www.pudn.com > mod_rssim6.zip > Resizer.h
/******************************************************************************\ $Copyright: (C)2001 Dmitry Kochin$Workfile: Resizer.h $ \******************************************************************************/ // Resizer.h: interface for the CResizer class. // ////////////////////////////////////////////////////////////////////// // Class to correctly move child windows after parent window was resized // Created: 06/07/01 by dukei@ ////////////////////////////////////////////////////////////////////// //An idea: // //Each child window side (left, top, right and bottom) is connected to a side of another window, //so called relative window. It is tipically dialog window, that owns the child window. //When dialog window is resized, child window sides are moved after the relative window, //preserving the connections. // //Typical usage: // // 1. CResizer m_resizer is member variable; // // 2. Add the following code to OnInitDialog() // (replacing control IDs to your specific ones). // See array format description later in the comment // // static CResizer::CBorderInfo s_bi[] = { // {IDC_CONTROL_ID, {CResizer::eFixed, IDC_MAIN, CResizer::eLeft}, //Left side // {CResizer::eFixed, IDC_MAIN, CResizer::eTop}, //Top side // {CResizer::eFixed, IDC_MAIN, CResizer::eLeft}, //Right side // {CResizer::eFixed, IDC_MAIN, CResizer::eTop}}, //Bottom side // {IDC_STATIC_ID, {CResizer::eFixed, IDC_MAIN, CResizer::eLeft}, // {CResizer::eFixed, IDC_MAIN, CResizer::eTop}, // {CResizer::eFixed, IDC_MAIN, CResizer::eRight}, // {CResizer::eFixed, IDC_MAIN, CResizer::eTop}}, // }; // const nSize = sizeof(s_bi)/sizeof(s_bi[0]); // m_resizer.Init(m_hWnd, NULL, s_bi, nSize); // // 3. Add the following code to OnSize() handler // // m_resizer.Move(); // // 4. Everything should work now // // P.S. Data array format consists of one or more CBorderInfo structures, which contains // moved control ID (first field) and four CBorder structures, // for left, top, right and bottom sides of moved control accordingly. // // The main difficulty is to understand CBorder structure, which has the following format: // // { , , // } // // CResizer::eFixed CResizer::eLeft // CResizer::eProportional IDC_MAIN CResizer::eTop // or {CResizer::eWidth , IDC_ANOTHER_CONTROL_ID , CResizer::eRight } // CResizer::eHeight CResizer::eBottom // CResizer::eXCenter // CResizer::eYCenter // // For example, {CResizer::eFixed, IDC_MAIN, CResizer::eLeft} means, that moved control side is // on the fixed distance (CResizer::eFixed) from left side (CResizer::eLeft) of dialog window (IDC_MAIN) // // Another example: {CResizer::eProportional, IDC_CONTROL_ID, CResizer::eLeft} means, that // moved control side preserves relation (proportionaly) (CResizer::eProportional) // to the width (CResizer::eLeft or CResizer::eRight) of control IDC_CONTROL_ID. // // TIP: Resizer resizes controls in the order they are defined in the array, so // should always be defined (and, therefore, moved by the resizer) before // it is used as relative window. Otherwise, resizer ASSERTs. #pragma once #define IDC_MAIN 0 //Parent dialog ID to be relative window class CResizer { public: enum EBorder{ eFixed = 1, //Given distance to specified window side eProportional, //Coordinate is changed proportionally to width/height of specified window eWidth, //The width is preserved (relative window and window side are ignored) eHeight, //The height is preserved (relative window and window side are ignored) }; enum ESize{ eLeft = 1, //Relative to left side eTop, //Top eRight, //Right eBottom, //Bottom eXCenter, //The center of width eYCenter //The center of height }; struct CBorder{ EBorder eType; //Type of relation to relative control side int nRelID; //Relative control ESize eRelType; //Side of relative control }; struct CBorderInfo{ int nID; //Control ID CBorder left; CBorder top; CBorder right; CBorder bottom; }; private: struct CControlInfo{ RECT rcInitial; //initial control position; const CBorderInfo *pInfo; }; struct CRectInfo{ int nID; //Control ID RECT rc; //New control rect bool bVisible; //If control is visible bool bHide; //If control should be hidden because it overlaps senior control }; HWND m_wndParent; RECT m_rcInitial; //Initial window client area typedef CControlInfo * TInfo; typedef CRectInfo * TRectInfo; TInfo m_vInfo; int m_nSize; //Size of m_vInfo array mutable TRectInfo m_vRectInfo; mutable int m_nCachedSize; //Size of m_vRectInfo protected: HWND GetDlgItem(int nID) const{return ::GetDlgItem(m_wndParent, nID);} void GetDlgItemRect(int nID, RECT &rc) const; void GetCachedDlgItemRect(int nID, RECT &rc) const; void GetInitialDlgItemRect(int nID, RECT &rc) const; void Move(int nIndex) const; int GetCoordinate(ESize eType, const RECT &rcInitial, const CBorder &border, const RECT &rc) const; static int GetRectCoord(ESize eType, const RECT &rc); static int GetRectSize(ESize eType, const RECT &rc); int GetRelativeCoord(const CBorder &border) const; int Find(int nID) const; int FindCached(int nID) const; void MoveAndHideOverlapped() const; void Clear(); public: //Initializes resizer bool Init(HWND hWndParent, LPCRECT rcInitial, const CBorderInfo *pBorders, int nSize); //Performs moving of controls void Move() const; //Just constructor CResizer(); //Just destructor ~CResizer(); };