Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
5.3 KiB

  1. // File: Toolbar.cpp
  2. #include "precomp.h"
  3. #include "GenContainers.h"
  4. #include <windowsx.h>
  5. CBorderWindow::CBorderWindow() :
  6. m_uParts(0),
  7. m_hGap(0),
  8. m_vGap(0)
  9. {
  10. }
  11. BOOL CBorderWindow::Create(
  12. HWND hWndParent // The parent of this window
  13. )
  14. {
  15. return(CGenWindow::Create(
  16. hWndParent, // Window parent
  17. 0, // ID of the child window
  18. TEXT("NMBorderWindow"), // Window name
  19. WS_CLIPCHILDREN, // Window style; WS_CHILD|WS_VISIBLE will be added to this
  20. WS_EX_CONTROLPARENT // Extended window style
  21. ));
  22. }
  23. extern void GetWindowDesiredSize(HWND hwnd, SIZE *ppt);
  24. extern BOOL IsChildVisible(HWND hwndChild);
  25. enum Parts
  26. {
  27. TL = 0,
  28. T,
  29. TR,
  30. L,
  31. C,
  32. R,
  33. BL,
  34. B,
  35. BR,
  36. } ;
  37. // Returns the number of child windows
  38. UINT FillWindowSizes(
  39. HWND hwndParent,
  40. HWND hwnds[CBorderWindow::NumParts],
  41. SIZE sizes[CBorderWindow::NumParts],
  42. UINT uParts
  43. )
  44. {
  45. UINT nChildren = 0;
  46. HWND hwndChild = ::GetWindow(hwndParent, GW_CHILD);
  47. for (int i=0; i<CBorderWindow::NumParts; ++i)
  48. {
  49. sizes[i].cx = sizes[i].cy = 0;
  50. if ((uParts&(1<<i)) == 0)
  51. {
  52. hwnds[i] = NULL;
  53. }
  54. else
  55. {
  56. hwnds[i] = hwndChild;
  57. if (NULL != hwndChild && IsChildVisible(hwndChild))
  58. {
  59. IGenWindow *pWin = IGenWindow::FromHandle(hwndChild);
  60. if (NULL != pWin)
  61. {
  62. ++nChildren;
  63. pWin->GetDesiredSize(&sizes[i]);
  64. }
  65. hwndChild = ::GetWindow(hwndChild, GW_HWNDNEXT);
  66. }
  67. }
  68. }
  69. return(nChildren);
  70. }
  71. // Returns the total children desired size in the arrays
  72. // Return value is the number of child windows
  73. UINT CBorderWindow::GetDesiredSize(
  74. HWND hwnds[NumParts],
  75. SIZE sizes[NumParts],
  76. int rows[3],
  77. int cols[3],
  78. SIZE *psize)
  79. {
  80. UINT nChildren = FillWindowSizes(GetWindow(), hwnds, sizes, m_uParts);
  81. cols[0] = max(max(sizes[TL].cx, sizes[L].cx), sizes[BL].cx);
  82. cols[1] = max(max(sizes[T ].cx, sizes[C].cx), sizes[B ].cx);
  83. cols[2] = max(max(sizes[TR].cx, sizes[R].cx), sizes[BR].cx);
  84. rows[0] = max(max(sizes[TL].cy, sizes[T].cy), sizes[TR].cy);
  85. rows[1] = max(max(sizes[L ].cy, sizes[C].cy), sizes[R ].cy);
  86. rows[2] = max(max(sizes[BL].cy, sizes[B].cy), sizes[BR].cy);
  87. psize->cx = cols[0] + cols[1] + cols[2];
  88. psize->cy = rows[0] + rows[1] + rows[2];
  89. // Add the gaps
  90. if (0 != cols[0])
  91. {
  92. if (0 != cols[1] || 0 != cols[2])
  93. {
  94. psize->cx += m_hGap;
  95. }
  96. }
  97. if (0 != cols[1] && 0 != cols[2])
  98. {
  99. psize->cx += m_hGap;
  100. }
  101. if (0 != rows[0])
  102. {
  103. if (0 != rows[1] || 0 != rows[2])
  104. {
  105. psize->cy += m_vGap;
  106. }
  107. }
  108. if (0 != rows[1] && 0 != rows[2])
  109. {
  110. psize->cy += m_vGap;
  111. }
  112. return(nChildren);
  113. }
  114. void CBorderWindow::GetDesiredSize(SIZE *psize)
  115. {
  116. HWND hwnds[NumParts];
  117. SIZE sizes[NumParts];
  118. int rows[3];
  119. int cols[3];
  120. GetDesiredSize(hwnds, sizes, rows, cols, psize);
  121. // Add on any non-client size
  122. SIZE sizeTemp;
  123. CGenWindow::GetDesiredSize(&sizeTemp);
  124. psize->cx += sizeTemp.cx;
  125. psize->cy += sizeTemp.cy;
  126. }
  127. HDWP SetWindowPosI(HDWP hdwp, HWND hwndChild, int left, int top, int width, int height)
  128. {
  129. if (NULL == hwndChild)
  130. {
  131. return(hdwp);
  132. }
  133. #if TRUE
  134. return(DeferWindowPos(hdwp, hwndChild, NULL, left, top, width, height, SWP_NOZORDER));
  135. #else
  136. // Helpful for debugging
  137. SetWindowPos(hwndChild, NULL, left, top, width, height, SWP_NOZORDER);
  138. return(hdwp);
  139. #endif
  140. }
  141. // Move the children into their various locations
  142. void CBorderWindow::Layout()
  143. {
  144. HWND hwnds[NumParts];
  145. SIZE sizes[NumParts];
  146. int rows[3];
  147. int cols[3];
  148. SIZE desiredSize;
  149. UINT nChildren = GetDesiredSize(hwnds, sizes, rows, cols, &desiredSize);
  150. bool bCenterOnly = (1 == nChildren) && (0 != (m_uParts & Center));
  151. HWND hwndThis = GetWindow();
  152. RECT rcClient;
  153. GetClientRect(hwndThis, &rcClient);
  154. // Add extra space to the center
  155. if (desiredSize.cx < rcClient.right || bCenterOnly)
  156. {
  157. cols[1] += rcClient.right - desiredSize.cx;
  158. }
  159. if (desiredSize.cy < rcClient.bottom || bCenterOnly)
  160. {
  161. rows[1] += rcClient.bottom - desiredSize.cy;
  162. }
  163. // Speed up layout by deferring it
  164. HDWP hdwp = BeginDeferWindowPos(NumParts);
  165. // Add the gaps
  166. // Make the dimension 3 so we can safely iterate through the loop below
  167. int hGaps[3] = { 0, 0 };
  168. if (0 != cols[0])
  169. {
  170. if (0 != cols[1] || 0 != cols[2])
  171. {
  172. hGaps[0] = m_hGap;
  173. }
  174. }
  175. if (0 != cols[1] && 0 != cols[2])
  176. {
  177. hGaps[1] = m_hGap;
  178. }
  179. // Make the dimension 3 so we can safely iterate through the loop below
  180. int vGaps[3] = { 0, 0 };
  181. if (0 != rows[0])
  182. {
  183. if (0 != rows[1] || 0 != rows[2])
  184. {
  185. vGaps[0] = m_vGap;
  186. }
  187. }
  188. if (0 != rows[1] && 0 != rows[2])
  189. {
  190. vGaps[1] = m_vGap;
  191. }
  192. // Layout by rows
  193. int top = 0;
  194. for (int i=0; i<3; ++i)
  195. {
  196. int left = 0;
  197. for (int j=0; j<3; ++j)
  198. {
  199. hdwp = SetWindowPosI(hdwp, hwnds[3*i+j], left, top, cols[j], rows[i]);
  200. left += cols[j] + hGaps[j];
  201. }
  202. top += rows[i] + vGaps[i];
  203. }
  204. // Actually move all the windows now
  205. EndDeferWindowPos(hdwp);
  206. }
  207. LRESULT CBorderWindow::ProcessMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  208. {
  209. switch (message)
  210. {
  211. HANDLE_MSG(hwnd, WM_COMMAND, OnCommand);
  212. }
  213. return(CGenWindow::ProcessMessage(hwnd, message, wParam, lParam));
  214. }
  215. void CBorderWindow::OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  216. {
  217. FORWARD_WM_COMMAND(GetParent(hwnd), id, hwndCtl, codeNotify, SendMessage);
  218. }