ResizablePage.cpp
上传用户:hjw22cn
上传日期:2007-01-11
资源大小:192k
文件大小:6k
源码类别:

Tab控件

开发平台:

Visual C++

  1. // ResizablePage.cpp : implementation file
  2. //
  3. /////////////////////////////////////////////////////////////////////////////
  4. //
  5. // Copyright (C) 2000 by Paolo Messina
  6. // (ppescher@yahoo.com)
  7. //
  8. // Free for non-commercial use.
  9. // You may change the code to your needs,
  10. // provided that credits to the original 
  11. // author is given in the modified files.
  12. //  
  13. /////////////////////////////////////////////////////////////////////////////
  14. #include "stdafx.h"
  15. #include "ResizablePage.h"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CResizablePage
  23. IMPLEMENT_DYNCREATE(CResizablePage, CPropertyPage)
  24. inline void CResizablePage::Construct()
  25. {
  26. m_bInitDone = FALSE;
  27. }
  28. CResizablePage::CResizablePage()
  29. {
  30. Construct();
  31. }
  32. CResizablePage::CResizablePage(UINT nIDTemplate, UINT nIDCaption)
  33. : CPropertyPage(nIDTemplate, nIDCaption)
  34. {
  35. Construct();
  36. }
  37. CResizablePage::CResizablePage(LPCTSTR lpszTemplateName, UINT nIDCaption)
  38. : CPropertyPage(lpszTemplateName, nIDCaption)
  39. {
  40. Construct();
  41. }
  42. CResizablePage::~CResizablePage()
  43. {
  44. Layout *pl;
  45. POSITION pos = m_plLayoutList.GetHeadPosition();
  46. while (pos != NULL)
  47. {
  48. pl = (Layout*)m_plLayoutList.GetNext(pos);
  49. delete pl;
  50. }
  51. }
  52. BEGIN_MESSAGE_MAP(CResizablePage, CPropertyPage)
  53. //{{AFX_MSG_MAP(CResizablePage)
  54. ON_WM_SIZE()
  55. //}}AFX_MSG_MAP
  56. END_MESSAGE_MAP()
  57. /////////////////////////////////////////////////////////////////////////////
  58. // CResizablePage message handlers
  59. BOOL CResizablePage::OnInitDialog() 
  60. {
  61. CPropertyPage::OnInitDialog();
  62. // gets the initial size as the min track size
  63. CRect rc;
  64. GetWindowRect(&rc);
  65. m_bInitDone = TRUE;
  66. return TRUE;  // return TRUE unless you set the focus to a control
  67.               // EXCEPTION: OCX Property Pages should return FALSE
  68. }
  69. void CResizablePage::AddAnchor(HWND wnd, CSize tl_type, CSize br_type)
  70. {
  71. ASSERT(wnd != NULL && ::IsWindow(wnd));
  72. ASSERT(::IsChild(*this, wnd));
  73. ASSERT(tl_type != NOANCHOR);
  74. // get control's window class
  75. CString st;
  76. GetClassName(wnd, st.GetBufferSetLength(MAX_PATH), MAX_PATH);
  77. st.ReleaseBuffer();
  78. st.MakeUpper();
  79. // add the style 'clipsiblings' to a GroupBox
  80. // to avoid unnecessary repainting of controls inside
  81. if (st == "BUTTON")
  82. {
  83. DWORD style = GetWindowLong(wnd, GWL_STYLE);
  84. if (style & BS_GROUPBOX)
  85. SetWindowLong(wnd, GWL_STYLE, style | WS_CLIPSIBLINGS);
  86. }
  87. // wnd classes that don't redraw client area correctly
  88. // when the hor scroll pos changes due to a resizing
  89. BOOL hscroll = FALSE;
  90. if (st == "LISTBOX")
  91. hscroll = TRUE;
  92. // wnd classes that need refresh when resized
  93. BOOL refresh = FALSE;
  94. if (st == "STATIC")
  95. {
  96. DWORD style = GetWindowLong(wnd, GWL_STYLE);
  97. switch (style & SS_TYPEMASK)
  98. {
  99. case SS_LEFT:
  100. case SS_CENTER:
  101. case SS_RIGHT:
  102. // word-wrapped text needs refresh
  103. refresh = TRUE;
  104. }
  105. // centered images or text need refresh
  106. if (style & SS_CENTERIMAGE)
  107. refresh = TRUE;
  108. // simple text never needs refresh
  109. if (style & SS_TYPEMASK == SS_SIMPLE)
  110. refresh = FALSE;
  111. }
  112. // get dialog's and control's rect
  113. CRect wndrc, objrc;
  114. GetClientRect(&wndrc);
  115. ::GetWindowRect(wnd, &objrc);
  116. ScreenToClient(&objrc);
  117. CSize tl_margin, br_margin;
  118. if (br_type == NOANCHOR)
  119. br_type = tl_type;
  120. // calculate margin for the top-left corner
  121. tl_margin.cx = objrc.left - wndrc.Width() * tl_type.cx / 100;
  122. tl_margin.cy = objrc.top - wndrc.Height() * tl_type.cy / 100;
  123. // calculate margin for the bottom-right corner
  124. br_margin.cx = objrc.right - wndrc.Width() * br_type.cx / 100;
  125. br_margin.cy = objrc.bottom - wndrc.Height() * br_type.cy / 100;
  126. // add to the list
  127. m_plLayoutList.AddTail(new Layout(wnd, tl_type, tl_margin,
  128. br_type, br_margin, hscroll, refresh));
  129. }
  130. void CResizablePage::ArrangeLayout()
  131. {
  132. // init some vars
  133. CRect wndrc;
  134. GetClientRect(&wndrc);
  135. Layout *pl;
  136. POSITION pos = m_plLayoutList.GetHeadPosition();
  137. HDWP hdwp = BeginDeferWindowPos(m_plLayoutList.GetCount());
  138. while (pos != NULL)
  139. {
  140. pl = (Layout*)m_plLayoutList.GetNext(pos);
  141. CRect objrc, newrc;
  142. CWnd* wnd = CWnd::FromHandle(pl->hwnd); // temporary solution
  143. wnd->GetWindowRect(&objrc);
  144. ScreenToClient(&objrc);
  145. // calculate new top-left corner
  146. newrc.left = pl->tl_margin.cx + wndrc.Width() * pl->tl_type.cx / 100;
  147. newrc.top = pl->tl_margin.cy + wndrc.Height() * pl->tl_type.cy / 100;
  148. // calculate new bottom-right corner
  149. newrc.right = pl->br_margin.cx + wndrc.Width() * pl->br_type.cx / 100;
  150. newrc.bottom = pl->br_margin.cy + wndrc.Height() * pl->br_type.cy / 100;
  151. if (!newrc.EqualRect(&objrc))
  152. {
  153. BOOL add = TRUE;
  154. if (pl->adj_hscroll)
  155. {
  156. // needs repainting, due to horiz scrolling
  157. int diff = newrc.Width() - objrc.Width();
  158. int max = wnd->GetScrollLimit(SB_HORZ);
  159. if (max > 0 && wnd->GetScrollPos(SB_HORZ) > max - diff)
  160. {
  161. wnd->MoveWindow(&newrc);
  162. wnd->Invalidate();
  163. wnd->UpdateWindow();
  164. add = FALSE;
  165. }
  166. }
  167. if (pl->need_refresh)
  168. {
  169. wnd->MoveWindow(&newrc);
  170. wnd->Invalidate();
  171. wnd->UpdateWindow();
  172. add = FALSE;
  173. }
  174. if (add)
  175. DeferWindowPos(hdwp, pl->hwnd, NULL, newrc.left, newrc.top,
  176. newrc.Width(), newrc.Height(), SWP_NOZORDER | SWP_NOACTIVATE);
  177. }
  178. }
  179. // go re-arrange child windows
  180. EndDeferWindowPos(hdwp);
  181. }
  182. void CResizablePage::OnSize(UINT nType, int cx, int cy) 
  183. {
  184. CWnd::OnSize(nType, cx, cy);
  185. if (m_bInitDone)
  186. ArrangeLayout();
  187. }