/*------------------------------------------------------------------------------*
 * File Name:ResizeDialog.h														*
 * Creation: CPY 6/12/2003														*
 * Purpose: OriginC Header file for basic dialog functions						*
 * Copyright (c) Originlab Corp. 2003, 2004, 2005, 2006, 						*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	DVT 8/1/03 TWO_GAPS_WHEN_BOTTOM_NULL										*
 *	CPY 9/13/03 PLOT_SETUP_PANEL_RESIZE_FROM_INSIDE_GRID						*
 *  Danice 3/31/04 ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT						*
 *  Danice 5/10/04 v8.0869 SUPPORT_BOTTOM_BUTTON_RESIZE							*
 *	CPY 5/18/04 v7.5844 ADD_IFDEF_TO_ALLOW_INCLUDE_TWICE						*
 *	CPY 5/27/04 NLFIT_MOVE_SHOW_GRID_CODE_CLEAN_UP								*
 *  Danice 9/12/04 v8.0132 NEW_WAY_SHOW_TOP_AND_BOTTOM_PANE						*
 *	Frank 11/10/04 v8.0160 QA70-6086   REMEMBER_LAST_USE_FUNCTION				*
 *  Danice 11/11/04 v8.0162 DLG_SIZE_CONSIGER_RIGHT_BOTTOM_BTN					*
 *  Danice 11/18/04 v8.0164 ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY				*
 *  Danice 11/22/04 v8.0166 ARRANGE_BUTTON_RIGHT_TO_LEFT						*
 *  DG 1/24/05 v8.0185 QA70-7345 POSITION_TOP_ITEM_WITHOUT_PANE					*
 *  DG 3/4/05 v8.0198 COL_PROPERTIES_MOVE_BTN_WHEN_HIDE							*
 *	CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW			*
 *	Frank 4/1/05	RISIZEDIG_SAVE_DLG_NAME_ON_INIT								*
 *  DG 4/2/05 v8.0214 MINI_SIZE_FOR_GETN_BOX									*
 *  DG 7/21/05 v8.0271 HIDDEN_BTN_MOVABLE										*
 *	Jasmine 02/22/06 ARRANGE_BOTTONS_CENTER_BOTTOM								*
 *	CPY 9/24/06 XF_PREVIEW_DLG_NEED_PREVIEW_ON_THE_SIDE							*
 *	Jasmine 10/25/06 REMEMBER_TOP_PANE_SIZE										*
 *	Jasmine 11/22/06 FIX_TOP_PANE_HEIGHT_REDUCE_BUG								*
 *	Sim 03-31-2007 RETURN_MAX_HEIGHT_OF_BTN										*
 *	EJP 2007-04-06 v8.0597 ALLOW_COPY_FROM_NLFIT_MESSAGE_LOG					*
 *	Jasmine 04/13/07 GET_CONTROL_SIZE_FROM_CONTENT								*
 *	Jasmine 04/20/07 OPTION_HIDDEN_BUTTON_NOT_IN_CAL							*
 *	Sim 07-31-2007 ARRANGE_BUTTON_AUTO_VERTICAL									*
 *	Folger Sim 11/02/07 FIX_MULTIPANE_DIALOG_RESIZE								*
 *	Folger 05/19/08 FIX_MULTIPANE_DIALOG_RESIZE_ERROR_WHEN_MINIMIZE_THEN_REOPEN	*
 *	Folger 08/07/08 QA80-11934 CORRECT_CALCULATION_ON_MULTIPANE_DIALOG_UP_DOWN_BUTTON_POSITION
 *	Folger 12/11/08 QA80-12764 v8.0985 MODIFY_PEAKS_IN_PA_DURING_CHANGE_PARAMETER_MAKE_ORIGIN_LOCK
 *	AW 01/15/09 MAKE_CHECKFORUPDATEMSG_DIALOG_RESIZABLE							*
 *	Kyle 06/23/2009 QA80-13831 SHOULD_LOAD_CHECK_BOX_SETTINGS_IN_OLD_ORDER_AND_THEN_CHANGE_IT_TO_NEW_ORDER
 *	Jasmine 07/16/09 #13952 HIDDEN_CONTROL_IS_IGNORED_IN_MOVING_AND_APPEAR_IN_BAD_POSITION
 *	TD 8-11-2009 QA80-14108 MORE_INFO_WHEN_ROLLUP_DDK_DIALOGS					*
 *	Hong 09/24/09 QA80-14350 NLFIT_DLG_NEED_HINT_TO_GUIDE_USER_MAKE_IT_MODALLESS*
 *	Hong 01/13/10 QA80-13590-P9 NLFIT_SUPPORT_BOLD_AND_RED_COLOR_FOR_ERR_MSG_IN_MSG_LOG
 *	Folger 07/06/10 ORG-436 BETTER_USE_OC_DEVICE_CONTEXT						*
 *	Folger 10/15/2010 ORG-1252 MULTIPANE_DIALOG_BAD_LAYOUT_IF_INVALID_PANE_HEIGHT_IN_REGISTRY
 *	Folger 10/26/2010 ORG-27 NEW_DIGITIZER_GADGET								*
 *------------------------------------------------------------------------------*/

#ifndef _RESIZE_DIALOG_H
#define _RESIZE_DIALOG_H

#include <Tree_utils.h>

#ifndef _RESIZE_CONTROL_H_
	#include "ResizeControl.h"
#endif //_RESIZE_CONTROL_H_

#define FACTOR_ORIG_TO_MIN  			0.8
#define MAX_NUM_CTRLS					50

///Danice 10/6/04 NEW_WAY_SHOW_TOP_AND_BOTTOM_PANE///Danice ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
enum {	BOTTOM_PANE, TOP_PANE, TOTAL_UPDOWN_BOTTON};
#define TOP_DOWN_BTN_GROUP_GAP			1		
///end
#define SPACE_BETWEEN_EACH_BTN_GROUP	2*GetControlGap()	//CPY 12/16/06 change from 3 to 2

enum{ PANEL_ORIENT_NONE, PANEL_ORIENT_VERTICAL, PANEL_ORIENT_HORIZONTAL };

#define MAX_ALLOWED_PANELS				5

#define	IDC_GROUP_GAP					-10000	///Joseph 12/11/06 ADD_BITMAP_BUTTON

//---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
class ResizeDialog;
class MoveControlsHelper
{
public:
	MoveControlsHelper(ResizeDialog* pDlg);
	~MoveControlsHelper();
	void Add(Control& btn, RECT& rr);
	bool GetClientRect(Control& btn, RECT& rr);
	//---- CPY 6/21/2006 FLEX_CNTRL_MOVE_SIZE_PROBLEM
	int Exclude(int nCntrlID);
	bool IsExclude(Control& btn);
	//----
private:
	bool	isInList(Control& btn, int& ii);
	ResizeDialog*	m_pDlg;
	int		m_nWnds;
	vector<uint> m_hWnds;
	RECT m_rects[MAX_NUM_CTRLS];
	vector<int> m_vnExcludeList; //---- CPY 6/21/2006 FLEX_CNTRL_MOVE_SIZE_PROBLEM
};
//---- end CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
	

class ResizeDialog : public Dialog
{
public:
	ResizeDialog(UINT nDlgID, LPCSTR lpcszDLL, BOOL bReserved = 0) :  Dialog(nDlgID, lpcszDLL)
	{
		
		m_bReady = false;
		
		//---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
		//m_bRepaintWhenMove = true;
		m_pMoveControlsHelper =NULL;
		//----
		/// TD 8-26-03 RESIZING
		m_bDoNotHandleOnSize = true;
		m_nNumPanels = 0;
		for(int ii = 0; ii < MAX_ALLOWED_PANELS; ii++)
		{
			m_parrPanels[ii] = NULL;
		}
		/// ----TD 8-26-03 RESIZING
	}
	void SetControlGap(int nEdge) {m_nEdge = nEdge;}
	void AddPanel(ResizeControl* pPanel)
	{
		m_parrPanels[m_nNumPanels++] = pPanel;
	}
	virtual string GetRuntimeClass()
	{
		return "ResizeDialog";
	}
	// return true only if was rolledUp and open
	BOOL ShowDialog(BOOL OpenIfRollup = true)
	{
		if(!m_wndDlg.Visible)
			m_wndDlg.Visible = true;
		
		if(OpenIfRollup)
		{
			if(IsRolledup())
			{
				Rollup(FALSE);
				return true;
			}
		}
		return false;
	}
	//---- CPY 2/15/2007 DLGSIZEINFO_CALL_NEED_PREV_SIZ
	void MoveDialogToCenter(SIZE& sz)
	{
		HWND hWndMain = GetWindow(OGW_MAIN);
		Window wndMain = hWndMain;
		RECT rectApp;
		wndMain.GetWindowRect(&rectApp);
		int nx = rectApp.left + RECT_WIDTH(rectApp)/2;
		int ny = rectApp.top + RECT_HEIGHT(rectApp)/2;
		nx -= sz.cx/2;
		ny -= sz.cy/2;
		if(nx < rectApp.left) nx = rectApp.left;
		if(ny < rectApp.top) ny = rectApp.top;
		RECT rDlg;
		rDlg.top = ny;
		rDlg.left = nx;
		rDlg.right = nx + sz.cx;
		rDlg.bottom = ny + sz.cy;
		MoveWindow(&rDlg);
	}
	//----
private:
	bool				m_bReady;	//CPY 5/22/05 moved from MultiPaneDlg, should really be in this class
	///Joseph 12/11/06	ADD_BITMAP_BUTTON
	int					m_nButtonGap;
	int					m_nGroupGap;
	vector<int>			m_vnGroupButtonWidth;
	vector<int>			m_vnEachGroupSize;
	///End ADD_BITMAP_BUTTON
protected:
	BOOL OnDestroy() {return true;} //CPY 2/16/05
	bool	IsInitReady() {return m_bReady;}
	void	SetInitReady(bool bSet = true) {m_bReady = bSet;}
	
	//------ Folger 12/11/08 QA80-12764 v8.0985 MODIFY_PEAKS_IN_PA_DURING_CHANGE_PARAMETER_MAKE_ORIGIN_LOCK
	BOOL		OnIsDialogRolledup(uint wParam, uint lParam)
	{
		bool*	pbIsRolledup = (bool*)wParam;
		*pbIsRolledup = IsRolledup();
		
		return TRUE;
	}
	//------ End MODIFY_PEAKS_IN_PA_DURING_CHANGE_PARAMETER_MAKE_ORIGIN_LOCK

	//---- CPY 9/6/03 v7.5686 RESIZEING_CLEAN_UP
	void SaveDlgHeight() { m_nDlgHight = GetDlgExtent();}

	BOOL OnResize(int nType, int cx, int cy) // return TRUE only if OnSize is enabled
	{
		if(m_bDoNotHandleOnSize)
		{
			//m_nDlgHight = cy;
			return FALSE;
		}
		resizePanelsOnDlgResize(cx, cy);
		return TRUE;
	}
	//---- CPY 9/13/03 PLOT_SETUP_PANEL_RESIZE_FROM_INSIDE_GRID
	// wParam = Panel index, 0 = wks List, 1 = col List, 3 = Plot List for example, this is the panel that we need to increase/decrease its height
	// lParam = LPARAM_RESIZE_CONTROLS_INCREASE, LPARAM_RESIZE_CONTROLS_DECREASE
	//
	BOOL OnIncreaseDecreasePanelSize(uint wParam, uint lParam)
	{
		bool bIncrease = LPARAM_RESIZE_CONTROLS_INCREASE == lParam? true:false;
		int nSizeDiff = 0;
		if(wParam < getNumOfPanels())
		{
			ResizeControl *pKeyPanel = m_parrPanels[wParam];
			if(!bIncrease || isDlgSmallerThenScreen(0, 0.9)) // simply decrease given panel
			{
				nSizeDiff = bIncrease? pKeyPanel->GetHeight() * (-0.75) : pKeyPanel->GetHeight() * 0.45;
				pKeyPanel->SetHeight(pKeyPanel->GetHeight() - nSizeDiff);
				return true;
			}
			// to increase, we will try not to increase the dialog since often there is no space to expand dialog
			// so we will need to grab space from other panels. To do this, we ask each panel how much it can give up
			// by comparing its current height and its GetMinHeight(true), so the extra is what we can add to the current (wParam) panel
			int nDiffs[MAX_ALLOWED_PANELS];
			int ii, ny, nTotal = 0;
			for(ii = 0; ii < getNumOfPanels(); ii++)
			{
				nDiffs[ii] = 0;
				if(wParam == ii)
					continue;
				if(m_parrPanels[ii]->IsVisible())
				{
					int ndiff = m_parrPanels[ii]->GetHeight() - m_parrPanels[ii]->GetMinHeight(true);
					if(ndiff < 0)
						ndiff = 0;
					nTotal += ndiff;
					nDiffs[ii] = ndiff;
				}
			}
			ny = pKeyPanel->GetHeight();
			int nn = pKeyPanel->GetMaxHeight(true);
			if(ny > nn)
				ny = nn;
			nSizeDiff = nTotal;
			if(0 == nSizeDiff || nSizeDiff > 0.4 * ny)
				nSizeDiff = 0.4 * ny;
			double factor = nSizeDiff / (double)nTotal;
			for(ii = 0; ii < getNumOfPanels(); ii++)
			{
				if(wParam == ii)
					continue;
				if(nDiffs[ii] > 0)
					m_parrPanels[ii]->SetHeight(m_parrPanels[ii]->GetHeight() - (0.5 + factor*nDiffs[ii])); 	
			}
			pKeyPanel->SetHeight(pKeyPanel->GetHeight() + nSizeDiff); 	
		}
		return TRUE;
	}
	//---- end PLOT_SETUP_PANEL_RESIZE_FROM_INSIDE_GRID
	virtual int GetTotalHeight(bool bMin = false) // by summing up each panels, assume vertical, need to modify if to support general
	{
		int nTotalHeight = 0;
		bool bAnyVisible = false;
		for(int ii = 0; ii < getNumOfPanels(); ii++)
		{
			if(m_parrPanels[ii]->IsVisible())
			{
				bAnyVisible = true;
				nTotalHeight += m_parrPanels[ii]->GetPanelHeight(bMin) + GetControlGap();
			}
		}
		if(bAnyVisible)
			nTotalHeight -= GetControlGap();
		
		return nTotalHeight;
	}
	virtual int GetTotalWidth(bool bGetMin = false)
	{
		int mx, nx = 0;
		for(int ii = 0; ii < getNumOfPanels(); ii++)
		{
			if(m_parrPanels[ii]->IsVisible())
			{
				mx = m_parrPanels[ii]->GetPanelWidth(true);
				if(GetPanelsOrientation() == PANEL_ORIENT_VERTICAL && mx > nx)
					nx = mx;
				else if(GetPanelsOrientation() == PANEL_ORIENT_HORIZONTAL)
					nx += mx; // + GetControlGap()
			}
		}
		return nx;
	}
	///Joseph 01/31/06 GET_DLG_OPTIMAL_SIZE
	virtual bool GetDlgOptimalSize(SIZE& sze){return false;}
	///End GET_DLG_OPTIMAL_SIZE
	///
public:
	///DG 4/2/05 MINI_SIZE_FOR_GETN_BOX
	//width and height have inlucded edge around
	void GetGroupTotalSize(uint nBtnIDs[], int &nWidth, int &nHeight, bool bHorizontal=true, int nGap = -1)
	{
		RECT rr;
		if(-1 == nGap)
			nGap=m_nEdge;
		
		nWidth=nGap;
		nHeight=nGap;
		for(int ii=0; nBtnIDs[ii]>0; ii++)
		{
			Control ctrl=GetItem(nBtnIDs[ii]);
			///Joseph 02/27/07 GET_WIDTH_HEIGHT_ON_VISIBLE
			//if the ctrl is not valid or not visible, then skip this ctrl
			//ctrl.GetClientRect(&rr);
			if(ctrl && ctrl.Visible)
				ctrl.GetClientRect(&rr);
			else
				continue;
			///End GET_WIDTH_HEIGHT_ON_VISIBLE
			if(bHorizontal)
			{
				nWidth+=RECT_WIDTH(rr)+nGap;
				int nCtrlHeight=RECT_HEIGHT(rr)+2*nGap;
				if(nCtrlHeight > nHeight)
					nHeight=nCtrlHeight;
			}
			else //vertical button
			{
				nHeight+=RECT_HEIGHT(rr)+nGap;
				int nCtrlWidth=RECT_WIDTH(rr)+2*nGap;
				if(nCtrlWidth > nWidth)
					nWidth=nCtrlWidth;
			}
		}
	}
	///end MINI_SIZE_FOR_GETN_BOX
	
	//---- end CPY 9/6/03 v7.5686 RESIZEING_CLEAN_UP
	//---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
	//	bool SetMoveRepaint(bool bRepaint = true)
	//	{
	//		bool bOldVal = m_bRepaintWhenMove;
	//		m_bRepaintWhenMove = bRepaint;
	//		return bOldVal;
	//	}
	void SetMoveControlsHelper(MoveControlsHelper* pHelper)
	{
		m_pMoveControlsHelper = pHelper;
	}
	void ShowControls(uint nButtonIDs[], bool bShow = true)
	{
		int ii = 0;
		while(nButtonIDs[ii] > 0)
		{
			Control btn = GetItem(nButtonIDs[ii]);
			if(btn)
				btn.Visible = bShow;
			
			ii++;
		}
	}
	//--- CPY 1/19/05
	void ShowControls(const vector<uint>& vn, bool bShow = true)
	{
		for(int ii = 0; ii < vn.GetSize(); ii++)
		{
			if(vn[ii])
			{
				Control btn = GetItem(vn[ii]);
				if(btn)
					btn.Visible = bShow;
			}
		}
	}
protected:
	void GetClientRect(Control& cc, RECT& rr);
	void MoveControl(Control& cc, RECT& rr);
	//---- end CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
	int GetDlgExtent(bool bVertial = true)
	{
		RECT r1;
		m_wndDlg.GetClientRect(&r1);
		return bVertial? r1.bottom : r1.right;
	}
	int GetControlGap() { return m_nEdge; }

	HWND	GetSafeHwnd()
	{
		return m_wndDlg.GetSafeHwnd();
	}	
	//---
	void EnableControls(uint nButtonIDs[], bool bEnable = true)
	{
		int ii = 0;
		while(nButtonIDs[ii] > 0)
		{
			Control btn = GetItem(nButtonIDs[ii]);
			if(btn)
				btn.Enable = bEnable;
			ii++;
		}
	}
	void CheckButtons(uint nButtonIDs[], bool bCheck = true)
	{
		int ii = 0;
		while(nButtonIDs[ii] > 0)
		{
			Button btn = GetItem(nButtonIDs[ii]);
			if(btn)
				btn.Check = bCheck;
			
			ii++;
		}
	}
	// use default gap if nGap < 0
public:
	// return the right most x position
	///Jasmine 07/16/09 #13952 HIDDEN_CONTROL_IS_IGNORED_IN_MOVING_AND_APPEAR_IN_BAD_POSITION 
	//int ArrangeControlsTopDown(uint nButtonIDs[], int nx, int ny, int nGap = -1, vector<int>& vnHeights = NULL, int nW = 0);
	int ArrangeControlsTopDown(uint nButtonIDs[], int nx, int ny, int nGap = -1, vector<int>& vnHeights = NULL, int nW = 0, bool bForceResize = false);
	///End HIDDEN_CONTROL_IS_IGNORED_IN_MOVING_AND_APPEAR_IN_BAD_POSITION
	
	///---Danice ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
	// use default gap if nGap < 0
	// return the left most x position
	int ArrangControlsDownTop(uint nButtonIDs[], int cx, int cy, int nGap = -1)
	{
		RECT rr, r1;
		rr.right = cx;
		rr.bottom = cy;
		if(nGap < 0)
			nGap = m_nEdge;
		int ii = 0;
		int nMaxWidth = 0;
		/// TD 3-2-05 QA70-7459 REPOSITION_WINDOWS_VECTOR
//		vector<uint> hWnds;
//		RECT rects[MAX_NUM_CTRLS];
//		int nWnds = 0;
		/// end REPOSITION_WINDOWS_VECTOR
		while(nButtonIDs[ii] > 0)
		{
			Control btn = GetItem(nButtonIDs[ii]);
			//if(btn && btn.Visible)	///DG 3/4/05 COL_PROPERTIES_MOVE_BTN_WHEN_HIDE
			if(btn)
			{
				//btn.GetWindowRect(&r1);
				GetClientRect(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
				if(nMaxWidth < RECT_WIDTH(r1))
					nMaxWidth = RECT_WIDTH(r1);
				rr.left = rr.right - nMaxWidth;
				rr.top = rr.bottom - RECT_HEIGHT(r1);
				/// TD 3-2-05 QA70-7459 REPOSITION_WINDOWS_VECTOR
				//btn.MoveWindow(&rr, m_bRepaintWhenMove);
//				hWnds.Add((uint)btn.GetSafeHwnd());
//				rects[nWnds++] = rr;
				MoveControl(btn, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
				/// end REPOSITION_WINDOWS_VECTOR

				rr.bottom = rr.top - nGap;
			}
			ii++;
		}
		/// TD 3-2-05 QA70-7459 REPOSITION_WINDOWS_VECTOR
//		SizeMoveChildWindows(hWnds, rects);
		/// end REPOSITION_WINDOWS_VECTOR
		return cx - nMaxWidth;
	}
	///---end ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
	
	//------------- CPY 11/10/05 PFM_DIALOG_IN_GRAPH_PANE
	// return position of top button - gap
	int ArrangeControlsBottomCenter(uint nButtonIDs[], int cx, int cy, int nGap = -1)
	{
		RECT rr, r1;
		rr.top = rr.bottom = cy - nGap;
		if(nGap < 0)
			nGap = m_nEdge;
		int ii = 0;
		while(nButtonIDs[ii] > 0)
		{
			Control btn = GetItem(nButtonIDs[ii]);
			if(btn && btn.Visible)
			{
				GetClientRect(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
				rr.left = (cx - RECT_WIDTH(r1))/2;
				rr.right = (cx + RECT_WIDTH(r1))/2;
				rr.top = rr.bottom - RECT_HEIGHT(r1);
				MoveControl(btn, rr); 
				rr.bottom = rr.top - nGap;
			}
			ii++;
		}
		return rr.top - nGap;
	}
	//------------- end CPY 11/10/05 PFM_DIALOG_IN_GRAPH_PANE
	
	///---Sim 07-31-2007 ARRANGE_BUTTON_AUTO_VERTICAL
	int ArrangeControlsCenterTop(uint nButtonIDs[], int cx, int cy, int nGap = -1, bool bCheckVisible = true, bool bAutoVertical = false)
	{
		if(nGap < 0)
			nGap = m_nEdge; 
		int nTotalWidth;
		Control btn;
		RECT rBtn;
		int ii;
		int nEndInLine;
		for(ii = 0, nEndInLine = 0; nButtonIDs[ii] > 0; ii++, nEndInLine++)
		{
			btn = GetItem(nButtonIDs[ii]);
			GetClientRect(btn, rBtn);
			if(btn && (!bCheckVisible || btn.Visible))
			{
				if ( bAutoVertical )
				{
					if ( ii > 0) // at least put one item on this line
						if ( nTotalWidth + RECT_WIDTH(rBtn) > cx ) // out of width of line
							break;
				}
				nTotalWidth = nTotalWidth + RECT_WIDTH(rBtn) + nGap;
			}
		}
		nTotalWidth -= nGap;
		
		int nTop = cy;
		
		nTop +=  nGap;
		
		int nLeft;
		nLeft = (cx - nTotalWidth)/2;
		
		int nMaxHeight = 0;
		for(ii = 0; ii < nEndInLine; ii++)
		{
			PositionControl(nButtonIDs[ii], nLeft, nTop, true, bCheckVisible);
			btn = GetItem(nButtonIDs[ii]);
			if ( btn )
			{
				if( bCheckVisible && !btn.Visible)
					continue;
				GetClientRect(btn, rBtn);
				if(nMaxHeight < RECT_HEIGHT(rBtn))
					nMaxHeight = RECT_HEIGHT(rBtn);
				nLeft = rBtn.right + nGap;
			}
		}
		nTop += nMaxHeight + nGap;
		
		if ( bAutoVertical && nButtonIDs[nEndInLine] > 0) // avoid to dead in recursion
			nTop = ArrangeControlsCenterTop(&nButtonIDs[nEndInLine], cx, nTop, nGap, bCheckVisible, bAutoVertical);
		
		return nTop;		
	}
	///---END ARRANGE_BUTTON_AUTO_VERTICAL
	
	///Jasmine 02/22/06 ARRANGE_BOTTONS_CENTER_BOTTOM
	//give dialog right and bottom position, 
	//arrange controls along the bottom of the dialog and in the middle.
	//return top - nGap
	///---Sim 07-31-2007 ARRANGE_BUTTON_AUTO_VERTICAL
	//int ArrangeControlsCenterBottom(uint nButtonIDs[], int cx, int cy, int nGap = -1, bool bCheckVisible = true)
	int ArrangeControlsCenterBottom(uint nButtonIDs[], int cx, int cy, int nGap = -1, bool bCheckVisible = true, bool bAutoVertical = false)
	///---END ARRANGE_BUTTON_AUTO_VERTICAL
	{
		if(nGap < 0)
			nGap = m_nEdge; 
		///---Sim 07-31-2007 ARRANGE_BUTTON_AUTO_VERTICAL
		//int nTotalWidth, nLeft, nBottom = cy - nGap;
		//int nMaxHeight = 0; ///---Sim 03-31-2007 RETURN_MAX_HEIGHT_OF_BTN
		int nTotalWidth;
		///---END ARRANGE_BUTTON_AUTO_VERTICAL
		Control btn;
		RECT rBtn;
		///---Sim 07-31-2007 ARRANGE_BUTTON_AUTO_VERTICAL
		//for(int ii = 0; nButtonIDs[ii] > 0; ii++)
		int ii;
		int nEndInLine;
		for(ii = 0, nEndInLine = 0; nButtonIDs[ii] > 0; ii++, nEndInLine++)
		///---END ARRANGE_BUTTON_AUTO_VERTICAL
		{
			btn = GetItem(nButtonIDs[ii]);
			GetClientRect(btn, rBtn);
			if(btn && (!bCheckVisible || btn.Visible))
			///---Sim 07-31-2007 ARRANGE_BUTTON_AUTO_VERTICAL
			{
				if ( bAutoVertical )
				{
					if ( ii > 0) // at least put one item on this line
						if ( nTotalWidth + RECT_WIDTH(rBtn) > cx ) // out of width of line
							break;
				}
			///---END ARRANGE_BUTTON_AUTO_VERTICAL
				nTotalWidth = nTotalWidth + RECT_WIDTH(rBtn) + nGap;
			}///---Sim 07-31-2007 ARRANGE_BUTTON_AUTO_VERTICAL
		}
		///---Sim 07-31-2007 ARRANGE_BUTTON_AUTO_VERTICAL
		nTotalWidth -= nGap;
		
		int nBottom = cy;
		if ( bAutoVertical && nButtonIDs[nEndInLine] > 0) // avoid to dead in recursion
			nBottom = ArrangeControlsCenterBottom(&nButtonIDs[nEndInLine], cx, nBottom, nGap, bCheckVisible, bAutoVertical);
		nBottom -=  nGap;
		
		int nLeft;
		//nLeft = (cx - nTotalWidth + nGap)/2;
		nLeft = (cx - nTotalWidth)/2;
		
		int nMaxHeight = 0; ///---Sim 03-31-2007 RETURN_MAX_HEIGHT_OF_BTN
		//for(ii = 0; nButtonIDs[ii] > 0; ii++)
		for(ii = 0; ii < nEndInLine; ii++)
		///---END ARRANGE_BUTTON_AUTO_VERTICAL
		{
			PositionControl(nButtonIDs[ii], nLeft, nBottom, false, bCheckVisible);
			btn = GetItem(nButtonIDs[ii]);
			///---Sim 03-31-2007 RETURN_MAX_HEIGHT_OF_BTN
			if ( btn )
			{
				/////Joseph 03/31/07 IGNORE_INVISIBLE_BUTTON_ON_RESIZE
				//if(!btn || !btn.Visible)
					//continue;
				/////End IGNORE_INVISIBLE_BUTTON_ON_RESIZE
				if( bCheckVisible && !btn.Visible)
					continue;
				GetClientRect(btn, rBtn);
				if(nMaxHeight < RECT_HEIGHT(rBtn))
					nMaxHeight = RECT_HEIGHT(rBtn);
				nLeft = rBtn.right + nGap;
			}
			///---END RETURN_MAX_HEIGHT_OF_BTN
		}
		///---Sim 03-31-2007 RETURN_MAX_HEIGHT_OF_BTN
		//return rBtn.top - nGap;
		return nBottom - nMaxHeight - nGap;
		///---END RETURN_MAX_HEIGHT_OF_BTN
	}
	///End ARRANGE_BOTTONS_CENTER_BOTTOM

	// starting from nx, ny as the top-right position, move controls one after another to
	// the left, nGap < 0 will use default gap between controls
	// return the lowest y position
	int ArrangeControlsRightLeft(uint nButtonIDs[], int nx, int ny, int nGap = -1)
	{
		RECT rr, r1;
		if(nGap < 0)
			nGap = m_nEdge;
		rr.right = nx - nGap;
		rr.top = ny;
		int ii = 0;
		int nMaxHeight = 0;
		while(nButtonIDs[ii] > 0)
		{
			Control btn = GetItem(nButtonIDs[ii]);
			if(btn && btn.Visible)
			{
				//btn.GetWindowRect(&r1);
				GetClientRect(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
				rr.left = rr.right - RECT_WIDTH(r1);
				if(nMaxHeight < RECT_HEIGHT(r1))
					nMaxHeight = RECT_HEIGHT(r1);
				rr.bottom = rr.top + RECT_HEIGHT(r1);
				//btn.MoveWindow(&rr, m_bRepaintWhenMove);
				MoveControl(btn, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW

				rr.right = rr.left - nGap;
			}
			ii++;
		}
		return ny + nMaxHeight;
	}
	// nButtonIDs must have 0 at the end
	// starting from nx, ny as the top-left position, move controls one after another to
	// the right, nGap < 0 will use default gap between controls
	// return the lowest y position
	int ArrangeControlsLeftRight(uint nButtonIDs[], int nx, int ny, int nGap = -1)
	{
		RECT rr, r1;
		if(nGap < 0)
			nGap = m_nEdge;
		rr.left = nx;
		rr.top = ny;
		int ii = 0;
		int nMaxHeight = 0;
		while(nButtonIDs[ii] > 0)
		{
			Control btn = GetItem(nButtonIDs[ii]);
			if(btn && btn.Visible)
			{
				//btn.GetWindowRect(&r1);
				GetClientRect(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
				rr.right = rr.left + RECT_WIDTH(r1);
				if(nMaxHeight < RECT_HEIGHT(r1))
					nMaxHeight = RECT_HEIGHT(r1);
				rr.bottom = rr.top + RECT_HEIGHT(r1);
				//btn.MoveWindow(&rr, m_bRepaintWhenMove);
				MoveControl(btn, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW

				rr.left = rr.right + nGap;
			}
			ii++;
		}
		return ny + nMaxHeight;
	}
	//------ CPY 10/1/04 QA70-6682 GETN_THEME_SAVEAS_NEW_DIALOG
	// starting from nx, ny as the top-left position, move controls one after another to
	// the right, nGap < 0 will use default gap between controls
	// return the lowest y position
	// if cx is given, then nIDStretch will be stretched to fill right most to cx location
	int 	ArrangeControlsLeftRight(uint nButtonIDs[], int nx, int ny, int cx, int nIDStretch, int nGap = -1);
	//------ end CPY 10/1/04 QA70-6682 GETN_THEME_SAVEAS_NEW_DIALOG
	///Jasmine 04/13/07 GET_CONTROL_SIZE_FROM_CONTENT
	void GetTextExtentSize(LPCSTR lpcsz, int* pnWidth = NULL, int* pnHeight = NULL)
	{
		SIZE sz;
		///------ Folger 07/06/10 ORG-436 BETTER_USE_OC_DEVICE_CONTEXT
		//DeviceContext	dc;

		//dc = m_wndDlg.GetDC();
		DeviceContext	dc(m_wndDlg);
		///------ End BETTER_USE_OC_DEVICE_CONTEXT
		sz = dc.GetTextExtent(lpcsz, lstrlen(lpcsz));
		if(pnWidth)
			*pnWidth = sz.cx;
		if(pnHeight)
			*pnHeight = sz.cy;
	}
	///End GET_CONTROL_SIZE_FROM_CONTENT
protected:
	// position nMainID as top-left and move nIDsRight group of controls to the far right and nIDsBottom to the left bottom
	//nIDsRight should be moved only horizontally, while nIDsBottom should be moved only vertically
	//nMainID should be resize right-bottom, while keeping top-left
	//cx is the right most x pixel
	//cy is the bottom y pixel
	// return height of nMainID
	int ResizeMoveControlsRightBottom(int nMainID, uint nRightIDs[], uint nBottomIDs[], int cx, int cy, int* lpnWidth = NULL)
	{
		int nRightGroupWidth = getControlGroupExtent(nRightIDs, true);
		int nBottomGroupHeight = getControlGroupExtent(nBottomIDs, false);
		int nRightGroupLeft = cx - m_nEdge - nRightGroupWidth;
		int	nBottomGroupTop = cy - m_nEdge - nBottomGroupHeight;
		RECT r1;
		r1.left = 0;
		if(nRightIDs && !GetControlClientRect(nRightIDs[0], r1))
			return false;
		int nRightGroupOffset = nRightGroupLeft - r1.left;
		r1.top = 0;
		if(nBottomIDs && !GetControlClientRect(nBottomIDs[0], r1))
			return false;
		int nBottomGroupOffset = nBottomGroupTop -  r1.top;
		
		Control cMain;
		if(!GetControlClientRect(nMainID, r1, &cMain))
			return false;
		
		//------ Folger 05/19/08 FIX_MULTIPANE_DIALOG_RESIZE_ERROR_WHEN_MINIMIZE_THEN_REOPEN
		if ( nRightGroupLeft < r1.left || nBottomGroupTop < r1.top )
		{
			if ( lpnWidth )
				*lpnWidth = -1;
			return -1;
		}
		//------
		
		r1.right = nRightGroupLeft;
		if(nRightIDs)
			r1.right-= m_nEdge;
		r1.bottom = nBottomGroupTop;
		if(nBottomIDs)
			r1.bottom -= m_nEdge;
		
		//cMain.MoveWindow(&r1, m_bRepaintWhenMove);
		MoveControl(cMain, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
		if(nRightIDs)
			MoveControls(nRightIDs, nRightGroupOffset, 0);
		if(nBottomIDs)
			MoveControls(nBottomIDs, 0, nBottomGroupOffset);
		if(lpnWidth)
			*lpnWidth = RECT_WIDTH(r1);
		
		return RECT_HEIGHT(r1);
	}
	//void MakeSameSize(uint nIDs[], bool bVert = true)	///Danice ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
	void MakeSameSize(uint nIDs[], bool bVert = true, int nSize=-1)
	{
		///---Danice ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
		/*
		RECT r0;
		Control btnRef = GetItem(nIDs[0]);
		btnRef.GetWindowRect(&r0);
		int ii=1;
		*/
		int ii;
		if(-1 == nSize)
		{
			RECT r0;
			Control btnRef = GetItem(nIDs[0]);
			//btnRef.GetWindowRect(&r0);
			GetClientRect(btnRef, r0); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW

			if(bVert)
				nSize=RECT_HEIGHT(r0);
			else
				nSize=RECT_WIDTH(r0);
			ii=1;
		}
		else
			ii=0;
		///---end ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
		while(nIDs[ii] > 0)
		{
			RECT r1;
			Control btn;
			if(GetControlClientRect(nIDs[ii], r1, &btn))
			{
				if(bVert)
					r1.bottom = r1.top + nSize; //RECT_HEIGHT(r0);
				else
					r1.right = r1.left + nSize; //RECT_WIDTH(r0);
				
				//btn.MoveWindow(&r1, m_bRepaintWhenMove); 
				MoveControl(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			}
			ii++;
		}
		return;
	}
	bool GetControlClientRect(uint nID, RECT& r1, Control* pCntrl = NULL)
	{
		Control btn;
		if(NULL == pCntrl)
			pCntrl = &btn;
			
		*pCntrl = GetItem(nID);
		if(*pCntrl)
		{
			//---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			//pCntrl->GetWindowRect(&r1);
			//m_wndDlg.ScreenToClient(&r1);
			GetClientRect(*pCntrl, r1);
			//----
			return true;
		}
		return false;
	}
	void MoveControls(uint nIDs[], int nDx, int nDy)
	{
		int ii = 0;
		while(nIDs[ii] > 0)
		{
			RECT r1;
			Control btn;
			if(GetControlClientRect(nIDs[ii], r1, &btn))
			{
				OffsetRect(&r1, nDx, nDy);
				//btn.MoveWindow(&r1, m_bRepaintWhenMove); 
				MoveControl(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			}
			ii++;
		}
	}
	//keep size moving
	//bLeftTopCorner=true, x and y are Left-Top corner;
	//bLeftTopCorner=false, x and y are Right-Bottom corner
	//return Control Height
	int MoveControl(uint nID, int x, int y, bool bLeftTopCorner=true, int* lpnWidth = NULL)
	{
		RECT rr;
		Control cc;
		if(GetControlClientRect(nID, rr, &cc))
		{
			int nWidth=RECT_WIDTH(rr), nHeight=RECT_HEIGHT(rr);
			if(bLeftTopCorner)
			{
				rr.left=x;
				rr.right=x+nWidth;
				rr.top=y;
				rr.bottom=y+nHeight;
			}
			else
			{
				rr.left=x-nWidth;
				rr.right=x;
				rr.top=y-nHeight;
				rr.bottom=y;
			}
			MoveControl(cc, rr);
			//---- CPY 1/2/2007 QA70-9168-P2 POPUP_MENU_FOR_COMMON_COL_CHOICES
			if(lpnWidth)
				*lpnWidth = nWidth;
			//----
			return nHeight;
		}
		return -1;
	}
	// return top
	int SizeControl(uint nID, int nW, int nH = -1)
	{
		RECT rr;
		Control btn;
		if(GetControlClientRect(nID, rr, &btn))
		{
			if(btn.Visible)
			{
				rr.right = rr.left + nW;
				if(nH > 0)
					rr.bottom = rr.top + nH;
				//btn.MoveWindow(&rr, m_bRepaintWhenMove);
				MoveControl(btn, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
				return rr.top;
			}
		}
		return -1;
	}
	// return top if bTop = false, return bottom if bTop = true
	int PositionControl(uint nID, int nx, int ny, bool bTop = true, bool bCheckVisible = true)
	{
		Control btn = GetItem(nID);
		int nRet = ny;
		if(btn && (!bCheckVisible || btn.Visible))
		{
			RECT rr, r1;
			//btn.GetWindowRect(&r1);
			GetClientRect(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			rr.left = nx;
			if(bTop)
			{
				rr.top = ny, rr.bottom = ny + RECT_HEIGHT(r1);
				nRet = rr.bottom;
			}
			else
			{
				rr.bottom = ny, rr.top = ny - RECT_HEIGHT(r1);
				nRet = rr.top;
			}
			rr.right = nx + RECT_WIDTH(r1);
			//btn.MoveWindow(&rr, m_bRepaintWhenMove);
			MoveControl(btn, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
		}
		return nRet;
	}
	///---Sim 07-31-2007 ARRANGE_BUTTON_AUTO_VERTICAL
	void PositionControlOffset(uint nID, int nOffset, int bVertical = true, bool bCheckVisible = true)
	{
		Control btn = GetItem(nID);
		if(btn && (!bCheckVisible || btn.Visible))
		{
			RECT rr;
			GetClientRect(btn, rr);
			if(bVertical)
			{
				rr.top += nOffset;
				rr.bottom += nOffset;
			}
			else
			{
				rr.left += nOffset;
				rr.right += nOffset;
			}
			MoveControl(btn, rr);
		}
	}
	///---END ARRANGE_BUTTON_AUTO_VERTICAL
	// return bottom of control
	int StretchControlWide(uint nID, int nx, int ny, int cx, int nGap = -1)
	{
		Control btn = GetItem(nID);
		if(nGap < 0)
			nGap = m_nEdge;
		if(btn && btn.Visible)
		{
			RECT rr, r1;
			//btn.GetWindowRect(&r1);
			GetClientRect(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			rr.left = nx;
			rr.top = ny;
			rr.right = cx - nGap;
			rr.bottom = ny + RECT_HEIGHT(r1);
			//btn.MoveWindow(&rr, m_bRepaintWhenMove);
			MoveControl(btn, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			ny = rr.bottom;
		}
		return ny;
	}
	// return right of control
	
	/// ---- CPY 9/6/03 v7.5686 RESIZEING_CLEAN_UP
	BOOL OnMinMaxInfo(int &nMinTrackX, int &nMinTrackY)
	{
		nMinTrackY = GetTotalHeight(true);
		nMinTrackX = GetTotalWidth(true);
		if(IsRolledup())
			nMinTrackY = 0;
			
		return TRUE;
	}
	virtual BYTE GetPanelsOrientation()
	{
		return PANEL_ORIENT_NONE;
	}
	void DisableOnSize(bool bDisable = true)
	{
		m_bDoNotHandleOnSize = bDisable;
	}
	bool MoveControlToBottomOfGroup(uint nGrpBoxID, uint nID, uint nIDItemAbove, int nHeight = 0)
	{
		RECT rGroup;
		Control btnGroup;
		if(!GetControlClientRect(nGrpBoxID, rGroup, &btnGroup))
			return false;
		RECT rAbove;
		GetControlClientRect(nIDItemAbove, rAbove);
		if(nID)
		{
			Control btn = GetItem(nID);
			RECT rr;
			rr = rGroup;
			rr.top = rAbove.bottom + m_nEdge;
			rr.bottom = rr.top + nHeight;
			//btn.MoveWindow(&rr);
			MoveControl(btn, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			rGroup.bottom = rr.bottom;
		}
		else
			rGroup.bottom = rAbove.bottom + m_nEdge;
		
		//btnGroup.MoveWindow(&rGroup);
		MoveControl(btnGroup, rGroup); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
		return true;
	}
	///Jasmine 10/25/06 REMEMBER_TOP_PANE_SIZE
	//move control to RightBottom of the dlg
	bool MoveControlToRightBottom(uint nID, int cy = 0, int cx = 0)
	{
		Control btn = GetItem(nID);
		if(!btn)
			return false;
		RECT rDlg, rrOld, rrNew;
		GetControlClientRect(nID, rrOld);
		m_wndDlg.GetClientRect(&rDlg);
		if(!cx)
			cx = RECT_WIDTH(rDlg);
		if(!cy)
			cy = RECT_HEIGHT(rDlg);		
		rrNew.right = cx - m_nEdge;
		rrNew.left = rrNew.right - RECT_WIDTH(rrOld);
		rrNew.bottom = cy - m_nEdge;
		rrNew.top = rrNew.bottom - RECT_HEIGHT(rrOld);
		MoveControl(btn, rrNew);
		return true;
	}
	///End REMEMBER_TOP_PANE_SIZE
	//----- CPY 9/24/06 XF_PREVIEW_DLG_NEED_PREVIEW_ON_THE_SIDE
	bool MoveControlToRight(uint nID, uint nIDItemLeft, int nWidth = 0)
	{
		Control btn = GetItem(nID);
		if(!btn)
			return false;
		if(0 == nWidth)
		{
			RECT rr;
			GetControlClientRect(nID, rr);
			nWidth = RECT_WIDTH(rr);
		}
		RECT rDlg;
		m_wndDlg.GetClientRect(&rDlg);
		int cy = RECT_HEIGHT(rDlg);
		RECT rLeft, rr;
		GetControlClientRect(nIDItemLeft, rLeft);
		rr.top = m_nEdge;
		rr.left = rLeft.right + m_nEdge;
		rr.right = rr.left + nWidth;
		rr.bottom = cy - m_nEdge;
		MoveControl(btn, rr);
		return true;
	}	
	//-----
	bool MoveControlToBottom(uint nID, uint nIDItemAbove, int nHeight = 0)
	{
		Control btn = GetItem(nID);
		if(!btn)
			return false;
		if(0== nHeight)
		{
			RECT rr;
			GetControlClientRect(nID, rr);
			nHeight = RECT_HEIGHT(rr);
		}
		RECT rDlg;
		m_wndDlg.GetClientRect(&rDlg);
		int cx = RECT_WIDTH(rDlg);
		RECT rAbove, rr;
		GetControlClientRect(nIDItemAbove, rAbove);
		rr.left = m_nEdge;
		rr.right = cx - m_nEdge;
		rr.top = rAbove.bottom + m_nEdge;
		rr.bottom = rr.top + nHeight;
		//btn.MoveWindow(&rr, m_bRepaintWhenMove);
		MoveControl(btn, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
		return true;
	}
	//---  CPY 5/27/04 NLFIT_MOVE_SHOW_GRID_CODE_CLEAN_UP
	// given a box(rect frame, or any control that is a box), position the control to
	// either top or bottom inside the box and stretch the width to fit width of box
	// rOther will contain the rect that is remained
	bool MoveStretchControlToTopOrBottom(uint nID, uint nIDBox, RECT& rOther, bool bToTopOfBox = true)
	{
		RECT rBox, rThis;
		Control cThis;
		if(!GetControlClientRect(nID, rThis, &cThis))
			return false;
		int nHeight = RECT_HEIGHT(rThis);
		
		Control cBox;
		if(!GetControlClientRect(nIDBox, rBox, &cBox))
			return false;
		rThis = rBox;
		rOther = rBox;
		if(bToTopOfBox)
			rOther.top = rThis.bottom = rThis.top + nHeight;//, rOther.top = rThis.bottom;// + 1;
		else
			rOther.bottom = rThis.top = rThis.bottom - nHeight;//, rOther.bottom = rThis.top;// -1;
		
		//cThis.MoveWindow(&rThis, m_bRepaintWhenMove);
		MoveControl(cThis, rThis); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
		return true;
	}
	//---

	/**
	bRight = true, move nID to align with bottom of nIDBottom and right of nIDRight,
	bRight = false, move nID to align with bottom of nIDRight and right of nIDBottom
	*/
	///Danice 10/05/04 NEW_WAY_SHOW_TOP_AND_BOTTOM_PANE
	//bool MoveControlToBottomRight(uint nID, uint nIDBottom, uint nIDRight, bool bRight = true)
	//return dialog height, which consider nIDBottom as dialog bottom control
	int MoveControlToBottomRight(uint nIDs[], uint nIDBottom, uint nIDRight, bool bRight = true, bool bAllowRightLarger=false)	///Danice ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
	{
		Control btn = GetItem(nIDs[0]);
		if(!btn)
			return 0;
		
		RECT rb, rr;
		int nHeight;
		///Danice 3/31/04 ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT
		if(bRight)
		{
			GetControlClientRect(nIDBottom, rb);
			GetControlClientRect(nIDRight, rr);
			nHeight=RECT_HEIGHT(rb);
		}
		else
		{
			GetControlClientRect(nIDBottom, rr);
			GetControlClientRect(nIDRight, rb);
			//nHeight=RECT_HEIGHT(rr);	///DG 8/17/05 : sometimes there is theme group in top of dialog
			nHeight = rr.bottom-GetControlGap();
			
			///Danice ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY : nlfit needed
			if(bAllowRightLarger && nIDs[1]>0)	//care only when more than 1 btn
			{
				RECT rbtn;
				GetControlClientRect(nIDs[0], rbtn);
				//------ Folger 08/07/08 QA80-11934 CORRECT_CALCULATION_ON_MULTIPANE_DIALOG_UP_DOWN_BUTTON_POSITION
				//int nbottom=rb.bottom-RECT_HEIGHT(rb)/2+RECT_HEIGHT(rbtn);
				int nbottom=rb.bottom-(RECT_HEIGHT(rb)-1)/2+RECT_HEIGHT(rbtn);
				//------
				if(nbottom > rb.bottom)
					rb.bottom=nbottom;
			}
			///end ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
		}
		///END ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT
		/*
		RECT r1;
		GetControlClientRect(nID, r1);
		RECT r2;
		r2.bottom = rb.bottom;
		r2.top = r2.bottom - RECT_HEIGHT(r1);
		r2.right = rr.right;
		r2.left = r2.right - RECT_WIDTH(r1);
		btn.MoveWindow(&r2, m_bRepaintWhenMove);
		*/
		///---Danice ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
		/*
		RECT r1, r2;
		for(int ii=0; 0<nIDs[ii]; ii++)
		{
			btn=GetItem(nIDs[ii]);
			if(!btn)
				continue;
			btn.GetWindowRect(&r1);
			r2.bottom = rb.bottom;
			r2.top = r2.bottom - RECT_HEIGHT(r1);
			r2.right = rr.right;
			r2.left = r2.right - RECT_WIDTH(r1);
			btn.MoveWindow(&r2, m_bRepaintWhenMove);
			
			if(bRight)
				rb.bottom=r2.top-m_nEdge;
			else
				rr.right =r2.left-m_nEdge;
		}
		*/
		ArrangControlsDownTop(nIDs, rr.right, rb.bottom, TOP_DOWN_BTN_GROUP_GAP);
		///---end ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
		return nHeight;
	}
	///end NEW_WAY_SHOW_TOP_AND_BOTTOM_PANE
	int StretchControlHeight(uint nID, int nx, int ny, int cy, int nGap = -1)
	{
		Control btn = GetItem(nID);
		if(nGap < 0)
			nGap = m_nEdge;
		if(btn && btn.Visible)
		{
			RECT rr, r1;
			//btn.GetWindowRect(&r1);
			GetClientRect(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			rr.left = nx;
			rr.top = ny;
			rr.right = nx + RECT_WIDTH(r1);
			rr.bottom = cy - nGap;
			//btn.MoveWindow(&rr, m_bRepaintWhenMove);
			MoveControl(btn, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			nx = rr.right;
		}
		return nx;
	}
	int StretchControlLeftRight(uint nIDLeft, int nIDRight, int nx, int ny, int cx, int nGap = -1)
	{
		Control btnLeft = GetItem(nIDLeft);
		Control btnRight = GetItem(nIDRight);
		if(nGap < 0)
			nGap = m_nEdge;

		RECT rr,r1;
		int ncxReduction = 0, ny1 = 0;
		if(btnRight && btnRight.Visible)
		{
			//btnRight.GetWindowRect(&r1);
			GetClientRect(btnRight, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			ncxReduction = RECT_WIDTH(r1);
			rr.right = cx - nGap;
			rr.left = rr.right - RECT_WIDTH(r1);
			rr.top = ny;
			rr.bottom = ny + RECT_HEIGHT(r1);
			//btnRight.MoveWindow(&rr, m_bRepaintWhenMove);
			MoveControl(btnRight, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			ny1 = rr.bottom;
		}
		cx -= ncxReduction;	
			
		if(btnLeft && btnLeft.Visible)
		{
			//btnLeft.GetWindowRect(&r1);
			GetClientRect(btnLeft, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			rr.left = nx;
			rr.top = ny;
			rr.right = cx - nGap;
			rr.bottom = ny + RECT_HEIGHT(r1);
			//btnLeft.MoveWindow(&rr, m_bRepaintWhenMove);
			MoveControl(btnLeft, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			ny = rr.bottom;
		}
		return ny > ny1? ny:ny1;
	}
		
	// return the gap between controls that might be used by caller
	// for repositioning of other controls
	///Jasmine 04/20/07 OPTION_HIDDEN_BUTTON_NOT_IN_CAL
	///Joseph 12/11/06 ADD_BITMAP_BUTTON
	//// bRight = true for arrange along the right edge, = false will arrange along bottom
	////int ArrangeMainItemAndControls(uint nButtonIDs[], uint nMainItemID, bool bRight = true, int cx = 0, int cy = 0)	///Danice DLG_SIZE_CONSIGER_RIGHT_BOTTOM_BTN
	//int ArrangeMainItemAndControls(uint nButtonIDs[], uint nMainItemID, uint nRightBottomIDs[], bool bRight = true, int cx = 0, int cy = 0)
	//int ArrangeMainItemAndControls(uint nButtonIDs[], uint nMainItemID, uint nRightBottomIDs[], bool bRight = true, int cx = 0, int cy = 0, int nButtonGap = -1, int nGroupButtonGap = -1)
	int ArrangeMainItemAndControls(uint nButtonIDs[], uint nMainItemID, uint nRightBottomIDs[], bool bRight = true, int cx = 0, int cy = 0, int nButtonGap = -1, int nGroupButtonGap = -1, bool bForceResize = true)
	///End	ADD_BITMAP_BUTTON
	///End OPTION_HIDDEN_BUTTON_NOT_IN_CAL
	{
		int nLeft;		///Danice 3/31/04 ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT
		RECT r1, r2;
		m_wndDlg.GetClientRect(&r1);
		if(0==cx)
			cx = RECT_WIDTH(r1);
		if(0==cy)
			cy = RECT_HEIGHT(r1);
		
		nLeft = r1.left;	///Danice 3/31/04 ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT
		
		
		/// AW 01/15/09 MAKE_CHECKFORUPDATEMSG_DIALOG_RESIZABLE
		if ( nButtonIDs[0] <= 0 )
			return 0;
		/// END MAKE_CHECKFORUPDATEMSG_DIALOG_RESIZABLE
		
		Button btn1 = GetItem(nButtonIDs[0]);
		//btn1.GetWindowRect(&r1);
		GetClientRect(btn1, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW

		int nBtnWidth = r1.right - r1.left;
		///Danice ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY : count the max btn height
		//int nBtnHeight= r1.bottom - r1.top;
		int nBtnHeight= r1.bottom - r1.top;
		if(nRightBottomIDs && nRightBottomIDs[1] > 0)
		{
			RECT rtemp;
			GetControlClientRect(nRightBottomIDs[0], rtemp);
			int nUpDownBtnHeight=RECT_HEIGHT(rtemp)*TOTAL_UPDOWN_BOTTON + TOP_DOWN_BTN_GROUP_GAP*(TOTAL_UPDOWN_BOTTON-1);
			if(nBtnHeight < nUpDownBtnHeight)
				nBtnHeight=nUpDownBtnHeight;
		}
		///end ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
		int nEdge = m_nEdge;
		
		Control cMainItem;
		if(!GetControlClientRect(nMainItemID, r1, &cMainItem))
			return -1;

		if(bRight)
		{
			r1.bottom = cy - nEdge;
			r1.right = cx - nBtnWidth - 2*nEdge;
		}
		else
		{
			r1.right = cx - nEdge;
			r1.bottom = cy - nBtnHeight - 2*nEdge;
		}
		RECT rMain;
		rMain = r1;
		
		int ii = 0;
		if(bRight)
		{
			r2.left = r1.right + nEdge;
			r2.top = nEdge;
			r2.right = r2.left + nBtnWidth;
			r2.bottom = r2.top + nBtnHeight;
		}
		else
		{
			///Danice 3/31/04 ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT
			r2.top = r1.bottom + nEdge;;
			r2.right = cx - nEdge;
			r2.left = r2.right - nBtnWidth;
			r2.bottom = cy - nEdge;
			/*
			r2.top = r1.bottom + nEdge;
			r2.left = nLeft + nEdge;
			r2.right = r2.left + nBtnWidth;
			r2.bottom = cy - nEdge;
			*/
			///END ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT
		}
		
		///Danice ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT : move up from bottom
		///---Danice DLG_SIZE_CONSIGER_RIGHT_BOTTOM_BTN
		if(nRightBottomIDs && !bRight)
		{
			Control btn = GetItem(nRightBottomIDs[0]);
			//btn.GetWindowRect(&r1);
			GetClientRect(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW

			r2.right = r2.right - (RECT_WIDTH(r1)+SPACE_BETWEEN_EACH_BTN_GROUP);	//skip updown btn width
			///Danice ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
			if(nRightBottomIDs[1] > 0)	//more than one button, diff way to show
			{
				RECT rtemp;
				//btn1.GetWindowRect(&rtemp);
				GetClientRect(btn1, rtemp); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
				r2.top=r2.top+RECT_HEIGHT(r1)-RECT_HEIGHT(rtemp)/2;	//Button snap to the middle of Updown button
				r2.bottom = r2.top+RECT_HEIGHT(rtemp);
			}
			///end ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
		}
		///---end DLG_SIZE_CONSIGER_RIGHT_BOTTOM_BTN
		///end ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT
		/// TD 3-2-05 QA70-7459 REPOSITION_WINDOWS_VECTOR
//		vector<uint> hWnds;
//		RECT rects[MAX_NUM_CTRLS];
//		int nWnds = 0;
		/// end REPOSITION_WINDOWS_VECTOR
		
		ii=0;
		///Joseph 12/11/06 ADD_BITMAP_BUTTON
		int nGroupGap = nEdge;
		if(nButtonGap > 0)
			nEdge = nButtonGap;
		if(nGroupButtonGap > 0)
			nGroupGap = nGroupButtonGap;
		vector<int> vnGroupButtonWidth;
		vector<int> vnEachGroupSize;
		int nButtonBeginIndex = -1;
		///End	ADD_BITMAP_BUTTON
		while(nButtonIDs[ii] > 0)
		{
			Control btn = GetItem(nButtonIDs[ii]);
			///Joseph 12/11/06 ADD_BITMAP_BUTTON
			if(IDC_GROUP_GAP == nButtonIDs[ii])
			{
				if(bRight)
					r2.top = r2.top + nGroupGap - nEdge;
				else
					r2.right = r2.right - nGroupGap + nEdge;
				vnGroupButtonWidth.Add(RECT_WIDTH(r1));
				vnEachGroupSize.Add(ii - nButtonBeginIndex - 1);
				nButtonBeginIndex = ii;
			}
			///End	ADD_BITMAP_BUTTON
			
			///Joseph 04/12/07 HIDDEN_BUTTON_NOT_IN_CAL
			//we should not calculate the hidden button size
			/*
			//if(btn && btn.Visible)	///DG 7/21/05 HIDDEN_BTN_MOVABLE : hidden control in XYZ2Mat dialog, need to move again when show so change this
			if(btn)
			*/
			///End HIDDEN_BUTTON_NOT_IN_CAL
			if(btn && (bForceResize || btn.Visible))//if(btn && btn.Visible)	///Jasmine 04/20/07 OPTION_HIDDEN_BUTTON_NOT_IN_CAL
			{
				//btn.GetWindowRect(&r1);
				GetClientRect(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
				//hWnds.Add((uint)btn.GetSafeHwnd());/// TD 3-2-05 QA70-7459 REPOSITION_WINDOWS_VECTOR
				if(bRight)
				{
					r2.bottom = r2.top + RECT_HEIGHT(r1);
					
					//btn.MoveWindow(&r2, m_bRepaintWhenMove);
					//rects[nWnds++] = r2;/// TD 3-2-05 QA70-7459 REPOSITION_WINDOWS_VECTOR
					MoveControl(btn, r2); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
					r2.top = r2.bottom + nEdge;
				}
				else
				{
					///Danice 3/31/04 ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT
					r2.left = r2.right - RECT_WIDTH(r1);
					
					//btn.MoveWindow(&r2, m_bRepaintWhenMove);
					//rects[nWnds++] = r2;/// TD 3-2-05 QA70-7459 REPOSITION_WINDOWS_VECTOR
					MoveControl(btn, r2); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
					r2.right = r2.left - nEdge;
					/*
					r2.right = r2.left + RECT_WIDTH(r1);
					btn.MoveWindow(&r2, m_bRepaintWhenMove);
					r2.left = r2.right + nEdge;
					*/
					///END ARRANGE_BOTTOM_BUTTON_FROM_LEFT_TO_RIGHT
				}
				

			}
			ii++;
		}
		///Joseph 12/11/06 ADD_BITMAP_BUTTON
		vnGroupButtonWidth.Add(RECT_WIDTH(r1));
		vnEachGroupSize.Add(ii - nButtonBeginIndex - 1);
		SetButtonAndGroupInfo(nEdge, nGroupGap, vnGroupButtonWidth, vnEachGroupSize); 
		///End ADD_BITMAP_BUTTON
		/// TD 3-2-05 QA70-7459 REPOSITION_WINDOWS_VECTOR
		//SizeMoveChildWindows(hWnds, rects);
		/// end REPOSITION_WINDOWS_VECTOR

		///Danice ARRANGE_BUTTON_RIGHT_TO_LEFT
		if(nRightBottomIDs && bRight)
		{
			Control btn = GetItem(nRightBottomIDs[0]);
			//btn.GetWindowRect(&r1);
			GetClientRect(btn, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
			r2.top=r2.top+(RECT_HEIGHT(r1)+nEdge);
		}
		///end ARRANGE_BUTTON_RIGHT_TO_LEFT
		if(bRight && r2.bottom > rMain.bottom)
			rMain.bottom = r2.bottom;
		///Danice SUPPORT_BOTTOM_BUTTON_RESIZE
		else if(!bRight && r2.right > rMain.right)
			rMain.right = r2.right;
		///END SUPPORT_BOTTOM_BUTTON_RESIZE
		//---- CPY 1/15/05 XF_DLG_CODE_CLEANUP
		//cMainItem.MoveWindow(&rMain, m_bRepaintWhenMove);
		PositionTopPaneMainItem(cMainItem, rMain, cx, nMainItemID);
		//----
		return nEdge;
	}
	
	///DG 1/24/05 POSITION_TOP_ITEM_WITHOUT_PANE
	bool PositionTopPane(int cx, int cy);
	///end POSITION_TOP_ITEM_WITHOUT_PANE
	
	//---- CPY 1/15/05 XF_DLG_CODE_CLEANUP
	//cMainItem.MoveWindow(&rMain, m_bRepaintWhenMove);
	virtual bool GetTopPaneControls(vector<uint>& vnTopDownIDs, vector& vdHeightRatios) {return false;}
	virtual void PositionTopPaneMainItem(Control& cMainItem, RECT& rMain, int cx, uint nMainItemID);
	//----
	///CPY 04/02/08 OPTION_TO_AUTOSIZE_GETPOINTSDIALOG move Jake 04/29/07 RESIZE_CUSTOM_BUTTONS_SIZE from DynaDlg.h
	// return height
	int ResizeControlWidth(Control btn, int nEdge = -1, bool bGrowOnly = true)
	{
		if(nEdge < 0)
			nEdge = m_nEdge;
		
		string strBText = btn.Text;
		int nWidth;
		int ny = btn.Measure(strBText,&nWidth,true);
		RECT rr;
        GetClientRect(btn, rr);
        int nNewWidth = nWidth + nEdge;
        if(!bGrowOnly || nNewWidth > RECT_WIDTH(rr))
        	rr.right += (nNewWidth - RECT_WIDTH(rr));
        else
        	return ny;
        
		MoveControl(btn, rr);
		return ny;
	}
	///end RESIZE_CUSTOM_BUTTONS_SIZE

	//---- CPY 9/24/06 XF_PREVIEW_DLG_NEED_PREVIEW_ON_THE_SIDE
	void ResizeDlgToRightOfControl(int nID, bool bAlsoBottom = false, bool bChildWinDlg = false)
	{
		RECT r1, rtDlg;
		m_wndDlg.GetWindowRect(&rtDlg);
		m_wndDlg.ScreenToClient(&rtDlg);
		Control cc = GetItem(nID);
		GetClientRect(cc, r1); 		
		rtDlg.right = r1.right + m_nEdge;
		//------ CPY 04/02/08 OPTION_TO_AUTOSIZE_GETPOINTSDIALOG
		//	m_wndDlg.ClientToScreen(&rtDlg);
		if(bAlsoBottom)
			rtDlg.bottom = r1.bottom + m_nEdge;
		if(!bChildWinDlg)
			m_wndDlg.ClientToScreen(&rtDlg);
		else // move to top-left, this is a temp solution, will need to look into this more later
			OffsetRect(&rtDlg, -rtDlg.left, -rtDlg.top);
		//------
		
		m_wndDlg.MoveWindow(&rtDlg);
	}
	//----
	void ResizeDlgToBottomOfControl(int nID, bool bToTop=false)
	{
		RECT r1, rtDlg;
		m_wndDlg.GetWindowRect(&rtDlg);
		m_wndDlg.ScreenToClient(&rtDlg);
		Control cc = GetItem(nID);
		//cc.GetWindowRect(&r1);
		//m_wndDlg.ScreenToClient(&r1);
		GetClientRect(cc, r1); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
		
		//---- CPY 5/27/04 NLFIT_MOVE_SHOW_GRID_CODE_CLEAN_UP
		//rtDlg.bottom = r1.bottom + r1.left; // assume item is next to edge so can use left as gap to bottom
		///Danice NEW_WAY_SHOW_TOP_AND_BOTTOM_PANE
		///rtDlg.bottom = r1.bottom + m_nEdge;
		///Jasmine 11/22/06 FIX_TOP_PANE_HEIGHT_REDUCE_BUG
		RECT rWindow;
		m_wndDlg.GetClientRect(&rWindow);
		if(!bToTop)
		{
			int nBottomHeight=rWindow.bottom-rtDlg.bottom;
			rtDlg.bottom = r1.bottom + m_nEdge + abs(nBottomHeight);
		}
		else
		{
			int nTitleHeight=rWindow.top-rtDlg.top;
			rtDlg.top = r1.top - m_nEdge - nTitleHeight;
		}
		///End FIX_TOP_PANE_HEIGHT_REDUCE_BUG
		///end NEW_WAY_SHOW_TOP_AND_BOTTOM_PANE
		//----
		m_wndDlg.ClientToScreen(&rtDlg);	
		m_wndDlg.MoveWindow(&rtDlg);
	}
	///Danice NEW_WAY_SHOW_TOP_AND_BOTTOM_PANE
	void MoveControlToTop(int nID, int nIDItemBottom, int nHeight=0)
	{
		RECT rr, rBottom, rDlg;
		Control cc = GetItem(nID);
		if(0 == nHeight)
		{
			GetControlClientRect(nID, rr);
			nHeight = RECT_HEIGHT(rr);
		}
		m_wndDlg.GetClientRect(&rDlg);
		GetControlClientRect(nIDItemBottom, rBottom);
		rr.left=rBottom.left;
		rr.right=rDlg.right;
		rr.top=rBottom.top-m_nEdge-nHeight;
		rr.bottom=rBottom.top-m_nEdge;
		//cc.MoveWindow(&rr, m_bRepaintWhenMove);
		MoveControl(cc, rr); //---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW

	}
	//uRightBtnIDs has 2 updown button
	void RepositionControls(int nMainID, uint uButtonIDs[], uint uRightBtnIDs[], int nBottomID)
	{
		Control cMain=GetItem(nMainID);
		Control cBottom=GetItem(nBottomID);
		RECT r1, r2, r3;
		int nx, ny, cx, cy;
		m_wndDlg.GetClientRect(&r1);
		if(cMain && cMain.Visible)
		{
			nx=r1.left+m_nEdge;
			ny=r1.top+m_nEdge;
			cx=r1.right;
			int nBottom=StretchControlWide(nMainID, nx, ny, cx);
			StretchControlHeight(nBottomID, nx, ny, r1.bottom);
			r1.top=nBottom+m_nEdge;
		}
		else
		{
			r1.top+=m_nEdge;
		}
		r1.left+=m_nEdge;
		
		ny=r1.top;
		cx=r1.right-m_nEdge;
		///Danice ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
		/*
		r1.top=ArrangeControlsLeftRight(uButtonIDs, nx, ny);
		ArrangeControlsRightLeft(uRightBtnIDs, cx, ny);
		*/
		GetControlClientRect(uRightBtnIDs[0], r2);
		int nTotalHeight=TOTAL_UPDOWN_BOTTON*RECT_HEIGHT(r2)+TOP_DOWN_BTN_GROUP_GAP;
		nx=ArrangControlsDownTop(uRightBtnIDs, cx, ny+nTotalHeight, TOP_DOWN_BTN_GROUP_GAP);
		
		GetControlClientRect(uButtonIDs[0], r3);
		int nBtnY=ny+RECT_HEIGHT(r2)-RECT_HEIGHT(r3)/2;
		ArrangeControlsRightLeft(uButtonIDs, nx-SPACE_BETWEEN_EACH_BTN_GROUP, nBtnY);
		ny+=nTotalHeight;
		///end ARRANGE_TWO_SHOW_PANE_BUTTON_NEW_WAY
		
		if(cBottom && cBottom.Visible)
		{
			ny+=m_nEdge;cy=r1.bottom;nx=r1.left;
			StretchControlWide(nBottomID, nx, ny, cx);
			StretchControlHeight(nBottomID, nx, ny, cy);
		}
	}
	///end
	
	//nRefID to be used to measure the gap between controls, m_nEdge
	///Frank 4/1/05	RISIZEDIG_SAVE_DLG_NAME_ON_INIT	
	//BOOL OnInitDialog(int nRefID = 0)
	BOOL OnInitDialog(int nRefID = 0, LPCSTR lpcszDlgName = NULL)
	{
		m_bReady = false;
		m_strRegSectionCheckBoxesName = lpcszDlgName;
	///End	RISIZEDIG_SAVE_DLG_NAME_ON_INIT	
		m_wndDlg = GetWindow();
		m_nEdge = GetSystemMetrics(SM_CXSIZEFRAME);
		if(nRefID)
		{
			RECT r1;
			if(GetControlClientRect(nRefID, r1))
				m_nEdge = r1.left;
		}
		SaveDlgHeight();//--- CPY 9/6/03 v7.5686 RESIZEING_CLEAN_UP
		return TRUE;
	}
	void UpdateWindow(bool bInvalidate = true)
	{
		if(bInvalidate)
			InvalidateRect(GetSafeHwnd(), NULL, TRUE);
		UpdateWindow(GetSafeHwnd());
	}
	// OnSystemCommand command to Rollup and RollDown Dialogs using minimize buttons
	// To call this function add 	ON_SYSCOMMAND(OnSystemCommand) in the drived class
	bool OnSystemCommand(int nCmd)
	{
		if( SC_MINIMIZE == nCmd)
		{
			BOOL bClose = !IsRolledup();
			/// TD 8-11-2009 QA80-14108 MORE_INFO_WHEN_ROLLUP_DDK_DIALOGS
			if(bClose)
			{
				if ( OM_RETURN_NOT_PRESENT == OptionalMessageStatus("NLFitMinimizeToModalless") ) /// Hong 09/24/09 QA80-14350 NLFIT_DLG_NEED_HINT_TO_GUIDE_USER_MAKE_IT_MODALLESS
					OptionalMessage("ClickMinimizeToRollDown", MB_OK);
			}
			/// end MORE_INFO_WHEN_ROLLUP_DDK_DIALOGS
			Rollup(bClose);
			return FALSE;
		}
		if(SC_MAXIMIZE == nCmd)
		{
			if(IsRolledup())
			{
				Rollup(FALSE);
				return FALSE;
			}
		}
		
		return TRUE;
	}

	///------ Folger 10/26/2010 ORG-27 NEW_DIGITIZER_GADGET
	BOOL	InitRadioBitmapButton(int nBtnID, int nBmpID, int nStates = 1, vector<string>* pvsTips = NULL, int nBmpSliceWidth = 16)
	{
		BitmapRadioButton btn = GetItem(nBtnID);
		if ( !btn )
			return FALSE;

		vector<string> vsTips;
		if ( pvsTips )
			vsTips = *pvsTips;
		return btn.Init(nStates, nBmpID, nBmpSliceWidth, vsTips);
	}
	///------ End NEW_DIGITIZER_GADGET

private:
	// x y factor, ignore if = 0
	// otherwise compare with screen after using factor as ratio
	bool isDlgSmallerThenScreen(double xFactor, double yFactor)
	{
		bool bXSmaller = xFactor == 0 || xFactor * GetSystemMetrics(SM_CXSCREEN) > GetDlgExtent(false) ? true:false;
		bool bYSmaller = yFactor == 0 || yFactor * GetSystemMetrics(SM_CYSCREEN) > GetDlgExtent(true) ? true:false;
		return bXSmaller && bYSmaller ? true:false;
	}
	/////////// checkbox and save/restore
	///Kyle 06/23/2009 QA80-13831 SHOULD_LOAD_CHECK_BOX_SETTINGS_IN_OLD_ORDER_AND_THEN_CHANGE_IT_TO_NEW_ORDER
	/*
	void rememberCheckBoxes(LPCSTR lpcszDlgName, int nID1, int nID2 = 0, int nID3 = 0, int nID4 = 0, int nID5 = 0, int nID6 = 0, int nID7 = 0, int nID8 = 0)
	{
		m_strRegSectionCheckBoxesName = lpcszDlgName;
		m_vnCheckBoxIDs.SetSize(0);
		m_vnCheckBoxIDs.Add(nID1);
		if(nID2)
		{
			m_vnCheckBoxIDs.Add(nID2);
			if(nID3)
			{
				m_vnCheckBoxIDs.Add(nID3);
				if(nID4)
				{
					m_vnCheckBoxIDs.Add(nID4);
					if(nID5)
					{
						m_vnCheckBoxIDs.Add(nID5);
						if(nID6)
						{
							m_vnCheckBoxIDs.Add(nID6);
							if(nID7)
							{
								m_vnCheckBoxIDs.Add(nID7);
								if(nID8)
									m_vnCheckBoxIDs.Add(nID8);
							}
						}
					}
				}
						
			}
		}
	}
	*/
	///End SHOULD_LOAD_CHECK_BOX_SETTINGS_IN_OLD_ORDER_AND_THEN_CHANGE_IT_TO_NEW_ORDER
	// width and height of a group of controls
	// based on [0] item
	int getControlGroupExtent(uint nIDs[], bool bWidth)
	{
		if(NULL == nIDs)
			return 0;
		
		int nCntrlID = nIDs[0];
		if(nCntrlID)
		{
			Control cntrl = GetItem(nCntrlID);
			if(cntrl)
			{
				RECT rect;
				cntrl.GetWindowRect(&rect);
				if(bWidth)
					return RECT_WIDTH(rect);
				else
					return RECT_HEIGHT(rect);
			}
		}
		return 0;
	}
	//---- CPY 9/6/03 v7.5686 RESIZEING_CLEAN_UP
	int getNumOfPanels()
	{
		return m_nNumPanels;
	}
	bool resizePanelsOnDlgResize(int cx, int cy)
	{
		if(m_bDoNotHandleOnSize)
			return false;

		BYTE bOrient = GetPanelsOrientation();
		int  nExpand = 0;
		if(bOrient == PANEL_ORIENT_VERTICAL)
			nExpand = cy - m_nDlgHight;
		else
		{
			return false; // later, other orientation
		}
		if(0 == nExpand)
			return true;
		int  nDenom = 0;
		int nSizeDiff[MAX_ALLOWED_PANELS];
		int	nOldHeight[MAX_ALLOWED_PANELS];
		for(int ii = 0; ii < getNumOfPanels(); ii++)
		{
			nSizeDiff[ii] = m_parrPanels[ii]->IsResize(nExpand > 0?true:false)? 1:0;
			nOldHeight[ii] = m_parrPanels[ii]->GetHeight();
			if(nSizeDiff[ii])
				nDenom += nOldHeight[ii];
		}
		if(nDenom <= 0)
			return false; // nothing to do
		double dDenom = nDenom;
		for(ii = 0; ii < getNumOfPanels(); ii++)
		{
			if(nSizeDiff[ii])
				nSizeDiff[ii] = nExpand * nOldHeight[ii]/dDenom;
		} 
		for(ii = 0; ii < getNumOfPanels(); ii++)
		{
			if(nSizeDiff[ii])
			{
				if(PANEL_ORIENT_VERTICAL == bOrient)
					m_parrPanels[ii]->SetHeight(nOldHeight[ii] + nSizeDiff[ii]); 
				else
				{
					// later, other orientation
				}
			}
		}
		return true;
	}
	//---- end CPY 9/6/03 v7.5686 RESIZEING_CLEAN_UP
			
protected:
	///Kyle 06/23/2009 QA80-13831 SHOULD_LOAD_CHECK_BOX_SETTINGS_IN_OLD_ORDER_AND_THEN_CHANGE_IT_TO_NEW_ORDER
	// change the method from Private to Protected so that Dlg can reset the IDs order in derived class if the order change from version to version
	void RememberCheckBoxes(LPCSTR lpcszDlgName, int nID1, int nID2 = 0, int nID3 = 0, int nID4 = 0, int nID5 = 0, int nID6 = 0, int nID7 = 0, int nID8 = 0)
	{
		m_strRegSectionCheckBoxesName = lpcszDlgName;
		m_vnCheckBoxIDs.SetSize(0);
		m_vnCheckBoxIDs.Add(nID1);
		if(nID2)
		{
			m_vnCheckBoxIDs.Add(nID2);
			if(nID3)
			{
				m_vnCheckBoxIDs.Add(nID3);
				if(nID4)
				{
					m_vnCheckBoxIDs.Add(nID4);
					if(nID5)
					{
						m_vnCheckBoxIDs.Add(nID5);
						if(nID6)
						{
							m_vnCheckBoxIDs.Add(nID6);
							if(nID7)
							{
								m_vnCheckBoxIDs.Add(nID7);
								if(nID8)
									m_vnCheckBoxIDs.Add(nID8);
							}
						}
					}
				}
						
			}
		}
	}
	///End SHOULD_LOAD_CHECK_BOX_SETTINGS_IN_OLD_ORDER_AND_THEN_CHANGE_IT_TO_NEW_ORDER

	void LoadCheckBoxSettings(LPCSTR lpcszDlgName, int nID1, int nID2 = 0, int nID3 = 0, int nID4 = 0, int nID5 = 0, int nID6 = 0, int nID7 = 0, int nID8 = 0)
	{
		///Kyle 06/23/2009 QA80-13831 SHOULD_LOAD_CHECK_BOX_SETTINGS_IN_OLD_ORDER_AND_THEN_CHANGE_IT_TO_NEW_ORDER
		//rememberCheckBoxes(lpcszDlgName, nID1, nID2, nID3, nID4, nID5, nID6, nID7, nID8);
		RememberCheckBoxes(lpcszDlgName, nID1, nID2, nID3, nID4, nID5, nID6, nID7, nID8);
		///End SHOULD_LOAD_CHECK_BOX_SETTINGS_IN_OLD_ORDER_AND_THEN_CHANGE_IT_TO_NEW_ORDER
		
		if(m_vnCheckBoxIDs.GetSize() > 0 && !m_strRegSectionCheckBoxesName.IsEmpty())
		{
			vector<byte> vbCheckSettings;
			if(load_default_checkboxes(m_strRegSectionCheckBoxesName, vbCheckSettings))
			{
				bool bCheck;
				for(int ii = 0; ii < m_vnCheckBoxIDs.GetSize(); ii++)
				{
					if(ii < vbCheckSettings.GetSize())
						bCheck = vbCheckSettings[ii];
					else
						bCheck = false;
					
					Button btnCheck = m_wndDlg.GetDlgItem(m_vnCheckBoxIDs[ii]);
					if(btnCheck)
						btnCheck.Check = bCheck;
				}
			}
		}
	}
	void SaveSizeOfPanels()
	{
		for(int ii = 0; ii < getNumOfPanels(); ii++)
		{
			string strClassName 	= m_parrPanels[ii]->GetRuntimeClass();
			SaveSetting(strClassName, m_parrPanels[ii]->GetHeight());
		}
	}
	void LoadSizeOfPanels()
	{
		for(int ii = 0; ii < getNumOfPanels(); ii++)
		{
			string strClassName 	= m_parrPanels[ii]->GetRuntimeClass();
			int nDefaultSize 	= m_parrPanels[ii]->GetHeight(true);
				
			m_parrPanels[ii]->SetHeight(LoadSetting(strClassName, nDefaultSize));
		}
		
		m_bDoNotHandleOnSize = false;// OK to allow OnSize handling now
	}
	void SaveCheckBoxSettings()
	{
		if(m_vnCheckBoxIDs.GetSize() > 0 && !m_strRegSectionCheckBoxesName.IsEmpty())
		{
			vector<byte> vbCheckSettings;
			bool bCheck = false;
			for(int ii = 0; ii < m_vnCheckBoxIDs.GetSize(); ii++)
			{
				Button btnCheck = m_wndDlg.GetDlgItem(m_vnCheckBoxIDs[ii]);
				if(btnCheck)
					bCheck = btnCheck.Check;
				else
					bCheck = false;
				vbCheckSettings.Add(bCheck);
			}
			save_default_checkboxes(m_strRegSectionCheckBoxesName, vbCheckSettings);
		}
	}
	// if called after LoadCheckBoxSettings, can skip lpcszDlgName
	///------ Folger 10/15/2010 ORG-1252 MULTIPANE_DIALOG_BAD_LAYOUT_IF_INVALID_PANE_HEIGHT_IN_REGISTRY
	//DWORD LoadSetting(LPCSTR lpcszValName, DWORD dwDefault = 0, LPCSTR lpcszDlgName = NULL)
	DWORD LoadSetting(LPCSTR lpcszValName, DWORD dwDefault = 0, LPCSTR lpcszDlgName = NULL, BOOL* pbSuccessfullyLoadFromReg = NULL)
	///------ End MULTIPANE_DIALOG_BAD_LAYOUT_IF_INVALID_PANE_HEIGHT_IN_REGISTRY
	{
		string strSecName = lpcszDlgName;//lpcszValName;//CPY 5/26/04 v7.5878 FO_FUNC_PREVIEW_IMPROVEMENT
		if(strSecName.IsEmpty())
			strSecName = m_strRegSectionCheckBoxesName;
		
		///------ Folger 10/15/2010 ORG-1252 MULTIPANE_DIALOG_BAD_LAYOUT_IF_INVALID_PANE_HEIGHT_IN_REGISTRY
		if ( pbSuccessfullyLoadFromReg )
			*pbSuccessfullyLoadFromReg = TRUE;
		///------ End MULTIPANE_DIALOG_BAD_LAYOUT_IF_INVALID_PANE_HEIGHT_IN_REGISTRY
		DWORD dwVal = dwDefault;
		if(dlg_load_registry(strSecName, lpcszValName, dwVal))
			return dwVal;
		
		///------ Folger 10/15/2010 ORG-1252 MULTIPANE_DIALOG_BAD_LAYOUT_IF_INVALID_PANE_HEIGHT_IN_REGISTRY
		if ( pbSuccessfullyLoadFromReg )
			*pbSuccessfullyLoadFromReg = FALSE;
		///------ End MULTIPANE_DIALOG_BAD_LAYOUT_IF_INVALID_PANE_HEIGHT_IN_REGISTRY
		return dwDefault;
	}
	void SaveSetting(LPCSTR lpcszValName, DWORD dwVal, LPCSTR lpcszDlgName = NULL)
	{
		string strSecName = lpcszDlgName;//lpcszValName;//CPY 5/26/04 v7.5878 FO_FUNC_PREVIEW_IMPROVEMENT
		if(strSecName.IsEmpty())
			strSecName = m_strRegSectionCheckBoxesName;
		
		dlg_save_to_registry(strSecName, lpcszValName, dwVal);
	}
	///Frank 11/10/04 v8.0160 QA70-6086   REMEMBER_LAST_USE_FUNCTION
	//Add two more function to save and load string to and from reg.
	//--- CPY 2/11/05 NO_REASON_TO_RETURN_LPCSTR
	//LPCSTR LoadSetting(LPCSTR lpcszValName, string &strVal , LPCSTR lpcszDlgName = NULL)
	bool LoadSetting(LPCSTR lpcszValName, string &strVal , LPCSTR lpcszDlgName = NULL)
	{
		string strSecName = lpcszDlgName;
		if(strSecName.IsEmpty())
			strSecName = m_strRegSectionCheckBoxesName;
		
		if(dlg_load_registry(strSecName, lpcszValName, strVal))
			return true;
		
		return false;
	}
	void SaveSetting(LPCSTR lpcszValName, LPCSTR lpcstrVal = NULL, LPCSTR lpcszDlgName = NULL)
	{
		string strSecName = lpcszDlgName;
		if(strSecName.IsEmpty())
			strSecName = m_strRegSectionCheckBoxesName;
		
		dlg_save_to_registry(strSecName, lpcszValName, lpcstrVal);
	}
	///End  REMEMBER_LAST_USE_FUNCTION
	
	///Joseph 12/11/06	ADD_BITMAP_BUTTON  
	///Jasmine 05/21/07 SET_WHEN_TOP_PANE_HIDE
	void SetButtonAndGroupInfo(uint nButtonIDs[], int nButtonGap = -1, int nGroupButtonGap = -1)
	{
		RECT rr;
		int ii, nButtonBeginIndex = -1;
		vector<int> vnGroupButtonWidth;
		vector<int> vnEachGroupSize;
		while(nButtonIDs[ii] > 0)
		{
			Control btn = GetItem(nButtonIDs[ii]);
			if(btn)
				GetClientRect(btn, rr);
			if(IDC_GROUP_GAP == nButtonIDs[ii])
			{
				vnGroupButtonWidth.Add(RECT_WIDTH(rr));
				vnEachGroupSize.Add(ii - nButtonBeginIndex - 1);
				nButtonBeginIndex = ii;
			}
			ii++;
		}
		vnGroupButtonWidth.Add(RECT_WIDTH(rr));
		vnEachGroupSize.Add(ii - nButtonBeginIndex - 1);
		SetButtonAndGroupInfo(nButtonGap > 0? nButtonGap : m_nEdge, nGroupButtonGap > 0? nGroupButtonGap : m_nEdge, vnGroupButtonWidth, vnEachGroupSize); 
	}
	///End SET_WHEN_TOP_PANE_HIDE
	//get and set the buttongap
	void SetButtonAndGroupInfo(int nButtonGap, int nGroupGap, const vector<int>& vnGroupButtonWidth, const vector<int>& vnEachGroupSize)
	{
		m_nButtonGap = nButtonGap;
		m_nGroupGap = nGroupGap;
		m_vnGroupButtonWidth = vnGroupButtonWidth;
		m_vnEachGroupSize = vnEachGroupSize;
	}
	bool GetButtonAndGroupInfo(int& nButtonGap, int& nGroupGap, vector<int>& vnGroupButtonWidth, vector<int>& vnEachGroupSize)
	{
		nButtonGap = m_nButtonGap;
		nGroupGap = m_nGroupGap;
		vnGroupButtonWidth = m_vnGroupButtonWidth;
		vnEachGroupSize = m_vnEachGroupSize;
		if(m_vnGroupButtonWidth.GetSize() != m_vnEachGroupSize.GetSize())
			return false;
		return true;
	}
	///End ADD_BITMAP_BUTTON
	
	//------ Folger Sim 11/02/07 FIX_MULTIPANE_DIALOG_RESIZE
	int GetWindowTitleHeight()
	{
		RECT rtDlg;
		m_wndDlg.GetWindowRect(&rtDlg);
		m_wndDlg.ScreenToClient(&rtDlg);
		
		RECT rWindow;
		m_wndDlg.GetClientRect(&rWindow);
		
		return (rWindow.top-rtDlg.top);
	}
	//------ END 11/02/07 FIX_MULTIPANE_DIALOG_RESIZE
	
private:
	int				m_nEdge;
	vector<uint>	m_vnCheckBoxIDs; // connect to registry
	string			m_strRegSectionCheckBoxesName;// for saving and reading bits
	//---- CPY 3/20/05 QA70-7459 CENTRALIZED_MOVE_CONTROL_WITH_BETTER_REDRAW
	//bool			m_bRepaintWhenMove;
	MoveControlsHelper*	m_pMoveControlsHelper;
	//----
	/// ---- TD 8-26-03 RESIZING
	bool	m_bDoNotHandleOnSize;	
	int		m_nDlgHight;
	int		m_nNumPanels;
	ResizeControl *m_parrPanels[MAX_ALLOWED_PANELS];	/// ---- TD 8-26-03 RESIZING
	/// ----
protected:
	Window	m_wndDlg;
	ToolBar	m_toolbar; //CPY 1/7/05 ADD_TOOLBAR_TO_DIALOG
	bool	InitToolBar(int nToolbarID, int nDlgCntrlID = 0);
	int		GetToolBarHeight();
};

//---- CPY 1/15/05 moved here from NLFit
///Frank 11/12/04 v8.0162  ADD_FUNCTION_FILE_PANE
class RichEditEx : public RichEdit
{
public:
	bool SaveSelection(LPCSTR lpcszFilename)
	{
		string strFilename(lpcszFilename);
		if( strFilename.IsEmpty() )
			return false;
		
		file ff(strFilename,file::modeCreate | file::modeReadWrite | file::typeText);
		if(ff.IsOpen())
		{
			string 	strText = GetSelText();
			int 	nSize = strText.GetLength();
			char* 	pText = strText.GetBuffer(nSize);
			ff.Write(pText, nSize);
			strText.ReleaseBuffer();
			ff.Close();
			return true;
		}		
		return false;
	}
	void SetWindowStyle(DWORD dwStyle, int nOffset = GWL_STYLE, bool bAddBits = true)
	{
		HWND hWnd = GetSafeHwnd();
		DWORD dwOldStyle = dwStyle;
		if(bAddBits)
		{
			dwOldStyle = GetWindowLong(hWnd, nOffset);
			dwOldStyle |= dwStyle;
		}
		SetWindowLong(hWnd, nOffset, dwOldStyle);
	}
	string GetText(long nBegin, long nEnd)
	{
		string strText;
		long nSelBegin, nSelEnd;
		GetSel(nSelBegin, nSelEnd); //restore the original selection		
		
		SetSel(nBegin, nEnd);	//select the text that want to get	
		strText = GetSelText(); //get selected text
		
		SetSel(nSelBegin, nSelEnd);	//select the original section back	
		
		return strText;
	}
};

// base class for message log
class OperationLog : public OperationLogBase
{
public:
	OperationLog() 
	{
		m_nOperationCount= 1;
	}
	virtual void Init(int nCntrlID, Dialog& dlg)
	{
		m_nOperationCount = 1;
		m_reOperationLog = dlg.GetItem(nCntrlID);
		
		/// EJP 2007-04-06 v8.0597 ALLOW_COPY_FROM_NLFIT_MESSAGE_LOG
		// The log should be made read-only by setting RichEdit ctrl to
		// read-only instead of handling ON_KEY events.
		m_reOperationLog.SetReadOnly(TRUE);
		/// end ALLOW_COPY_FROM_NLFIT_MESSAGE_LOG
	}
	virtual void	Reset(  bool bResetCounter = true  )
	{
		m_reOperationLog.Reset();
		if(bResetCounter)
			ResetCounter();
	}
	virtual void ResetCounter()
	{
		m_nOperationCount = 1;
	}
	virtual int WriteSeparator(bool bShowCounter = true, bool bAddNewLine = false )
	{
		if(bShowCounter)
		{
			string	strSeparator =  "(" + m_nOperationCount + ") ";
			Write(strSeparator);
		}

		if(bAddNewLine)
			WriteLine();
		return m_nOperationCount++;
	}
	virtual		void	WriteLine(LPCSTR lpcstr = NULL)
	{
		Write(lpcstr);
		string	strReturn = "\r\n";
		Write(strReturn);
	}
	/// Hong 01/13/10 QA80-13590-P9 NLFIT_SUPPORT_BOLD_AND_RED_COLOR_FOR_ERR_MSG_IN_MSG_LOG
	//virtual		void	Write(LPCSTR lpcstr)
	virtual		void	Write(LPCSTR lpcstr, BOOL* pbBold = NULL, COLORREF* pcrTextClr = NULL)
	/// end NLFIT_SUPPORT_BOLD_AND_RED_COLOR_FOR_ERR_MSG_IN_MSG_LOG
	{
		/// Hong 01/13/10 QA80-13590-P9 NLFIT_SUPPORT_BOLD_AND_RED_COLOR_FOR_ERR_MSG_IN_MSG_LOG
		CHARFORMAT		cf;
		bool			bCFChanged = false;
		if ( pbBold || pcrTextClr )
		{
			m_reOperationLog.GetDefaultCharFormat(cf);
			BOOL		bCurrBold = (cf.dwEffects & CFE_BOLD) ? TRUE : FALSE;
			if ( pbBold && *pbBold != bCurrBold )
			{
				bCFChanged = true;
				if ( *pbBold )
				{
					O_ADD_BIT(cf.dwEffects, CFE_BOLD);
					O_ADD_BIT(cf.dwMask, CFM_BOLD);
				}
				else
				{
					O_REMOVE_BIT(cf.dwEffects, CFE_BOLD);
					O_REMOVE_BIT(cf.dwMask, CFM_BOLD);
				}
			}
			COLORREF		crCurrTextClr = cf.crTextColor;
			if ( pcrTextClr && *pcrTextClr != crCurrTextClr )
			{
				bCFChanged = true;
				O_REMOVE_BIT(cf.dwEffects, CFE_AUTOCOLOR);
				O_ADD_BIT(cf.dwMask, CFM_COLOR);
				cf.crTextColor = *pcrTextClr;
			}
		}
		
		int				nStart = 0;
		if ( bCFChanged )
		{
			nStart = m_reOperationLog.LineIndex(m_reOperationLog.GetLineCount() - 1);
			nStart += m_reOperationLog.LineLength(nStart);
		}
		/// end NLFIT_SUPPORT_BOLD_AND_RED_COLOR_FOR_ERR_MSG_IN_MSG_LOG
		m_reOperationLog.Write(lpcstr);
		/// Hong 01/13/10 QA80-13590-P9 NLFIT_SUPPORT_BOLD_AND_RED_COLOR_FOR_ERR_MSG_IN_MSG_LOG
		if ( bCFChanged )
		{
			int			nEnd = m_reOperationLog.LineIndex(m_reOperationLog.GetLineCount() - 1);
			nEnd += m_reOperationLog.LineLength(nEnd);
			int			nSelStart, nSelEnd;
			m_reOperationLog.GetSel(nSelStart, nSelEnd);
			m_reOperationLog.SetSel(nStart, nEnd);
			m_reOperationLog.SetSelectionCharFormat(cf);
			m_reOperationLog.SetSel(nSelStart, nSelEnd);
		}
		/// end NLFIT_SUPPORT_BOLD_AND_RED_COLOR_FOR_ERR_MSG_IN_MSG_LOG
	}
	
private:	
	RichEditEx		m_reOperationLog;
	int				m_nOperationCount;
};

///End  ADD_FUNCTION_FILE_PANE


#endif //_RESIZE_DIALOG_H

