cdxCDynamicControlsManager.h
上传用户:cbxyz2008
上传日期:2007-01-02
资源大小:45k
文件大小:15k
源码类别:

Static控件

开发平台:

Visual C++

  1. // cdxCDynamicControlsManager.h: interface for the cdxCDynamicControlsManager class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #if !defined(AFX_CDXCDYNAMICCONTROLSMANAGER_H__6517AE13_5D12_11D2_BE4C_000000000000__INCLUDED_)
  5. #define AFX_CDXCDYNAMICCONTROLSMANAGER_H__6517AE13_5D12_11D2_BE4C_000000000000__INCLUDED_
  6. #if _MSC_VER >= 1000
  7. #pragma once
  8. #endif // _MSC_VER >= 1000
  9. #include "cdxCSizeIconCtrl.h"
  10. typedef cdxCSizeIconCtrl cdxCSizeCtrl;
  11. //
  12. // cdxCDynamicControlsManager.h : header file
  13. // -----------------------------------------------------------------------
  14. // Author:  Hans B黨ler (hans.buehler@student.hu-berlin.de)
  15. //          codex design (http://www-pool.mathematik.hu-berlin.de/~codex
  16. // Version: 1.3
  17. // Release: 3 (Jan 1999 to www.codeguru.com)
  18. // -----------------------------------------------------------------------
  19. // Changes for V1.1:
  20. // - cdxCSizeCtrl is now only a typedef on cdxCSizeIconCtrl which is been
  21. //   but in two extra files (header and impl.) to make it available to
  22. //   the programmer even if you don't use cdxCDynamicControls.
  23. //   The include/impl file for cdxCSizeIconCtrl must be available.
  24. // - GetSizeIconBitmap() is been deleted.
  25. // - ICON_CONTROL_ID has been changed to AFX_IDW_SIZE_BOX
  26. // Changes for V1.2:
  27. // - cdxCDynamicControlsManager::DoOnGetMinMaxInfo() has been modified
  28. //   (thanks to a bug report by Michel Wassink <mww@mitutoyo.nl>):
  29. //   Now, if you don't call SetMaxSize(), the maximum position of a window
  30. //   will not be changed.
  31. //   BUG: Under W95 and W98, resizing didn't work properly REMOVED.
  32. // Changes for V1.3:
  33. // - FindSzControl() and RemSzControl() have been added.
  34. // -----------------------------------------------------------------------
  35. // Comments welcome.
  36. //
  37. /*
  38.  * cdxCDynamicControlsManager
  39.  * ==========================
  40.  * Makes any CWnd derived class capable of dynamic control resizing
  41.  * and repositioning.
  42.  * Moreover, it can set a window's max/min tracking size (the size
  43.  * the user can change) and add a nice sizing icon to the windows
  44.  * lower right corner (if the window does not have one - as dialogs).
  45.  *
  46.  * To make any CWnd derived capable of automatically displaying
  47.  * its controls, you embed a member of this class in your window
  48.  * (or you derive your class from both this class and your window
  49.  * base class - that depends on how you want to use the member
  50.  * functions of this class).
  51.  *
  52.  * Then, the following functions must be called
  53.  *
  54.  * DoInitWindow() - Must be called after the window became
  55.  * valid (i.e. CWnd::m_hWnd is non-zero)
  56.  * and has its initial (minimum) size.
  57.  * DoOnSize() - by the OnSize() message handler
  58.  * DoOnGetMinMaxInfo() - by the OnGetMinMaxInfo() message handler
  59.  * DoDestroyWindow() - by DestroyWindow().
  60.  *
  61.  * See cdxCSizingDialog.h for an example.
  62.  * 
  63.  * NOTE:
  64.  * Unfortunately, we cannot derive this class from CObject, because
  65.  * those macros DECLARE_xxx are too lame to handle multipile derived
  66.  * classes if both classes have been derived from the same base-class
  67.  * CObject.
  68.  */
  69. class cdxCDynamicControlsManager
  70. {
  71. //
  72. // various constants
  73. //
  74. public:
  75. enum Mode // flags for AddSzControl()
  76. {
  77. mdNone = 0, // does nothing
  78. mdResize = 1, // resize in that dimension
  79. mdRepos = 2, // reposition
  80. mdRelative = 3, // center (size by delta/2 and repos by delta/2)
  81. md__Last = mdRelative
  82. };
  83. enum Freedom
  84. {
  85. fdNone = 0, // might be used but I don't imagine what you want from this ??
  86. fdHoriz = 0x01, // horizantally sizable only
  87. fdVert = 0x02, // vertically sizable only
  88. fdAll = fdHoriz|fdVert // sizable in all directions
  89. };
  90. enum RestoreFlags
  91. {
  92. rflg_none = 0, // only load window position
  93. rflg_state = 0x01, // make window iconic/zoomed if been before
  94. rflg_visibility = 0x02, // hide/show window as been before
  95. rflg_all = rflg_state|rflg_visibility
  96. };
  97. enum
  98. {
  99. ICON_CONTROL_ID = AFX_IDW_SIZE_BOX
  100. };
  101. //
  102. // an astract handle to a sizeable control that you can
  103. // use to add further controls to
  104. // see discussion of AddSzControl()
  105. //
  106. public:
  107. class ControlPosition
  108. {
  109. protected:
  110. ControlPosition() {}
  111. public:
  112. virtual ~ControlPosition() {}
  113. public:
  114. virtual void Add(CWnd & ctrl) = NULL;
  115. };
  116. //
  117. // internal storage class for controls and their
  118. // original positions and their behaviour settings
  119. //
  120. private:
  121. class ControlData : public ControlPosition
  122. {
  123. //
  124. // all controls with the same positioning arguments
  125. // (used by Add())
  126. // Note that the window is not need to be already created
  127. //
  128. private:
  129. struct Control
  130. {
  131. private:
  132. Control *m_pNext; // next
  133. CWnd & m_rCtrl; // the control
  134. public:
  135. Control(CWnd & ctrl, Control *pNext = NULL) : m_pNext(pNext), m_rCtrl(ctrl) {}
  136. virtual ~Control() { if(m_pNext) delete m_pNext; } // no need to be virtual
  137. bool IsMemberOf(CWnd & ctrl) { if(&ctrl == &m_rCtrl) return true; return m_pNext ? m_pNext->IsMemberOf(ctrl) : false; }
  138. void Add(CWnd & ctrl, int x, int y, int wid, int hi);
  139. void Position(int x, int y, int wid, int hi, bool bAl);
  140. };
  141. friend struct Control;
  142. private:
  143. cdxCDynamicControlsManager
  144. & m_rMaster; // the master class
  145. ControlData *m_pNext,*m_pPrev; // a linked list (root in m_rMaster.m_pFirst)
  146. Control m_Ctrl; // control link list
  147. BYTE m_dX1pcnt,m_dX2pcnt,
  148. m_dY1pcnt,m_dY2pcnt; // percentage values of deltaX(Y) to add to coordinate
  149. CRect m_rectOriginal; // original position of control(s)
  150. public:
  151. ControlData(cdxCDynamicControlsManager & rMaster, CWnd & ctrl, BYTE dX1pcnt, BYTE dX2pcnt, BYTE dY1pcnt, BYTE dY2pcnt);
  152. virtual ~ControlData();
  153. bool IsMemberOf(CWnd & ctrl) { return m_Ctrl.IsMemberOf(ctrl); }
  154. void OnSize(const CSize & szDelta);
  155. ControlData *GetNext(void) { return m_pNext; }
  156. virtual void Add(CWnd & ctrl) { m_Ctrl.Add(ctrl,m_rectOriginal.left,m_rectOriginal.top,m_rectOriginal.Width(),m_rectOriginal.Height()); }
  157. };
  158. //
  159. // my members
  160. //
  161. friend class ControlData;
  162. private:
  163. ControlData *m_pFirst;
  164. CWnd *m_pWnd; // Use Init() !!!!!!!!!
  165. CSize m_szClientRelative, // original's window size (client !!) - used in OnSize() to calculate delta size
  166. m_szMin, // minimum size (whole window)
  167. m_szMax; // maximum (whole window)
  168. Freedom m_Freedom; // what is allowed
  169. cdxCSizeCtrl *m_pWndSizeIcon; // the icon control
  170. public:
  171. UINT m_idSizeIcon; // ID of the icon control (you can set this to change the default, ICON_CONTROL_ID)
  172. public:
  173. cdxCDynamicControlsManager() : m_pFirst(NULL), m_pWnd(NULL), m_Freedom(fdAll), m_pWndSizeIcon(NULL), m_idSizeIcon(ICON_CONTROL_ID) {}
  174. virtual ~cdxCDynamicControlsManager() { DoDestroyWindow(); }
  175. //
  176. // check status
  177. //
  178. bool IsReady(void) const { return (m_pWnd != NULL) && ::IsWindow(m_pWnd->m_hWnd); }
  179. //
  180. // get some basics
  181. //
  182. const CSize & GetMinSize(void) const { return m_szMin; }
  183. const CSize & GetMaxSize(void) const { return m_szMax; }
  184. Freedom GetFreedom(void) const { return m_Freedom; }
  185. //
  186. // wanna change some basics ?
  187. //
  188. bool SetMinMaxSize(const CSize & szMin, const CSize & szMax, bool bResizeIfNecessary = true);
  189. bool FixWindowSize(void);
  190. void SetFreedom(Freedom fd) { m_Freedom = fd; }
  191. void HideSizeIcon(void);
  192. void ShowSizeIcon(void);
  193. //
  194. // add controls to handle
  195. //
  196. ControlPosition *AddSzControl(CWnd & ctrl, Mode modeX, Mode modeY);
  197. ControlPosition *AddSzXControl(CWnd & ctrl, Mode modeX) { return AddSzControl(ctrl,modeX,mdNone); }
  198. ControlPosition *AddSzYControl(CWnd & ctrl, Mode modeY) { return AddSzControl(ctrl,mdNone,modeY); }
  199. virtual ControlPosition *AddSzControlEx(CWnd & ctrl, BYTE dX1pcnt, BYTE dX2pcnt, BYTE dY1pcnt, BYTE dY2pcnt);
  200. ControlPosition *AddSzXControlEx(CWnd & ctrl, BYTE dX1pcnt, BYTE dX2pcnt) { return AddSzControlEx(ctrl,dX1pcnt,dX2pcnt,0,0); }
  201. ControlPosition *AddSzYControlEx(CWnd & ctrl, BYTE dY1pcnt, BYTE dY2pcnt) { return AddSzControlEx(ctrl,0,0,dY1pcnt,dY2pcnt); }
  202. //
  203. // advanced (new to V1.3)
  204. //
  205. ControlPosition *FindSzControl(CWnd & ctrl);
  206. bool RemSzControl(CWnd & ctrl) { ControlPosition *p = FindSzControl(ctrl); if(!p) return false; delete p; return true; }
  207. //
  208. // these must be called by the appropiate message handlers of the window
  209. // class you're deriving from
  210. //
  211. void DoInitWindow(CWnd & rWnd, Freedom fd = fdAll, bool bSizeIcon = false, const CSize * pBaseClientSize = NULL);
  212. void DoOnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
  213. void DoOnSize(UINT nType, int cx, int cy);
  214. void DoDestroyWindow(void);
  215. //
  216. // some helpers
  217. //
  218. void ReorganizeControls(bool bRedraw = true);
  219. void ReorganizeControlsAdvanced(const CRect & rectWin, CRect rectClient, bool bRedraw = true);
  220. bool StretchWindow(const CSize & szDelta) { ASSERT(IsReady()); return StretchWindow(*m_pWnd,szDelta); }
  221. bool StretchWindow(int iAddPcnt) { ASSERT(IsReady()); return StretchWindow(*m_pWnd,iAddPcnt); }
  222. CSize GetWindowSize(void) { ASSERT(IsReady()); return GetWindowSize(*m_pWnd); }
  223. bool RestoreWindowPosition(LPCTSTR lpszProfile, UINT restoreFlags = rflg_none) { ASSERT(IsReady()); return RestoreWindowPosition(*m_pWnd,lpszProfile,restoreFlags); }
  224. bool StoreWindowPosition(LPCTSTR lpszProfile) { ASSERT(IsReady()); return StoreWindowPosition(*m_pWnd,lpszProfile); }
  225. //
  226. // helpers; static
  227. //
  228. static bool StretchWindow(CWnd & rWnd, const CSize & szDelta);
  229. static bool StretchWindow(CWnd & rWnd, int iAddPcnt);
  230. static CSize GetWindowSize(CWnd & rWnd);
  231. static bool RestoreWindowPosition(CWnd & rWnd, LPCTSTR lpszProfile, UINT restoreFlags = rflg_none);
  232. static bool StoreWindowPosition(CWnd & rWnd, LPCTSTR lpszProfile);
  233. //
  234. // misc
  235. //
  236. public:
  237. /* removed */ //static CBitmap & GetSizeIconBitmap(CSize * pSzBmp = NULL);
  238. static CImageList & GetSizeIconImageList(CSize * pSzBmp = NULL) { if(pSzBmp) *pSzBmp = cdxCSizeIconCtrl::M_ilImage.Size(); return cdxCSizeIconCtrl::M_ilImage; }
  239. };
  240. /*
  241.  * cdxCSizeCtrl
  242.  * ============
  243.  * Is now a typedef to cdxCSizeIconCtrl - see above.
  244.  */
  245. /////////////////////////////////////////////////////////////////////////////
  246. // cdxCDynamicControlsManager::ControlData::Control inlines
  247. /////////////////////////////////////////////////////////////////////////////
  248. /*
  249.  * add a control that has the same coordinates as the
  250.  * control embedded in the ControlData object.
  251.  * The coordinates are needed to immediately place the
  252.  * control to the original control's position.
  253.  */
  254. inline void cdxCDynamicControlsManager::ControlData::Control::Add(CWnd & ctrl, int x, int y, int wid, int hi)
  255. {
  256. VERIFY( m_pNext = new Control(ctrl,m_pNext) );
  257. m_pNext->Position(x,y,wid,hi,false);
  258. }
  259. /*
  260.  * apply new position to all "Control" controls
  261.  * we don't change the z-order here !
  262.  */
  263. inline void cdxCDynamicControlsManager::ControlData::Control::Position(int x, int y, int wid, int hi, bool bAll)
  264. {
  265. if(::IsWindow(m_rCtrl.m_hWnd)) // those window don't need to exist :)
  266. {
  267. VERIFY( m_rCtrl.SetWindowPos(&CWnd::wndBottom,x,y,wid,hi,
  268. SWP_NOCOPYBITS|SWP_NOOWNERZORDER|
  269. SWP_NOACTIVATE|SWP_NOZORDER) );
  270. }
  271. if(m_pNext && bAll)
  272. m_pNext->Position(x,y,wid,hi,true);
  273. }
  274. /////////////////////////////////////////////////////////////////////////////
  275. // cdxCDynamicControlsManager inlines
  276. /////////////////////////////////////////////////////////////////////////////
  277. /*
  278.  * add a control - we leave that work
  279.  * to the embedded ControlData class
  280.  */
  281. inline cdxCDynamicControlsManager::ControlPosition *cdxCDynamicControlsManager::AddSzControlEx(CWnd & ctrl, BYTE dX1pcnt, BYTE dX2pcnt, BYTE dY1pcnt, BYTE dY2pcnt)
  282. {
  283. ASSERT(IsReady()); // don't called DoInitWindow() before ?
  284. ASSERT((dX1pcnt <= dX2pcnt) && (dY1pcnt <= dY2pcnt));
  285. // NOT recommended !!!!!!!
  286. ControlData *si = new ControlData(*this, ctrl, dX1pcnt, dX2pcnt, dY1pcnt, dY2pcnt);
  287. ASSERT(si != NULL); // if you don't throw exceptions :)
  288. return si;
  289. }
  290. /*
  291.  * find a control's ControlPosition
  292.  */
  293. inline cdxCDynamicControlsManager::ControlPosition *cdxCDynamicControlsManager::FindSzControl(CWnd & ctrl)
  294. {
  295. ASSERT(::IsWindow(ctrl.m_hWnd)); // will work for exiting windows only !
  296. for(ControlData *si = m_pFirst; si; si = si->GetNext())
  297. if(si->IsMemberOf(ctrl))
  298. return si;
  299. return NULL;
  300. }
  301. /*
  302.  * adding controls by my nice constants
  303.  */
  304. inline cdxCDynamicControlsManager::ControlPosition *cdxCDynamicControlsManager::AddSzControl(CWnd & ctrl, Mode modeX, Mode modeY)
  305. {
  306. BYTE dX1pcnt = 0,
  307. dX2pcnt = 0,
  308. dY1pcnt = 0,
  309. dY2pcnt = 0;
  310. switch(modeX)
  311. {
  312. default : ASSERT(false); // unknown value for modeX
  313. case mdNone : break;
  314. case mdRepos : dX1pcnt = dX2pcnt = 100;
  315. break;
  316. case mdResize : dX2pcnt = 100;
  317. break;
  318. case mdRelative: dX1pcnt = dX2pcnt = 100 / 2;
  319. break;
  320. }
  321. switch(modeY)
  322. {
  323. default : ASSERT(false); // unknown value for modeY
  324. case mdNone : break;
  325. case mdRepos : dY1pcnt = dY2pcnt = 100;
  326. break;
  327. case mdResize : dY2pcnt = 100;
  328. break;
  329. case mdRelative: dY1pcnt = dY2pcnt = 100 / 2;
  330. break;
  331. }
  332. return AddSzControlEx(ctrl,dX1pcnt,dX2pcnt,dY1pcnt,dY2pcnt);
  333. }
  334. /////////////////////////////////////////////////////////////////////////////
  335. /*
  336.  * Reposition
  337.  */
  338. inline void cdxCDynamicControlsManager::ReorganizeControls(bool bRedraw)
  339. {
  340. ASSERT(IsReady());
  341. CRect clrect;
  342. m_pWnd->GetClientRect(&clrect);
  343. CRect winrect;
  344. m_pWnd->GetWindowRect(&winrect);
  345. ReorganizeControlsAdvanced(winrect,clrect,bRedraw);
  346. }
  347. /////////////////////////////////////////////////////////////////////////////
  348. /*
  349.  * fill in MINMAXINFO as requested
  350.  * Call your CWnd's OnGetMinMaxInfo first !
  351.  *
  352.  * changed due to a but report by Michel Wassink <mww@mitutoyo.nl>
  353.  */
  354. inline void cdxCDynamicControlsManager::DoOnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
  355. {
  356. if(IsReady())
  357. {
  358. lpMMI->ptMinTrackSize.x = m_szMin.cx;
  359. lpMMI->ptMinTrackSize.y = m_szMin.cy;
  360. if(m_Freedom & fdHoriz)
  361. {
  362. if(m_szMax.cx)
  363. lpMMI->ptMaxTrackSize.x = m_szMax.cx;
  364. }
  365. else
  366. lpMMI->ptMaxTrackSize.x = m_szMin.cx;
  367. if(m_Freedom & fdVert)
  368. {
  369. if(m_szMax.cy)
  370. lpMMI->ptMaxTrackSize.y = m_szMax.cy;
  371. }
  372. else
  373. lpMMI->ptMaxTrackSize.y = m_szMin.cy;
  374. }
  375. }
  376. /*
  377.  * handle OnSize - we can't rely on cx,cy being client dimensions
  378.  * as stated in the documentation ...
  379.  */
  380. inline void cdxCDynamicControlsManager::DoOnSize(UINT nType, int cx, int cy)
  381. {
  382. if(IsReady() && (nType != SIZE_MINIMIZED))
  383. ReorganizeControls(true);
  384. }
  385. /*
  386.  * free all memory
  387.  * after having called this function, you can reuse the object
  388.  * although I wouldn't recommend to do so :)
  389.  */
  390. inline void cdxCDynamicControlsManager::DoDestroyWindow(void)
  391. {
  392. while(m_pFirst)
  393. delete m_pFirst;
  394. if(m_pWndSizeIcon)
  395. {
  396. if(::IsWindow(m_pWndSizeIcon->m_hWnd))
  397. m_pWndSizeIcon->DestroyWindow();
  398. delete m_pWndSizeIcon;
  399. m_pWndSizeIcon = NULL;
  400. }
  401. m_pWnd = NULL;
  402. }
  403. #endif // !defined(AFX_CDXCDYNAMICCONTROLSMANAGER_H__6517AE13_5D12_11D2_BE4C_000000000000__INCLUDED_)