ResizableSheet.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:9k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. // ResizableSheet.cpp : implementation file
  2. //
  3. /////////////////////////////////////////////////////////////////////////////
  4. //
  5. // Copyright (C) 2000-2002 by Paolo Messina
  6. // (http://www.geocities.com/ppescher - ppescher@yahoo.com)
  7. //
  8. // The contents of this file are subject to the Artistic License (the "License").
  9. // You may not use this file except in compliance with the License. 
  10. // You may obtain a copy of the License at:
  11. // http://www.opensource.org/licenses/artistic-license.html
  12. //
  13. // If you find this code useful, credits would be nice!
  14. //
  15. /////////////////////////////////////////////////////////////////////////////
  16. #include "stdafx.h"
  17. #include "ResizableSheet.h"
  18. #ifdef _DEBUG
  19. #define new DEBUG_NEW
  20. #undef THIS_FILE
  21. static char THIS_FILE[] = __FILE__;
  22. #endif
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CResizableSheet
  25. IMPLEMENT_DYNAMIC(CResizableSheet, CPropertySheet)
  26. inline void CResizableSheet::PrivateConstruct()
  27. {
  28. m_bEnableSaveRestore = FALSE;
  29. m_bSavePage = FALSE;
  30. m_dwGripTempState = 1;
  31. }
  32. CResizableSheet::CResizableSheet()
  33. {
  34. PrivateConstruct();
  35. }
  36. CResizableSheet::CResizableSheet(UINT nIDCaption, CWnd *pParentWnd, UINT iSelectPage)
  37.  : CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
  38. {
  39. PrivateConstruct();
  40. }
  41. CResizableSheet::CResizableSheet(LPCTSTR pszCaption, CWnd *pParentWnd, UINT iSelectPage)
  42.  : CPropertySheet(pszCaption, pParentWnd, iSelectPage)
  43. {
  44. PrivateConstruct();
  45. }
  46. CResizableSheet::~CResizableSheet()
  47. {
  48. }
  49. BEGIN_MESSAGE_MAP(CResizableSheet, CPropertySheet)
  50. //{{AFX_MSG_MAP(CResizableSheet)
  51. ON_WM_GETMINMAXINFO()
  52. ON_WM_SIZE()
  53. ON_WM_DESTROY()
  54. ON_WM_CREATE()
  55. ON_WM_ERASEBKGND()
  56. //}}AFX_MSG_MAP
  57. ON_NOTIFY_REFLECT_EX(PSN_SETACTIVE, OnPageChanging)
  58. END_MESSAGE_MAP()
  59. /////////////////////////////////////////////////////////////////////////////
  60. // CResizableSheet message handlers
  61. int CResizableSheet::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  62. {
  63. if (CPropertySheet::OnCreate(lpCreateStruct) == -1)
  64. return -1;
  65. // keep client area
  66. CRect rect;
  67. GetClientRect(&rect);
  68. // set resizable style
  69. ModifyStyle(DS_MODALFRAME, WS_POPUP | WS_THICKFRAME);
  70. // adjust size to reflect new style
  71. ::AdjustWindowRectEx(&rect, GetStyle(),
  72. ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle());
  73. SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), SWP_FRAMECHANGED|
  74. SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREPOSITION);
  75. // create and init the size-grip
  76. if (!CreateSizeGrip())
  77. return -1;
  78. return 0;
  79. }
  80. BOOL CResizableSheet::OnInitDialog() 
  81. {
  82. BOOL bResult = CPropertySheet::OnInitDialog();
  83. // set the initial size as the min track size
  84. CRect rc;
  85. GetWindowRect(&rc);
  86. SetMinTrackSize(rc.Size());
  87. // initialize layout
  88. PresetLayout();
  89. // prevent flickering
  90. GetTabControl()->ModifyStyle(0, WS_CLIPSIBLINGS);
  91. return bResult;
  92. }
  93. void CResizableSheet::OnDestroy() 
  94. {
  95. if (m_bEnableSaveRestore)
  96. {
  97. SaveWindowRect(m_sSection, m_bRectOnly);
  98. SavePage();
  99. }
  100. RemoveAllAnchors();
  101. CPropertySheet::OnDestroy();
  102. }
  103. // maps an index to a button ID and vice-versa
  104. static UINT _propButtons[] =
  105. {
  106. IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP,
  107. ID_WIZBACK, ID_WIZNEXT, ID_WIZFINISH
  108. };
  109. const int _propButtonsCount = sizeof(_propButtons)/sizeof(UINT);
  110. // horizontal line in wizard mode
  111. #define ID_WIZLINE ID_WIZFINISH+1
  112. void CResizableSheet::PresetLayout()
  113. {
  114. if (IsWizard()) // wizard mode
  115. {
  116. // hide tab control
  117. GetTabControl()->ShowWindow(SW_HIDE);
  118. AddAnchor(ID_WIZLINE, BOTTOM_LEFT, BOTTOM_RIGHT);
  119. }
  120. else // tab mode
  121. {
  122. AddAnchor(AFX_IDC_TAB_CONTROL, TOP_LEFT, BOTTOM_RIGHT);
  123. }
  124. // add a callback for active page (which can change at run-time)
  125. AddAnchorCallback(1);
  126. // use *total* parent size to have correct margins
  127. CRect rectPage, rectSheet;
  128. GetTotalClientRect(&rectSheet);
  129. GetActivePage()->GetWindowRect(&rectPage);
  130. ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectPage, 2);
  131. // pre-calculate margins
  132. m_sizePageTL = rectPage.TopLeft() - rectSheet.TopLeft();
  133. m_sizePageBR = rectPage.BottomRight() - rectSheet.BottomRight();
  134. // add all possible buttons, if they exist
  135. for (int i = 0; i < _propButtonsCount; i++)
  136. {
  137. if (NULL != GetDlgItem(_propButtons[i]))
  138. AddAnchor(_propButtons[i], BOTTOM_RIGHT);
  139. }
  140. }
  141. BOOL CResizableSheet::ArrangeLayoutCallback(LayoutInfo &layout)
  142. {
  143. if (layout.nCallbackID != 1) // we only added 1 callback
  144. return CResizableLayout::ArrangeLayoutCallback(layout);
  145. // set layout info for active page
  146. layout.hWnd = (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0);
  147. if (!::IsWindow(layout.hWnd))
  148. return FALSE;
  149. // set margins
  150. if (IsWizard()) // wizard mode
  151. {
  152. // use pre-calculated margins
  153. layout.sizeMarginTL = m_sizePageTL;
  154. layout.sizeMarginBR = m_sizePageBR;
  155. }
  156. else // tab mode
  157. {
  158. CTabCtrl* pTab = GetTabControl();
  159. ASSERT(pTab != NULL);
  160. // get tab position after resizing and calc page rect
  161. CRect rectPage, rectSheet;
  162. GetTotalClientRect(&rectSheet);
  163. VERIFY(GetAnchorPosition(pTab->m_hWnd, rectSheet, rectPage));
  164. pTab->AdjustRect(FALSE, &rectPage);
  165. // set margins
  166. layout.sizeMarginTL = rectPage.TopLeft() - rectSheet.TopLeft();
  167. layout.sizeMarginBR = rectPage.BottomRight() - rectSheet.BottomRight();
  168. }
  169. // set anchor types
  170. layout.sizeTypeTL = TOP_LEFT;
  171. layout.sizeTypeBR = BOTTOM_RIGHT;
  172. // use this layout info
  173. return TRUE;
  174. }
  175. void CResizableSheet::OnSize(UINT nType, int cx, int cy) 
  176. {
  177. CWnd::OnSize(nType, cx, cy);
  178. if (nType == SIZE_MAXHIDE || nType == SIZE_MAXSHOW)
  179. return; // arrangement not needed
  180. if (nType == SIZE_MAXIMIZED)
  181. HideSizeGrip(&m_dwGripTempState);
  182. else
  183. ShowSizeGrip(&m_dwGripTempState);
  184. // update grip and layout
  185. UpdateSizeGrip();
  186. ArrangeLayout();
  187. }
  188. BOOL CResizableSheet::OnPageChanging(NMHDR* /*pNotifyStruct*/, LRESULT* /*pResult*/)
  189. {
  190. // update new wizard page
  191. // active page changes after this notification
  192. PostMessage(WM_SIZE);
  193. return FALSE; // continue routing
  194. }
  195. BOOL CResizableSheet::OnEraseBkgnd(CDC* pDC) 
  196. {
  197. // Windows XP doesn't like clipping regions ...try this!
  198. EraseBackground(pDC);
  199. return TRUE;
  200. /* ClipChildren(pDC); // old-method (for safety)
  201. return CPropertySheet::OnEraseBkgnd(pDC);
  202. */
  203. }
  204. void CResizableSheet::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 
  205. {
  206. MinMaxInfo(lpMMI);
  207. }
  208. // protected members
  209. int CResizableSheet::GetMinWidth()
  210. {
  211. CWnd* pWnd = NULL;
  212. CRect rectWnd, rectSheet;
  213. GetTotalClientRect(&rectSheet);
  214. int max = 0, min = rectSheet.Width();
  215. // search for leftmost and rightmost button margins
  216. for (int i = 0; i < 7; i++)
  217. {
  218. pWnd = GetDlgItem(_propButtons[i]);
  219. // exclude not present or hidden buttons
  220. if (pWnd == NULL || !(pWnd->GetStyle() & WS_VISIBLE))
  221. continue;
  222. // left position is relative to the right border
  223. // of the parent window (negative value)
  224. pWnd->GetWindowRect(&rectWnd);
  225. ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectWnd, 2);
  226. int left = rectSheet.right - rectWnd.left;
  227. int right = rectSheet.right - rectWnd.right;
  228. if (left > max)
  229. max = left;
  230. if (right < min)
  231. min = right;
  232. }
  233. // sizing border width
  234. int border = GetSystemMetrics(SM_CXSIZEFRAME);
  235. // compute total width
  236. return max + min + 2*border;
  237. }
  238. // NOTE: this must be called after all the other settings
  239. //       to have the window and its controls displayed properly
  240. void CResizableSheet::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly, BOOL bWithPage)
  241. {
  242. m_sSection = pszSection;
  243. m_bSavePage = bWithPage;
  244. m_bEnableSaveRestore = TRUE;
  245. m_bRectOnly = bRectOnly;
  246. // restore immediately
  247. LoadWindowRect(pszSection, bRectOnly);
  248. LoadPage();
  249. }
  250. // private memebers
  251. // used to save/restore active page
  252. // either in the registry or a private .INI file
  253. // depending on your application settings
  254. #define ACTIVEPAGE  _T("ActivePage")
  255. void CResizableSheet::SavePage()
  256. {
  257. if (!m_bSavePage)
  258. return;
  259. // saves active page index, zero (the first) if problems
  260. // cannot use GetActivePage, because it always fails
  261. CTabCtrl *pTab = GetTabControl();
  262. int page = 0;
  263. if (pTab != NULL) 
  264. page = pTab->GetCurSel();
  265. if (page < 0)
  266. page = 0;
  267. AfxGetApp()->WriteProfileInt(m_sSection, ACTIVEPAGE, page);
  268. }
  269. void CResizableSheet::LoadPage()
  270. {
  271. // restore active page, zero (the first) if not found
  272. int page = AfxGetApp()->GetProfileInt(m_sSection, ACTIVEPAGE, 0);
  273. if (m_bSavePage)
  274. {
  275. SetActivePage(page);
  276. ArrangeLayout(); // needs refresh
  277. }
  278. }
  279. void CResizableSheet::RefreshLayout()
  280. {
  281. SendMessage(WM_SIZE);
  282. }