Source code of Windows XP (NT5)
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.

435 lines
12 KiB

  1. //+---------------------------------------------------------------------
  2. //
  3. // File: ipborder.cxx
  4. //
  5. // Classes: InPlaceBorder
  6. //
  7. // Notes: Use of this class limits windows to the use
  8. // of the non-client region for UIAtive borders
  9. // only: Standard (non-control window) scroll bars
  10. // are specifically NOT supported.
  11. //
  12. // History: 14-May-93 CliffG Created.
  13. //
  14. //------------------------------------------------------------------------
  15. #include "headers.hxx"
  16. #pragma hdrstop
  17. #define IPB_GRABFACTOR 3
  18. #define SetWF(hwnd,wf) SetWindowLongPtr(hwnd, GWL_STYLE, \
  19. GetWindowLongPtr(hwnd,GWL_STYLE) | (wf))
  20. #define ClrWF(hwnd,wf) SetWindowLongPtr(hwnd, GWL_STYLE, \
  21. GetWindowLongPtr(hwnd,GWL_STYLE) &~(wf))
  22. #define TestWF(hwnd,wf) (GetWindowLongPtr(hwnd,GWL_STYLE) & (wf))
  23. WORD InPlaceBorder::_cUsage = 0;
  24. HBRUSH InPlaceBorder::_hbrActiveCaption;
  25. HBRUSH InPlaceBorder::_hbrInActiveCaption;
  26. //+---------------------------------------------------------------
  27. //
  28. // Member: InPlaceBorder::DrawFrame
  29. //
  30. //---------------------------------------------------------------
  31. void
  32. InPlaceBorder::DrawFrame(HWND hwnd)
  33. {
  34. if(!_fUIActive)
  35. return;
  36. HDC hdc = GetWindowDC(hwnd);
  37. if (!hdc)
  38. return;
  39. HBRUSH hbr;
  40. if(_fParentActive)
  41. hbr = _hbrActiveCaption;
  42. else
  43. hbr = _hbrInActiveCaption;
  44. if (hbr)
  45. {
  46. RECT rcWhole;
  47. GetWindowRect(hwnd, &rcWhole);
  48. OffsetRect(&rcWhole, -rcWhole.left, -rcWhole.top);
  49. RECT rc;
  50. //Top
  51. rc = rcWhole;
  52. rc.bottom = rc.top + _cyFrame;
  53. FillRect(hdc, &rc, hbr);
  54. //Left
  55. rc = rcWhole;
  56. rc.right = rc.left + _cxFrame;
  57. FillRect(hdc, &rc, hbr);
  58. //Bottom
  59. rc = rcWhole;
  60. rc.top = rc.bottom - _cyFrame;
  61. FillRect(hdc, &rc, hbr);
  62. //Right
  63. rc = rcWhole;
  64. rc.left = rc.right - _cxFrame;
  65. FillRect(hdc, &rc, hbr);
  66. if(TestWF(hwnd, WS_THICKFRAME)) //Resizable window?
  67. {
  68. //
  69. //Draw grab handles at 4 corners of the border...
  70. //
  71. hbr = (HBRUSH)GetStockObject( BLACK_BRUSH );
  72. //TopLeft
  73. rc = rcWhole;
  74. rc.right = rc.left + _cxFrame;
  75. rc.bottom = rc.top + _cyFrame * IPB_GRABFACTOR;
  76. FillRect(hdc, &rc, hbr);
  77. rc.bottom = rc.top + _cyFrame;
  78. rc.right = rc.left + _cxFrame * IPB_GRABFACTOR;
  79. FillRect(hdc, &rc, hbr);
  80. //TopRight
  81. rc.right = rcWhole.right;
  82. rc.left = rc.right - _cxFrame * IPB_GRABFACTOR;
  83. FillRect(hdc, &rc, hbr);
  84. rc.left = rc.right - _cxFrame;
  85. rc.bottom = rc.top + _cyFrame * IPB_GRABFACTOR;
  86. FillRect(hdc, &rc, hbr);
  87. //BottomLeft
  88. rc = rcWhole;
  89. rc.top = rc.bottom - _cyFrame * IPB_GRABFACTOR;
  90. rc.right = rc.left + _cxFrame;
  91. FillRect(hdc, &rc, hbr);
  92. rc.top = rc.bottom - _cyFrame;
  93. rc.right = rc.left + _cxFrame * IPB_GRABFACTOR;
  94. FillRect(hdc, &rc, hbr);
  95. //BottomRight
  96. rc.right = rcWhole.right;
  97. rc.left = rc.right - _cxFrame * IPB_GRABFACTOR;
  98. FillRect(hdc, &rc, hbr);
  99. rc.right = rcWhole.right;
  100. rc.left = rc.right - _cxFrame;
  101. rc.top = rc.bottom - _cyFrame * IPB_GRABFACTOR;
  102. FillRect(hdc, &rc, hbr);
  103. }
  104. }
  105. ReleaseDC(hwnd, hdc);
  106. }
  107. //+---------------------------------------------------------------
  108. //
  109. // Member: InPlaceBorder::HitTest
  110. //
  111. //---------------------------------------------------------------
  112. LONG
  113. InPlaceBorder::HitTest(HWND hwnd, int x, int y)
  114. {
  115. POINT pt = { x, y };
  116. RECT rcClient;
  117. GetWindowRect(hwnd, &rcClient);
  118. CalcClientRect(hwnd, &rcClient);
  119. if (PtInRect(&rcClient, pt))
  120. return HTCLIENT;
  121. // We're somewhere on the window frame.
  122. if (y >= rcClient.bottom)
  123. {
  124. if (x <= rcClient.left + _cxFrame * IPB_GRABFACTOR)
  125. return HTBOTTOMLEFT;
  126. if (x >= rcClient.right - _cxFrame * IPB_GRABFACTOR)
  127. return HTBOTTOMRIGHT;
  128. return HTBOTTOM;
  129. }
  130. else if (y <= rcClient.top)
  131. {
  132. if (x <= rcClient.left + _cxFrame * IPB_GRABFACTOR)
  133. return(HTTOPLEFT);
  134. if (x >= rcClient.right - _cxFrame * IPB_GRABFACTOR)
  135. return(HTTOPRIGHT);
  136. return HTTOP;
  137. }
  138. else if (x <= rcClient.left)
  139. {
  140. if (y <= rcClient.top + _cyFrame * IPB_GRABFACTOR)
  141. return HTTOPLEFT;
  142. if (y >= rcClient.bottom - _cyFrame * IPB_GRABFACTOR)
  143. return HTBOTTOMLEFT;
  144. return HTLEFT;
  145. }
  146. else
  147. {
  148. if (y <= rcClient.top + _cyFrame * IPB_GRABFACTOR)
  149. return HTTOPRIGHT;
  150. if (y >= rcClient.bottom - _cyFrame * IPB_GRABFACTOR)
  151. return HTBOTTOMRIGHT;
  152. return HTRIGHT;
  153. }
  154. return HTNOWHERE;
  155. }
  156. //+---------------------------------------------------------------
  157. //
  158. // Member: InPlaceBorder::DefWindowProc
  159. //
  160. //---------------------------------------------------------------
  161. LRESULT
  162. InPlaceBorder::DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  163. {
  164. LRESULT lRet = 0L;
  165. //REVIEW code assumes an SDI app...
  166. if(_hwnd == NULL)
  167. return ::DefWindowProc(hwnd,msg,wParam,lParam);
  168. switch (msg)
  169. {
  170. case WM_WINDOWPOSCHANGED:
  171. if(_pSite != NULL && _cResizing == 0 && _fUIActive)
  172. {
  173. ++_cResizing;
  174. RECT rc;
  175. GetChildWindowRect(hwnd, &rc);
  176. InflateRect(&rc,-_cxFrame,-_cyFrame);
  177. _pSite->OnPosRectChange(&rc);
  178. _cResizing--;
  179. }
  180. break;
  181. case WM_NCCALCSIZE: // lParam == LPRECT of window rect
  182. //
  183. //Turn off the WS_THICKFRAME style bit during
  184. //default processing so we keep ownership of visualization...
  185. //
  186. if (TestWF(hwnd, WS_THICKFRAME))
  187. {
  188. ClrWF(hwnd, WS_THICKFRAME);
  189. lRet = ::DefWindowProc(hwnd, msg, wParam,lParam);
  190. SetWF(hwnd, WS_THICKFRAME);
  191. }
  192. CalcClientRect(hwnd, (LPRECT)lParam);
  193. return lRet;
  194. case WM_NCHITTEST: // lParam is POINT in screen cords
  195. return HitTest(hwnd, LOWORD(lParam), HIWORD(lParam));
  196. case WM_NCPAINT:
  197. DrawFrame(hwnd);
  198. return 0L;
  199. case WM_NCLBUTTONDOWN:
  200. case WM_NCMOUSEMOVE:
  201. case WM_NCLBUTTONUP:
  202. case WM_NCLBUTTONDBLCLK:
  203. case WM_NCRBUTTONDOWN:
  204. case WM_NCRBUTTONUP:
  205. case WM_NCRBUTTONDBLCLK:
  206. case WM_NCMBUTTONDOWN:
  207. case WM_NCMBUTTONUP:
  208. case WM_NCMBUTTONDBLCLK:
  209. case WM_NCACTIVATE: // wParam == active state
  210. case WM_NCCREATE: // Sent before WM_CREATE
  211. case WM_NCDESTROY: // Sent before WM_DESTROY
  212. break;
  213. }
  214. return ::DefWindowProc(hwnd, msg, wParam, lParam);
  215. }
  216. //+---------------------------------------------------------------
  217. //
  218. // Member: InPlaceBorder::InPlaceBorder
  219. //
  220. //---------------------------------------------------------------
  221. InPlaceBorder::InPlaceBorder(void)
  222. {
  223. _fParentActive = TRUE;
  224. _fUIActive = FALSE;
  225. _hwnd = NULL;
  226. _pSite = NULL;
  227. _cResizing = 0;
  228. _cxFrame = _cyFrame = IPBORDER_THICKNESS;
  229. if(_cUsage++ == 0)
  230. {
  231. // the following could fail and we would be hosed...
  232. _hbrActiveCaption = CreateHatchBrush(HS_BDIAGONAL,
  233. GetSysColor(COLOR_ACTIVECAPTION));
  234. _hbrInActiveCaption = CreateHatchBrush(HS_BDIAGONAL,
  235. GetSysColor(COLOR_WINDOWFRAME));
  236. }
  237. }
  238. //+---------------------------------------------------------------
  239. //
  240. // Member: InPlaceBorder::~InPlaceBorder
  241. //
  242. //---------------------------------------------------------------
  243. InPlaceBorder::~InPlaceBorder(void)
  244. {
  245. if(--_cUsage == 0)
  246. {
  247. DeleteObject(_hbrActiveCaption);
  248. _hbrActiveCaption = NULL;
  249. DeleteObject(_hbrInActiveCaption);
  250. _hbrInActiveCaption = NULL;
  251. }
  252. }
  253. //+---------------------------------------------------------------
  254. //
  255. // Member: InPlaceBorder::SetState
  256. //
  257. //Change the border state: reflected in the nonclient window border
  258. //---------------------------------------------------------------
  259. void
  260. InPlaceBorder::SetUIActive(BOOL fUIActive)
  261. {
  262. if(_hwnd == NULL)
  263. return;
  264. if(_fUIActive != fUIActive)
  265. {
  266. RECT rcClient;
  267. GetChildWindowRect(_hwnd, &rcClient);
  268. int cx = rcClient.right - rcClient.left;
  269. int cy = rcClient.bottom - rcClient.top;
  270. int x = rcClient.left;
  271. int y = rcClient.top;
  272. BOOL fResize = FALSE;
  273. if (fUIActive)
  274. {
  275. fResize = TRUE;
  276. cx += _cxFrame * 2;
  277. cy += _cyFrame * 2;
  278. x -= _cxFrame;
  279. y -= _cyFrame;
  280. }
  281. else if (_fUIActive)
  282. {
  283. fResize = TRUE;
  284. cx -= _cxFrame * 2;
  285. cy -= _cyFrame * 2;
  286. x += _cxFrame;
  287. y += _cyFrame;
  288. }
  289. if (fResize)
  290. {
  291. //
  292. //Set our state member up so CalcClientRect generates correct values,
  293. //then move the window (keeping client area same size and position)
  294. //
  295. _fUIActive = fUIActive;
  296. ++_cResizing;
  297. SetWindowPos( _hwnd, NULL, x, y, cx, cy, SWP_FRAMECHANGED |
  298. SWP_NOACTIVATE | SWP_NOZORDER);
  299. RedrawFrame();
  300. _cResizing--;
  301. }
  302. else
  303. {
  304. InvalidateFrame();
  305. }
  306. }
  307. _fUIActive = fUIActive;
  308. }
  309. //+---------------------------------------------------------------
  310. //
  311. // Member: InPlaceBorder::SetSize
  312. //
  313. //---------------------------------------------------------------
  314. void
  315. InPlaceBorder::SetSize(HWND hwnd, RECT& rc)
  316. {
  317. int cx = rc.right - rc.left;
  318. int cy = rc.bottom - rc.top;
  319. int x = rc.left;
  320. int y = rc.top;
  321. if(_fUIActive)
  322. {
  323. cx += _cxFrame * 2;
  324. cy += _cyFrame * 2;
  325. x -= _cxFrame;
  326. y -= _cyFrame;
  327. }
  328. ++_cResizing;
  329. MoveWindow(hwnd, x, y, cx, cy, TRUE);
  330. _cResizing--;
  331. }
  332. //+---------------------------------------------------------------
  333. //
  334. // Member: InPlaceBorder::Erase
  335. //
  336. // Force border state to non-UIActive, managing the coresponding
  337. // change in border appearance
  338. //
  339. //---------------------------------------------------------------
  340. void
  341. InPlaceBorder::Erase(void)
  342. {
  343. if(_hwnd == NULL)
  344. return;
  345. SetUIActive(FALSE);
  346. _fParentActive = TRUE;
  347. InvalidateFrame();
  348. RedrawFrame();
  349. }
  350. //+---------------------------------------------------------------
  351. //
  352. // Member: InPlaceBorder::SetBorderSize
  353. //
  354. //---------------------------------------------------------------
  355. void
  356. InPlaceBorder::SetBorderSize( int cx, int cy )
  357. {
  358. if(cx < 0)
  359. cx = 0;
  360. if(cy < 0)
  361. cy = 0;
  362. _cxFrame = cx;
  363. _cyFrame = cy;
  364. InvalidateFrame();
  365. RedrawFrame();
  366. }
  367. //+---------------------------------------------------------------
  368. //
  369. // Member: InPlaceBorder::GetBorderSize
  370. //
  371. //---------------------------------------------------------------
  372. void
  373. InPlaceBorder::GetBorderSize( LPINT pcx, LPINT pcy )
  374. {
  375. *pcx = _cxFrame;
  376. *pcy = _cyFrame;
  377. }
  378. //+---------------------------------------------------------------
  379. //
  380. // Member: InPlaceBorder::Attach
  381. //
  382. //---------------------------------------------------------------
  383. void
  384. InPlaceBorder::Attach(HWND hwnd, BOOL fUIActive)
  385. {
  386. if((_hwnd = hwnd) != NULL)
  387. {
  388. SetUIActive(fUIActive);
  389. InvalidateFrame(); //force first-time NCCALC
  390. }
  391. }
  392. void
  393. InPlaceBorder::Bind(LPOLEINPLACESITE pSite, HWND hwnd, BOOL fUIActive)
  394. {
  395. _pSite = NULL;
  396. if((_hwnd = hwnd) != NULL && (_pSite = pSite) != NULL)
  397. {
  398. SetUIActive(fUIActive);
  399. InvalidateFrame(); //force first-time NCCALC
  400. }
  401. }