The UI Layout C Class (UILayout.h)

[Previous] [Next]

Many of the sample applications in this book allow the user to resize the main window. Resizing the main window, of course, causes all the child controls to be repositioned or resized. The CUILayout C++ class, shown in Listing B-4, encapsulates all the child control reposition and resize logic.

Each application that supports a resizable main window will create a CUILayout object. In that window's Dlg_OnInitDialog function, the CUILayout object's Initialize method is called to set the parent window handle and the minimum width and height of the window. Then the CUILayout object's AnchorControl or AnchorControls methods are called repeatedly to identify each child control window and how that control should be anchored relative to its parent window.

When the main window executes its Dlg_OnSize function, it just needs to call the CUILayout object's AdjustControls method, passing it the width and height of the main window's client area. The AdjustControls method will automatically reposition and resize all the child controls so that they keep their relative position to the parent window.

When the main window executes its Dlg_OnGetMinMaxInfo function, it needs to call the CUILayout object's HandleMinMax method. This method sets the members of the MINMAXINFO structure so that the user cannot shrink the window too small and obscure any of the child controls.

Listing B-4. The UILayout.h header file

 

UILayout.h

/****************************************************************************** Module: UILayout.h Notices: Copyright (c) 2000 Jeffrey Richter Purpose: This class manages child window positioning and sizing when a parent window is resized. See Appendix B. ******************************************************************************/ #pragma once // Include this header file once per compilation unit /////////////////////////////////////////////////////////////////////////////// #include "..\CmnHdr.h" // See Appendix A. /////////////////////////////////////////////////////////////////////////////// class CUILayout { public: enum ANCHORPOINT { AP_TOPLEFT, AP_TOPMIDDLE, AP_TOPRIGHT, AP_MIDDLERIGHT, AP_BOTTOMRIGHT, AP_BOTTOMMIDDLE, AP_BOTTOMLEFT, AP_MIDDLELEFT, AP_CENTER }; public: void Initialize(HWND hwndParent, int nMinWidth = 0, int nMinHeight = 0); BOOL AnchorControl(ANCHORPOINT apUpperLeft, ANCHORPOINT apLowerRight, int nID, BOOL fRedraw = FALSE); BOOL AnchorControls(ANCHORPOINT apUpperLeft, ANCHORPOINT apLowerRight, BOOL fRedraw, ...); BOOL AdjustControls(int cx, int cy); void HandleMinMax(PMINMAXINFO pMinMax) { pMinMax->ptMinTrackSize = m_ptMinParentDims; } private: struct CONTROL { int m_nID; BOOL m_fRedraw; ANCHORPOINT m_apUpperLeft; ANCHORPOINT m_apLowerRight; POINT m_ptULDelta; POINT m_ptLRDelta; }; private: void PixelFromAnchorPoint(ANCHORPOINT ap, int cxParent, int cyParent, PPOINT ppt); private: CONTROL m_CtrlInfo[255]; // Max controls allowed in a dialog template int m_nNumControls; HWND m_hwndParent; POINT m_ptMinParentDims; }; /////////////////////////////////////////////////////////////////////////////// #ifdef UILAYOUT_IMPL /////////////////////////////////////////////////////////////////////////////// void CUILayout::Initialize(HWND hwndParent, int nMinWidth, int nMinHeight) { m_hwndParent = hwndParent; m_nNumControls = 0; if ((nMinWidth == 0) || (nMinHeight == 0)) { RECT rc; GetWindowRect(m_hwndParent, &rc); m_ptMinParentDims.x = rc.right - rc.left; m_ptMinParentDims.y = rc.bottom - rc.top; } if (nMinWidth != 0) m_ptMinParentDims.x = nMinWidth; if (nMinHeight != 0) m_ptMinParentDims.y = nMinHeight; } /////////////////////////////////////////////////////////////////////////////// BOOL CUILayout::AnchorControl(ANCHORPOINT apUpperLeft, ANCHORPOINT apLowerRight, int nID, BOOL fRedraw) { BOOL fOk = FALSE; try { { HWND hwndControl = GetDlgItem(m_hwndParent, nID); if (hwndControl == NULL) goto leave; if (m_nNumControls >= chDIMOF(m_CtrlInfo)) goto leave; m_CtrlInfo[m_nNumControls].m_nID = nID; m_CtrlInfo[m_nNumControls].m_fRedraw = fRedraw; m_CtrlInfo[m_nNumControls].m_apUpperLeft = apUpperLeft; m_CtrlInfo[m_nNumControls].m_apLowerRight = apLowerRight; RECT rcControl; GetWindowRect(hwndControl, &rcControl); // Screen coords of control // Convert coords to parent-relative coordinates MapWindowPoints(HWND_DESKTOP, m_hwndParent, (PPOINT) &rcControl, 2); RECT rcParent; GetClientRect(m_hwndParent, &rcParent); POINT pt; PixelFromAnchorPoint(apUpperLeft, rcParent.right, rcParent.bottom, &pt); m_CtrlInfo[m_nNumControls].m_ptULDelta.x = pt.x - rcControl.left; m_CtrlInfo[m_nNumControls].m_ptULDelta.y = pt.y - rcControl.top; PixelFromAnchorPoint(apLowerRight, rcParent.right, rcParent.bottom, &pt); m_CtrlInfo[m_nNumControls].m_ptLRDelta.x = pt.x - rcControl.right; m_CtrlInfo[m_nNumControls].m_ptLRDelta.y = pt.y - rcControl.bottom; m_nNumControls++; fOk = TRUE; } leave:; } catch (...) { } chASSERT(fOk); return(fOk); } /////////////////////////////////////////////////////////////////////////////// BOOL CUILayout::AnchorControls(ANCHORPOINT apUpperLeft, ANCHORPOINT apLowerRight, BOOL fRedraw, ...) { BOOL fOk = TRUE; va_list arglist; va_start(arglist, fRedraw); int nID = va_arg(arglist, int); while (fOk && (nID != -1)) { fOk = fOk && AnchorControl(apUpperLeft, apLowerRight, nID, fRedraw); nID = va_arg(arglist, int); } va_end(arglist); return(fOk); } /////////////////////////////////////////////////////////////////////////////// BOOL CUILayout::AdjustControls(int cx, int cy) { BOOL fOk = FALSE; // Create region consisting of all areas occupied by controls HRGN hrgnPaint = CreateRectRgn(0, 0, 0, 0); for (int n = 0; n < m_nNumControls; n++) { HWND hwndControl = GetDlgItem(m_hwndParent, m_CtrlInfo[n].m_nID); RECT rcControl; GetWindowRect(hwndControl, &rcControl); // Screen coords of control // Convert coords to parent-relative coordinates MapWindowPoints(HWND_DESKTOP, m_hwndParent, (PPOINT) &rcControl, 2); HRGN hrgnTemp = CreateRectRgnIndirect(&rcControl); CombineRgn(hrgnPaint, hrgnPaint, hrgnTemp, RGN_OR); DeleteObject(hrgnTemp); } for (n = 0; n < m_nNumControls; n++) { // Get control's upper/left position w/respect to parent's width/height RECT rcControl; PixelFromAnchorPoint(m_CtrlInfo[n].m_apUpperLeft, cx, cy, (PPOINT) &rcControl); rcControl.left -= m_CtrlInfo[n].m_ptULDelta.x; rcControl.top -= m_CtrlInfo[n].m_ptULDelta.y; // Get control's lower/right position w/respect to parent's width/height PixelFromAnchorPoint(m_CtrlInfo[n].m_apLowerRight, cx, cy, (PPOINT) &rcControl.right); rcControl.right -= m_CtrlInfo[n].m_ptLRDelta.x; rcControl.bottom -= m_CtrlInfo[n].m_ptLRDelta.y; // Position/size the control HWND hwndControl = GetDlgItem(m_hwndParent, m_CtrlInfo[n].m_nID); MoveWindow(hwndControl, rcControl.left, rcControl.top, rcControl.right - rcControl.left, rcControl.bottom - rcControl.top, FALSE); if (m_CtrlInfo[n].m_fRedraw) { InvalidateRect(hwndControl, NULL, FALSE); } else { // Remove the regions occupied by the control's new position HRGN hrgnTemp = CreateRectRgnIndirect(&rcControl); CombineRgn(hrgnPaint, hrgnPaint, hrgnTemp, RGN_DIFF); DeleteObject(hrgnTemp); // Make the control repaint itself InvalidateRect(hwndControl, NULL, TRUE); SendMessage(hwndControl, WM_NCPAINT, 1, 0); UpdateWindow(hwndControl); } } // Paint the newly exposed portion of the dialog box's client area HDC hdc = GetDC(m_hwndParent); HBRUSH hbrColor = CreateSolidBrush(GetSysColor(COLOR_3DFACE)); FillRgn(hdc, hrgnPaint, hbrColor); DeleteObject(hbrColor); ReleaseDC(m_hwndParent, hdc); DeleteObject(hrgnPaint); return(fOk); } /////////////////////////////////////////////////////////////////////////////// void CUILayout::PixelFromAnchorPoint(ANCHORPOINT ap, int cxParent, int cyParent, PPOINT ppt) { ppt->x = ppt->y = 0; switch (ap) { case AP_TOPMIDDLE: case AP_CENTER: case AP_BOTTOMMIDDLE: ppt->x = cxParent / 2; break; case AP_TOPRIGHT: case AP_MIDDLERIGHT: case AP_BOTTOMRIGHT: ppt->x = cxParent; break; } switch| (ap) { case AP_MIDDLELEFT: case AP_CENTER: case AP_MIDDLERIGHT: ppt->y = cyParent / 2; break; case AP_BOTTOMLEFT: case AP_BOTTOMMIDDLE: case AP_BOTTOMRIGHT: ppt->y = cyParent; break; } } /////////////////////////////////////////////////////////////////////////////// #endif // UILAYOUT_IMPL ///////////////////////////////// End of File /////////////////////////////////



Programming Server-Side Applications for Microsoft Windows 2000
Programming Server-Side Applications for Microsoft Windows 2000 (Microsoft Programming)
ISBN: 0735607532
EAN: 2147483647
Year: 2000
Pages: 126

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net