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.

631 lines
22 KiB

  1. //---------------------------------------------------------------------------
  2. // DrawHelp.cpp - flat drawing helper routines
  3. //---------------------------------------------------------------------------
  4. #include "stdafx.h"
  5. #include "DrawHelp.h"
  6. #include "rgn.h"
  7. #define cxRESIZE (ClassicGetSystemMetrics(SM_CXEDGE)+ClassicGetSystemMetrics( SM_CXSIZEFRAME ))
  8. #define cyRESIZE (ClassicGetSystemMetrics(SM_CYEDGE)+ClassicGetSystemMetrics( SM_CYSIZEFRAME ))
  9. #define cxRESIZEPAD ClassicGetSystemMetrics(SM_CXVSCROLL)
  10. #define cyRESIZEPAD ClassicGetSystemMetrics(SM_CYHSCROLL)
  11. //---------------------------------------------------------------------------
  12. typedef WORD (* HITTESTRECTPROC)(LPCRECT, int, int, const POINT&, WORD);
  13. WORD _HitTestRectCorner( HITTESTRECTPROC, HITTESTRECTPROC, LPCRECT,
  14. int, int, int, int, const POINT&,
  15. WORD, WORD, WORD, WORD );
  16. //---------------------------------------------------------------------------
  17. WORD _HitTestRectLeft(
  18. LPCRECT prc, int cxMargin, int cyMargin, const POINT& pt, WORD wMiss )
  19. {
  20. return ((WORD)((pt.x <= (prc->left + cxMargin)) ? HTLEFT : wMiss));
  21. }
  22. //---------------------------------------------------------------------------
  23. WORD _HitTestRectTop(
  24. LPCRECT prc, int cxMargin, int cyMargin, const POINT& pt, WORD wMiss )
  25. {
  26. return ((WORD)((pt.y <= (prc->top + cyMargin)) ? HTTOP : wMiss));
  27. }
  28. //---------------------------------------------------------------------------
  29. WORD _HitTestRectRight(
  30. LPCRECT prc, int cxMargin, int cyMargin, const POINT& pt, WORD wMiss )
  31. {
  32. return ((WORD)((pt.x >= (prc->right - cxMargin)) ? HTRIGHT : wMiss));
  33. }
  34. //---------------------------------------------------------------------------
  35. WORD _HitTestRectBottom(
  36. LPCRECT prc, int cxMargin, int cyMargin, const POINT& pt, WORD wMiss )
  37. {
  38. return ((WORD)((pt.y >= (prc->bottom - cyMargin)) ? HTBOTTOM : wMiss));
  39. }
  40. //---------------------------------------------------------------------------
  41. WORD _HitTestRectTopLeft(
  42. LPCRECT prc, int cxMargin, int cyMargin, const POINT& pt, WORD wMiss )
  43. {
  44. return _HitTestRectCorner(
  45. _HitTestRectLeft, _HitTestRectTop, prc,
  46. cxMargin, cyMargin, cxRESIZEPAD, cyRESIZEPAD,
  47. pt, HTTOPLEFT, HTLEFT, HTTOP, wMiss );
  48. }
  49. //---------------------------------------------------------------------------
  50. WORD _HitTestRectTopRight(
  51. LPCRECT prc, int cxMargin, int cyMargin, const POINT& pt, WORD wMiss )
  52. {
  53. return _HitTestRectCorner(
  54. _HitTestRectRight, _HitTestRectTop, prc,
  55. cxMargin, cyMargin, cxRESIZEPAD, cyRESIZEPAD,
  56. pt, HTTOPRIGHT, HTRIGHT, HTTOP, wMiss );
  57. }
  58. //---------------------------------------------------------------------------
  59. WORD _HitTestRectBottomLeft(
  60. LPCRECT prc, int cxMargin, int cyMargin, const POINT& pt, WORD wMiss )
  61. {
  62. return _HitTestRectCorner(
  63. _HitTestRectLeft, _HitTestRectBottom, prc,
  64. cxMargin, cyMargin, cxRESIZEPAD, cyRESIZEPAD,
  65. pt, HTBOTTOMLEFT, HTLEFT, HTBOTTOM, wMiss );
  66. }
  67. //---------------------------------------------------------------------------
  68. WORD _HitTestRectBottomRight(
  69. LPCRECT prc, int cxMargin, int cyMargin, const POINT& pt, WORD wMiss )
  70. {
  71. return _HitTestRectCorner(
  72. _HitTestRectRight, _HitTestRectBottom, prc,
  73. cxMargin, cyMargin, cxRESIZEPAD, cyRESIZEPAD,
  74. pt, HTBOTTOMRIGHT, HTRIGHT, HTBOTTOM, wMiss );
  75. }
  76. //---------------------------------------------------------------------------
  77. WORD _HitTestRectCorner(
  78. HITTESTRECTPROC pfnX, HITTESTRECTPROC pfnY,
  79. LPCRECT prc, // target rect
  80. int cxMargin, int cyMargin, // width, height of resizing borders
  81. int cxMargin2, int cyMargin2, // width, height of scrollbars
  82. const POINT& pt, // test point
  83. WORD wHitC, WORD wHitX, WORD wHitY, // winning hittest codes
  84. WORD wMiss ) // losing hittest code
  85. {
  86. WORD wRetX = pfnX( prc, cxMargin, cyMargin, pt, wMiss );
  87. WORD wRetY = pfnY( prc, cxMargin, cyMargin, pt, wMiss );
  88. if( wMiss != wRetX && wMiss != wRetY )
  89. return wHitC;
  90. if( wMiss != wRetX )
  91. {
  92. wMiss = wHitX;
  93. if( wMiss != pfnY( prc, cxMargin2, cyMargin2, pt, wMiss ) )
  94. return wHitC;
  95. }
  96. else if( wMiss != wRetY )
  97. {
  98. wMiss = wHitY;
  99. if( wMiss != pfnX( prc, cxMargin2, cyMargin2, pt, wMiss ) )
  100. return wHitC;
  101. }
  102. return wMiss;
  103. }
  104. //---------------------------------------------------------------------------
  105. WORD HitTest9Grid( LPCRECT prc, const MARGINS& margins, const POINT& pt )
  106. {
  107. ASSERT(PtInRect(prc,pt));
  108. WORD wHit = HTCLIENT;
  109. // test left side
  110. if( HTLEFT == _HitTestRectLeft( prc, margins.cxLeftWidth, 0, pt, wHit ) )
  111. {
  112. if( HTTOP == _HitTestRectTop( prc, 0, margins.cyTopHeight, pt, wHit ) )
  113. return HTTOPLEFT;
  114. if( HTBOTTOM == _HitTestRectBottom( prc, 0, margins.cyBottomHeight, pt, wHit ) )
  115. return HTBOTTOMLEFT;
  116. wHit = HTLEFT;
  117. }
  118. else // test right side
  119. if( HTRIGHT == _HitTestRectRight( prc, margins.cxRightWidth, 0, pt, wHit ) )
  120. {
  121. if( HTTOP == _HitTestRectTop( prc, 0, margins.cyTopHeight, pt, wHit ) )
  122. return HTTOPRIGHT;
  123. if( HTBOTTOM == _HitTestRectBottom( prc, 0, margins.cyBottomHeight, pt, wHit ) )
  124. return HTBOTTOMRIGHT;
  125. wHit = HTRIGHT;
  126. }
  127. else // test top
  128. if( HTTOP == _HitTestRectTop( prc, 0, margins.cyTopHeight, pt, wHit ) )
  129. {
  130. return HTTOP;
  131. }
  132. else // test bottom
  133. if( HTBOTTOM == _HitTestRectBottom( prc, 0, margins.cyBottomHeight, pt, wHit ) )
  134. {
  135. return HTBOTTOM;
  136. }
  137. return wHit;
  138. }
  139. //---------------------------------------------------------------------------
  140. WORD _HitTestResizingRect( DWORD dwHTFlags, LPCRECT prc, const POINT& pt,
  141. WORD w9GridHit, WORD wMiss )
  142. {
  143. WORD wHit = wMiss;
  144. BOOL fTestLeft = TESTFLAG(dwHTFlags, HTTB_RESIZINGBORDER_LEFT);
  145. BOOL fTestTop = TESTFLAG(dwHTFlags, HTTB_RESIZINGBORDER_TOP);
  146. BOOL fTestRight = TESTFLAG(dwHTFlags, HTTB_RESIZINGBORDER_RIGHT);
  147. BOOL fTestBottom = TESTFLAG(dwHTFlags, HTTB_RESIZINGBORDER_BOTTOM);
  148. BOOL fTestCaption = TESTFLAG( dwHTFlags, HTTB_CAPTION );
  149. switch( w9GridHit )
  150. {
  151. case HTLEFT:
  152. if( fTestLeft )
  153. {
  154. // first test for a hit in the corner resizing areas, respecting caller's option flags.
  155. if( (fTestTop && (wHit = _HitTestRectTopLeft( prc, cxRESIZE, cyRESIZE, pt, wMiss )) != HTLEFT) ||
  156. (fTestBottom && (wHit = _HitTestRectBottomLeft( prc, cxRESIZE, cyRESIZE, pt, wMiss )) != HTLEFT) )
  157. break;
  158. // failed corners, just test the resizing margin within the specified 9-grid hit seg.
  159. wHit = _HitTestRectLeft( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  160. }
  161. break;
  162. case HTTOP:
  163. if( fTestCaption )
  164. wHit = wMiss = HTCAPTION;
  165. if( fTestTop )
  166. {
  167. // first test for a hit in the corner resizing areas, respecting caller's option flags.
  168. if( (fTestLeft && (wHit = _HitTestRectTopLeft( prc, cxRESIZE, cyRESIZE, pt, wMiss )) != HTTOP) ||
  169. (fTestRight && (wHit = _HitTestRectTopRight( prc, cxRESIZE, cyRESIZE, pt, wMiss )) != HTTOP) )
  170. break;
  171. // failed corners, just test the resizing margin within the specified 9-grid hit seg.
  172. wHit = _HitTestRectTop( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  173. }
  174. break;
  175. case HTRIGHT:
  176. if( fTestRight )
  177. {
  178. // first test for a hit in the corner resizing areas, respecting caller's option flags.
  179. if( (fTestTop && (wHit = _HitTestRectTopRight( prc, cxRESIZE, cyRESIZE, pt, wMiss )) != HTRIGHT) ||
  180. (fTestBottom && (wHit = _HitTestRectBottomRight( prc, cxRESIZE, cyRESIZE, pt, wMiss )) != HTRIGHT) )
  181. break;
  182. // failed corners, just test the resizing margin within the specified 9-grid hit seg.
  183. wHit = _HitTestRectRight( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  184. break;
  185. }
  186. case HTBOTTOM:
  187. if( fTestBottom )
  188. {
  189. // first test for a hit in the corner resizing areas, respecting caller's option flags.
  190. if( (fTestLeft && (wHit = _HitTestRectBottomLeft( prc, cxRESIZE, cyRESIZE, pt, wMiss )) != HTBOTTOM) ||
  191. (fTestRight && (wHit = _HitTestRectBottomRight( prc, cxRESIZE, cyRESIZE, pt, wMiss )) != HTBOTTOM) )
  192. break;
  193. // failed corners, just test the resizing margin within the specified 9-grid hit seg.
  194. wHit = _HitTestRectBottom( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  195. }
  196. break;
  197. case HTTOPLEFT:
  198. if( fTestCaption )
  199. wHit = wMiss = HTCAPTION;
  200. // first test for a resizing hit in the corner, and failing that, test the
  201. // resizing margin on either side.
  202. if( fTestTop && fTestLeft )
  203. wHit = _HitTestRectTopLeft( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  204. else if( fTestLeft )
  205. wHit = _HitTestRectLeft( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  206. else if( fTestTop )
  207. wHit = _HitTestRectTop( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  208. break;
  209. case HTTOPRIGHT:
  210. if( fTestCaption )
  211. wHit = wMiss = HTCAPTION;
  212. // first test for a resizing hit in the corner, and failing that, test the
  213. // resizing margin on either side.
  214. if( fTestTop && fTestRight )
  215. wHit = _HitTestRectTopRight( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  216. else if( fTestRight )
  217. wHit = _HitTestRectRight( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  218. else if( fTestTop )
  219. wHit = _HitTestRectTop( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  220. break;
  221. case HTBOTTOMLEFT:
  222. // first test for a resizing hit in the corner, and failing that, test the
  223. // resizing margin on either side.
  224. if( fTestBottom && fTestLeft )
  225. wHit = _HitTestRectBottomLeft( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  226. else if( fTestLeft )
  227. wHit = _HitTestRectLeft( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  228. else if( fTestBottom )
  229. wHit = _HitTestRectBottom( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  230. break;
  231. case HTBOTTOMRIGHT:
  232. // first test for a resizing hit in the corner, and failing that, test the
  233. // resizing margin on either side.
  234. if( fTestBottom && fTestRight )
  235. wHit = _HitTestRectBottomRight( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  236. else if( fTestRight )
  237. wHit = _HitTestRectRight( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  238. else if( fTestBottom )
  239. wHit = _HitTestRectBottom( prc, cxRESIZE, cyRESIZE, pt, wMiss );
  240. break;
  241. }
  242. return wHit;
  243. }
  244. //---------------------------------------------------------------------------
  245. WORD HitTestRect(DWORD dwHTFlags, LPCRECT prc, const MARGINS& margins, const POINT& pt )
  246. {
  247. WORD wHit = HTNOWHERE;
  248. if( PtInRect( prc, pt ) )
  249. {
  250. wHit = HitTest9Grid( prc, margins, pt );
  251. if( HTCLIENT != wHit )
  252. {
  253. if( TESTFLAG(dwHTFlags, HTTB_RESIZINGBORDER) )
  254. {
  255. WORD wMiss = HTBORDER;
  256. wHit = _HitTestResizingRect( dwHTFlags, prc, pt, wHit, wMiss );
  257. }
  258. else if( TESTFLAG(dwHTFlags, HTTB_CAPTION|HTTB_FIXEDBORDER) )
  259. {
  260. switch( wHit )
  261. {
  262. case HTTOP:
  263. case HTTOPLEFT:
  264. case HTTOPRIGHT:
  265. wHit = (WORD)(TESTFLAG(dwHTFlags, HTTB_CAPTION) ? HTCAPTION : HTBORDER);
  266. break;
  267. default:
  268. wHit = HTBORDER;
  269. }
  270. }
  271. } // !HTCLIENT
  272. } // PtInRect
  273. return wHit;
  274. }
  275. //---------------------------------------------------------------------------
  276. WORD _HitTestResizingTemplate( DWORD dwHTFlags, HRGN hrgn, const POINT& pt,
  277. WORD w9GridHit, WORD wMiss )
  278. {
  279. WORD wHit = wMiss;
  280. BOOL fTestLeft = TESTFLAG(dwHTFlags, HTTB_RESIZINGBORDER_LEFT);
  281. BOOL fTestTop = TESTFLAG(dwHTFlags, HTTB_RESIZINGBORDER_TOP);
  282. BOOL fTestRight = TESTFLAG(dwHTFlags, HTTB_RESIZINGBORDER_RIGHT);
  283. BOOL fTestBottom = TESTFLAG(dwHTFlags, HTTB_RESIZINGBORDER_BOTTOM);
  284. BOOL fTestCaption = TESTFLAG( dwHTFlags, HTTB_CAPTION );
  285. BOOL fInsideRgn;
  286. switch( w9GridHit )
  287. {
  288. case HTLEFT:
  289. if( !fTestLeft )
  290. {
  291. return wMiss;
  292. }
  293. break;
  294. case HTTOP:
  295. if( fTestCaption )
  296. wMiss = HTCAPTION;
  297. if( !fTestTop )
  298. {
  299. return wMiss;
  300. }
  301. break;
  302. case HTRIGHT:
  303. if( !fTestRight )
  304. {
  305. return wMiss;
  306. }
  307. break;
  308. case HTBOTTOM:
  309. if( !fTestBottom )
  310. {
  311. return wMiss;
  312. }
  313. break;
  314. case HTTOPLEFT:
  315. if( fTestCaption )
  316. wMiss = HTCAPTION;
  317. if( !fTestTop || !fTestLeft )
  318. {
  319. return wMiss;
  320. }
  321. break;
  322. case HTTOPRIGHT:
  323. if( fTestCaption )
  324. wMiss = HTCAPTION;
  325. if( !fTestTop || !fTestRight )
  326. {
  327. return wMiss;
  328. }
  329. break;
  330. case HTBOTTOMLEFT:
  331. if( !fTestBottom || !fTestLeft )
  332. {
  333. return wMiss;
  334. }
  335. break;
  336. case HTBOTTOMRIGHT:
  337. if( !fTestBottom || !fTestRight )
  338. {
  339. return wMiss;
  340. }
  341. break;
  342. }
  343. fInsideRgn = PtInRegion(hrgn, pt.x, pt.y);
  344. if( fInsideRgn )
  345. {
  346. wHit = w9GridHit;
  347. }
  348. return wHit;
  349. }
  350. //---------------------------------------------------------------------------
  351. WORD HitTestTemplate(DWORD dwHTFlags, LPCRECT prc, HRGN hrgn, const MARGINS& margins, const POINT& pt )
  352. {
  353. WORD wHit = HTNOWHERE;
  354. if( PtInRect( prc, pt ) )
  355. {
  356. wHit = HitTest9Grid( prc, margins, pt );
  357. if( HTCLIENT != wHit )
  358. {
  359. if( TESTFLAG(dwHTFlags, HTTB_RESIZINGBORDER) )
  360. {
  361. WORD wMiss = HTBORDER;
  362. wHit = _HitTestResizingTemplate( dwHTFlags, hrgn, pt, wHit, wMiss );
  363. }
  364. else if( TESTFLAG(dwHTFlags, HTTB_CAPTION|HTTB_FIXEDBORDER) )
  365. {
  366. switch( wHit )
  367. {
  368. case HTTOP:
  369. case HTTOPLEFT:
  370. case HTTOPRIGHT:
  371. wHit = (WORD)(TESTFLAG(dwHTFlags, HTTB_CAPTION) ? HTCAPTION : HTBORDER);
  372. break;
  373. default:
  374. wHit = HTBORDER;
  375. }
  376. }
  377. } // !HTCLIENT
  378. }
  379. return wHit;
  380. }
  381. // --------------------------------------------------------------------------
  382. // FillRectClr
  383. //
  384. // History: 2000-12-06 lmouton borrowed from comctl32\v6\cutils.c
  385. //---------------------------------------------------------------------------
  386. void FillRectClr(HDC hdc, LPRECT prc, COLORREF clr)
  387. {
  388. COLORREF clrSave = SetBkColor(hdc, clr);
  389. ExtTextOut(hdc,0,0,ETO_OPAQUE,prc,NULL,0,NULL);
  390. SetBkColor(hdc, clrSave);
  391. }
  392. //---------------------------------------------------------------------------
  393. // _DrawEdge
  394. //
  395. // Classic values are:
  396. // clrLight = 192 192 192
  397. // clrHighlight = 255 255 255
  398. // clrShadow = 128 128 128
  399. // clrDkShadow = 0 0 0
  400. // clrFill = 192 192 192
  401. //
  402. // History: 2000-12-06 lmouton borrowed from comctl32\v6\cutils.c, modified colors
  403. //---------------------------------------------------------------------------
  404. HRESULT _DrawEdge(HDC hdc, const RECT *pDestRect, UINT uEdge, UINT uFlags,
  405. COLORREF clrLight, COLORREF clrHighlight, COLORREF clrShadow, COLORREF clrDkShadow, COLORREF clrFill,
  406. OUT RECT *pContentRect)
  407. {
  408. if (hdc == NULL || pDestRect == NULL)
  409. return E_INVALIDARG;
  410. HRESULT hr = S_OK;
  411. RECT rc, rcD;
  412. UINT bdrType;
  413. COLORREF clrTL = 0;
  414. COLORREF clrBR = 0;
  415. // This is were we would adjust for high DPI if the new "BF_DPISCALE" flag is specified in uFlags.
  416. int cxBorder = GetSystemMetrics(SM_CXBORDER);
  417. int cyBorder = GetSystemMetrics(SM_CYBORDER);
  418. //
  419. // Enforce monochromicity and flatness
  420. //
  421. // if (oemInfo.BitCount == 1)
  422. // uFlags |= BF_MONO;
  423. if (uFlags & BF_MONO)
  424. uFlags |= BF_FLAT;
  425. CopyRect(&rc, pDestRect);
  426. //
  427. // Draw the border segment(s), and calculate the remaining space as we
  428. // go.
  429. //
  430. bdrType = (uEdge & BDR_OUTER);
  431. if (bdrType)
  432. {
  433. DrawBorder:
  434. //
  435. // Get colors. Note the symmetry between raised outer, sunken inner and
  436. // sunken outer, raised inner.
  437. //
  438. if (uFlags & BF_FLAT)
  439. {
  440. if (uFlags & BF_MONO)
  441. clrBR = (bdrType & BDR_OUTER) ? clrDkShadow : clrHighlight;
  442. else
  443. clrBR = (bdrType & BDR_OUTER) ? clrShadow: clrFill;
  444. clrTL = clrBR;
  445. }
  446. else
  447. {
  448. // 5 == HILIGHT
  449. // 4 == LIGHT
  450. // 3 == FACE
  451. // 2 == SHADOW
  452. // 1 == DKSHADOW
  453. switch (bdrType)
  454. {
  455. // +2 above surface
  456. case BDR_RAISEDOUTER: // 5 : 4
  457. clrTL = ((uFlags & BF_SOFT) ? clrHighlight : clrLight);
  458. clrBR = clrDkShadow; // 1
  459. break;
  460. // +1 above surface
  461. case BDR_RAISEDINNER: // 4 : 5
  462. clrTL = ((uFlags & BF_SOFT) ? clrLight : clrHighlight);
  463. clrBR = clrShadow; // 2
  464. break;
  465. // -1 below surface
  466. case BDR_SUNKENOUTER: // 1 : 2
  467. clrTL = ((uFlags & BF_SOFT) ? clrDkShadow : clrShadow);
  468. clrBR = clrHighlight; // 5
  469. break;
  470. // -2 below surface
  471. case BDR_SUNKENINNER: // 2 : 1
  472. clrTL = ((uFlags & BF_SOFT) ? clrShadow : clrDkShadow);
  473. clrBR = clrLight; // 4
  474. break;
  475. default:
  476. hr = E_INVALIDARG;
  477. }
  478. }
  479. if FAILED(hr)
  480. {
  481. return hr;
  482. }
  483. //
  484. // Draw the sides of the border. NOTE THAT THE ALGORITHM FAVORS THE
  485. // BOTTOM AND RIGHT SIDES, since the light source is assumed to be top
  486. // left. If we ever decide to let the user set the light source to a
  487. // particular corner, then change this algorithm.
  488. //
  489. // Bottom Right edges
  490. if (uFlags & (BF_RIGHT | BF_BOTTOM))
  491. {
  492. // Right
  493. if (uFlags & BF_RIGHT)
  494. {
  495. rc.right -= cxBorder;
  496. // PatBlt(hdc, rc.right, rc.top, g_cxBorder, rc.bottom - rc.top, PATCOPY);
  497. rcD.left = rc.right;
  498. rcD.right = rc.right + cxBorder;
  499. rcD.top = rc.top;
  500. rcD.bottom = rc.bottom;
  501. FillRectClr(hdc, &rcD, clrBR);
  502. }
  503. // Bottom
  504. if (uFlags & BF_BOTTOM)
  505. {
  506. rc.bottom -= cyBorder;
  507. // PatBlt(hdc, rc.left, rc.bottom, rc.right - rc.left, g_cyBorder, PATCOPY);
  508. rcD.left = rc.left;
  509. rcD.right = rc.right;
  510. rcD.top = rc.bottom;
  511. rcD.bottom = rc.bottom + cyBorder;
  512. FillRectClr(hdc, &rcD, clrBR);
  513. }
  514. }
  515. // Top Left edges
  516. if (uFlags & (BF_TOP | BF_LEFT))
  517. {
  518. // Left
  519. if (uFlags & BF_LEFT)
  520. {
  521. // PatBlt(hdc, rc.left, rc.top, g_cxBorder, rc.bottom - rc.top, PATCOPY);
  522. rc.left += cxBorder;
  523. rcD.left = rc.left - cxBorder;
  524. rcD.right = rc.left;
  525. rcD.top = rc.top;
  526. rcD.bottom = rc.bottom;
  527. FillRectClr(hdc, &rcD, clrTL);
  528. }
  529. // Top
  530. if (uFlags & BF_TOP)
  531. {
  532. // PatBlt(hdc, rc.left, rc.top, rc.right - rc.left, g_cyBorder, PATCOPY);
  533. rc.top += cyBorder;
  534. rcD.left = rc.left;
  535. rcD.right = rc.right;
  536. rcD.top = rc.top - cyBorder;
  537. rcD.bottom = rc.top;
  538. FillRectClr(hdc, &rcD, clrTL);
  539. }
  540. }
  541. }
  542. bdrType = (uEdge & BDR_INNER);
  543. if (bdrType)
  544. {
  545. //
  546. // Strip this so the next time through, bdrType will be 0.
  547. // Otherwise, we'll loop forever.
  548. //
  549. uEdge &= ~BDR_INNER;
  550. goto DrawBorder;
  551. }
  552. //
  553. // Fill the middle & clean up if asked
  554. //
  555. if (uFlags & BF_MIDDLE)
  556. FillRectClr(hdc, &rc, (uFlags & BF_MONO) ? clrHighlight : clrFill);
  557. if ((uFlags & BF_ADJUST) && (pContentRect != NULL))
  558. CopyRect(pContentRect, &rc);
  559. return hr;
  560. }