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.

901 lines
24 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. hatchwnd.h
  5. Abstract:
  6. Implementation of the CHatchWin class. CHatchWin when used
  7. as a parent window creates a thin hatch border around
  8. the child window.
  9. --*/
  10. #include <windows.h>
  11. #include <oleidl.h>
  12. #include "hatchwnd.h"
  13. #include "resource.h"
  14. #include "globals.h"
  15. // Hit codes for computing handle code (Y_CODE + 3 * X_CODE)
  16. #define Y_TOP 0
  17. #define Y_MIDDLE 1
  18. #define Y_BOTTOM 2
  19. #define X_LEFT 0
  20. #define X_MIDDLE 1
  21. #define X_RIGHT 2
  22. #define NO_HIT -1
  23. // Sizing flags
  24. #define SIZING_TOP 0x0001
  25. #define SIZING_BOTTOM 0x0002
  26. #define SIZING_LEFT 0x0004
  27. #define SIZING_RIGHT 0x0008
  28. #define SIZING_ALL 0x0010
  29. // Sizing flags lookup (indexed by handle code)
  30. static UINT uSizingTable[9] = {
  31. SIZING_LEFT | SIZING_TOP, SIZING_TOP, SIZING_RIGHT | SIZING_TOP,
  32. SIZING_LEFT, SIZING_ALL, SIZING_RIGHT,
  33. SIZING_LEFT | SIZING_BOTTOM, SIZING_BOTTOM, SIZING_BOTTOM | SIZING_RIGHT };
  34. // Cursor ID lookup (indexed by handle code)
  35. static UINT uCursIDTable[9] = {
  36. IDC_CURS_NWSE, IDC_CURS_NS, IDC_CURS_NESW,
  37. IDC_CURS_WE, IDC_CURS_MOVE, IDC_CURS_WE,
  38. IDC_CURS_NESW, IDC_CURS_NS, IDC_CURS_NWSE
  39. };
  40. // Cursors (indexed by cursor ID)
  41. static HCURSOR hCursTable[IDC_CURS_MAX - IDC_CURS_MIN + 1];
  42. #define IDTIMER_DEBOUNCE 1
  43. #define MIN_SIZE 8
  44. // Brush patterns
  45. static WORD wHatchBmp[]={0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88};
  46. static WORD wGrayBmp[]={0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa};
  47. static HBRUSH hBrHatch;
  48. static HBRUSH hBrGray;
  49. // System parameters
  50. static INT iBorder;
  51. static INT iDragMinDist;
  52. static INT iDragDelay;
  53. static INT fLocalInit = FALSE;
  54. // Forward refs
  55. void DrawShading(HDC, LPRECT);
  56. void DrawHandles (HDC, LPRECT);
  57. void DrawDragRgn (HWND, HRGN);
  58. HRGN CreateDragRgn(LPRECT);
  59. WCHAR szHatchWinClassName[] = L"Hatchwin" ;
  60. /*
  61. * CHatchWin:CHatchWin
  62. * CHatchWin::~CHatchWin
  63. *
  64. * Constructor Parameters:
  65. * hInst HINSTANCE of the application we're in.
  66. */
  67. CHatchWin::CHatchWin(
  68. VOID
  69. )
  70. {
  71. m_hWnd = NULL;
  72. m_hWndParent = NULL;
  73. m_hWndKid = NULL;
  74. m_hWndAssociate = NULL;
  75. m_hRgnDrag = NULL;
  76. m_iBorder = 0;
  77. m_uID = 0;
  78. m_uDragMode = DRAG_IDLE;
  79. m_bResizeInProgress = FALSE;
  80. SetRect(&m_rcPos, 0, 0, 0, 0);
  81. SetRect(&m_rcClip, 0, 0, 0, 0);
  82. return;
  83. }
  84. CHatchWin::~CHatchWin(void)
  85. {
  86. if (NULL != m_hWnd)
  87. DestroyWindow(m_hWnd);
  88. return;
  89. }
  90. /*
  91. * CHatchWin::Init
  92. *
  93. * Purpose:
  94. * Instantiates a hatch window within a given parent with a
  95. * default rectangle. This is not initially visible.
  96. *
  97. * Parameters:
  98. * hWndParent HWND of the parent of this window
  99. * uID UINT identifier for this window (send in
  100. * notifications to associate window).
  101. * hWndAssoc HWND of the initial associate.
  102. *
  103. * Return Value:
  104. * BOOL TRUE if the function succeeded, FALSE otherwise.
  105. */
  106. BOOL CHatchWin::Init(HWND hWndParent, UINT uID, HWND hWndAssoc)
  107. {
  108. INT i;
  109. HBITMAP hBM;
  110. WNDCLASS wc;
  111. LONG_PTR lptrID = 0;
  112. BEGIN_CRITICAL_SECTION
  113. // If first time through
  114. if (pstrRegisteredClasses[HATCH_WNDCLASS] == NULL) {
  115. // Register the hatch window class
  116. wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  117. wc.hInstance = g_hInstance;
  118. wc.cbClsExtra = 0;
  119. wc.lpfnWndProc = HatchWndProc;
  120. wc.cbWndExtra = CBHATCHWNDEXTRA;
  121. wc.hIcon = NULL;
  122. wc.hCursor = NULL;
  123. wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  124. wc.lpszMenuName = NULL;
  125. wc.lpszClassName = szHatchWinClassName;
  126. if (RegisterClass(&wc)) {
  127. // Save class name for later unregistering
  128. pstrRegisteredClasses[HATCH_WNDCLASS] = szHatchWinClassName;
  129. // Get system metrics
  130. iBorder = GetProfileInt(TEXT("windows"),
  131. TEXT("OleInPlaceBorderWidth"), 4);
  132. iDragMinDist = GetProfileInt(TEXT("windows"),
  133. TEXT("DragMinDist"), DD_DEFDRAGMINDIST);
  134. iDragDelay = GetProfileInt(TEXT("windows"),
  135. TEXT("DragDelay"), DD_DEFDRAGDELAY);
  136. // Load the arrow cursors
  137. for (i = IDC_CURS_MIN; i <= IDC_CURS_MAX; i++) {
  138. hCursTable[i - IDC_CURS_MIN] = LoadCursor(g_hInstance, MAKEINTRESOURCE(i));
  139. }
  140. // Create brushes for hatching and drag region
  141. hBM = CreateBitmap(8, 8, 1, 1, wHatchBmp);
  142. if ( NULL != hBM ) {
  143. hBrHatch = CreatePatternBrush(hBM);
  144. DeleteObject(hBM);
  145. }
  146. hBM = CreateBitmap(8, 8, 1, 1, wGrayBmp);
  147. if ( NULL != hBM ) {
  148. hBrGray = CreatePatternBrush(hBM);
  149. DeleteObject(hBM);
  150. }
  151. }
  152. }
  153. END_CRITICAL_SECTION
  154. if (pstrRegisteredClasses[HATCH_WNDCLASS] == NULL)
  155. return FALSE;
  156. lptrID = uID;
  157. m_hWnd = CreateWindowEx(
  158. WS_EX_NOPARENTNOTIFY,
  159. szHatchWinClassName,
  160. szHatchWinClassName,
  161. WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
  162. 0,
  163. 0,
  164. 100,
  165. 100,
  166. hWndParent,
  167. (HMENU)lptrID,
  168. g_hInstance,
  169. this);
  170. m_uID = uID;
  171. m_hWndAssociate = hWndAssoc;
  172. m_hWndParent = hWndParent;
  173. return (NULL != m_hWnd);
  174. }
  175. /*
  176. * CHatchWin::HwndAssociateSet
  177. * CHatchWin::HwndAssociateGet
  178. *
  179. * Purpose:
  180. * Sets (Set) or retrieves (Get) the associate window of the
  181. * hatch window.
  182. *
  183. * Parameters: (Set only)
  184. * hWndAssoc HWND to set as the associate.
  185. *
  186. * Return Value:
  187. * HWND Previous (Set) or current (Get) associate
  188. * window.
  189. */
  190. HWND CHatchWin::HwndAssociateSet(HWND hWndAssoc)
  191. {
  192. HWND hWndT = m_hWndAssociate;
  193. m_hWndAssociate = hWndAssoc;
  194. return hWndT;
  195. }
  196. HWND CHatchWin::HwndAssociateGet(void)
  197. {
  198. return m_hWndAssociate;
  199. }
  200. /*
  201. * CHatchWin::RectsSet
  202. *
  203. * Purpose:
  204. * Changes the size and position of the hatch window and the child
  205. * window within it using a position rectangle for the child and
  206. * a clipping rectangle for the hatch window and child. The hatch
  207. * window occupies prcPos expanded by the hatch border and clipped
  208. * by prcClip. The child window is fit to prcPos to give the
  209. * proper scaling, but it clipped to the hatch window which
  210. * therefore clips it to prcClip without affecting the scaling.
  211. *
  212. * Parameters:
  213. * prcPos LPRECT providing the position rectangle.
  214. * prcClip LPRECT providing the clipping rectangle.
  215. *
  216. * Return Value:
  217. * None
  218. */
  219. void CHatchWin::RectsSet(LPRECT prcPos, LPRECT prcClip)
  220. {
  221. RECT rc;
  222. RECT rcPos;
  223. UINT uPosFlags = SWP_NOZORDER | SWP_NOACTIVATE;
  224. BOOL bChanged = TRUE;
  225. // If new rectangles, save them
  226. if (prcPos != NULL) {
  227. bChanged = !EqualRect ( prcPos, &m_rcPos );
  228. m_rcPos = *prcPos;
  229. // If clipping rect supplied, use it
  230. // else just use the position rect again
  231. if (prcClip != NULL) {
  232. if ( !bChanged )
  233. bChanged = !EqualRect ( prcClip, &m_rcClip );
  234. m_rcClip = *prcClip;
  235. } else {
  236. m_rcClip = m_rcPos;
  237. }
  238. }
  239. if ( bChanged ) {
  240. // Expand position rect to include hatch border
  241. rcPos = m_rcPos;
  242. InflateRect(&rcPos, m_iBorder, m_iBorder);
  243. // Clip with clipping rect to get actual window rect
  244. IntersectRect(&rc, &rcPos, &m_rcClip);
  245. // Save hatch wnd origin relative to clipped window
  246. m_ptHatchOrg.x = rcPos.left - rc.left;
  247. m_ptHatchOrg.y = rcPos.top - rc.top;
  248. // Set flag to avoid reentrant call from window proc
  249. m_bResizeInProgress = TRUE;
  250. // Offset child window from hatch rect by border width
  251. // (maintaining its original size)
  252. SetWindowPos(m_hWndKid, NULL, m_ptHatchOrg.x + m_iBorder, m_ptHatchOrg.y + m_iBorder,
  253. m_rcPos.right - m_rcPos.left, m_rcPos.bottom - m_rcPos.top, uPosFlags);
  254. // Position the hatch window
  255. SetWindowPos(m_hWnd, NULL, rc.left, rc.top, rc.right - rc.left,
  256. rc.bottom - rc.top, uPosFlags);
  257. m_bResizeInProgress = FALSE;
  258. }
  259. // This is here to ensure that the control background gets redrawn
  260. // On a UI deactivate, the VC test container erases the control window
  261. // between the WM_ERASEBKGND and WM_PAINT, so the background ends up
  262. // the container color instead of the control color
  263. if (m_iBorder == 0)
  264. InvalidateRect(m_hWndKid, NULL, TRUE);
  265. return;
  266. }
  267. /*
  268. * CHatchWin::ChildSet
  269. *
  270. * Purpose:
  271. * Assigns a child window to this hatch window.
  272. *
  273. * Parameters:
  274. * hWndKid HWND of the child window.
  275. *
  276. * Return Value:
  277. * None
  278. */
  279. void CHatchWin::ChildSet(HWND hWndKid)
  280. {
  281. m_hWndKid = hWndKid;
  282. if (NULL != hWndKid)
  283. {
  284. SetParent(hWndKid, m_hWnd);
  285. //Insure this is visible when the hatch window becomes visible.
  286. ShowWindow(hWndKid, SW_SHOW);
  287. }
  288. return;
  289. }
  290. void CHatchWin::OnLeftDown(INT x, INT y)
  291. {
  292. m_ptDown.x = x;
  293. m_ptDown.y = y;
  294. SetCapture(m_hWnd);
  295. m_uDragMode = DRAG_PENDING;
  296. SetTimer(m_hWnd, IDTIMER_DEBOUNCE, iDragDelay, NULL);
  297. }
  298. void CHatchWin::OnLeftUp(void)
  299. {
  300. switch (m_uDragMode) {
  301. case DRAG_PENDING:
  302. KillTimer(m_hWnd, IDTIMER_DEBOUNCE);
  303. ReleaseCapture();
  304. break;
  305. case DRAG_ACTIVE:
  306. // Erase and release drag region
  307. if ( NULL != m_hRgnDrag ) {
  308. DrawDragRgn(m_hWndParent, m_hRgnDrag);
  309. DeleteObject(m_hRgnDrag);
  310. m_hRgnDrag = NULL;
  311. }
  312. ReleaseCapture();
  313. // Inform associated window of change
  314. if ( !EqualRect(&m_rectNew, &m_rcPos) ) {
  315. SendMessage(m_hWndAssociate, WM_COMMAND,
  316. MAKEWPARAM(m_uID, HWN_RESIZEREQUESTED),
  317. (LPARAM)&m_rectNew);
  318. }
  319. break;
  320. }
  321. m_uDragMode = DRAG_IDLE;
  322. }
  323. void CHatchWin::OnMouseMove(INT x, INT y)
  324. {
  325. INT dx, dy;
  326. HRGN hRgnNew, hRgnDiff;
  327. UINT uResizeFlags;
  328. INT iWidth, iHeight;
  329. INT xHit, yHit;
  330. static INT xPrev, yPrev;
  331. if (x == xPrev && y == yPrev)
  332. return;
  333. xPrev = x;
  334. yPrev = y;
  335. switch (m_uDragMode)
  336. {
  337. case DRAG_IDLE:
  338. // Adjust to hatch window coordinates
  339. x -= m_ptHatchOrg.x;
  340. y -= m_ptHatchOrg.y;
  341. iWidth = m_rcPos.right - m_rcPos.left + 2 * m_iBorder;
  342. iHeight = m_rcPos.bottom - m_rcPos.top + 2 * m_iBorder;
  343. // Determine if x is within a handle
  344. if (x <= m_iBorder)
  345. xHit = X_LEFT;
  346. else if (x >= iWidth - m_iBorder)
  347. xHit = X_RIGHT;
  348. else if (x >= (iWidth - m_iBorder)/2 && x <= (iWidth + m_iBorder)/2)
  349. xHit = X_MIDDLE;
  350. else
  351. xHit = NO_HIT;
  352. // Determine is y within a handle
  353. if (y <= m_iBorder)
  354. yHit = Y_TOP;
  355. else if (y >= iHeight - m_iBorder)
  356. yHit = Y_BOTTOM;
  357. else if (y > (iHeight - m_iBorder)/2 && y < (iHeight + m_iBorder)/2)
  358. yHit = Y_MIDDLE;
  359. else
  360. yHit = NO_HIT;
  361. // Compute handle code
  362. // if no handle hit, set to 4 (drag full object)
  363. if (xHit != NO_HIT && yHit != NO_HIT)
  364. m_uHdlCode = xHit + 3 * yHit;
  365. else
  366. m_uHdlCode = 4;
  367. // Set cursor to match handle
  368. SetCursor(hCursTable[uCursIDTable[m_uHdlCode] - IDC_CURS_MIN]);
  369. break;
  370. case DRAG_PENDING:
  371. // Start resize if movement threshold exceeded
  372. dx = (x >= m_ptDown.x) ? (x - m_ptDown.x) : (m_ptDown.x - x);
  373. dy = (y >= m_ptDown.y) ? (y - m_ptDown.y) : (m_ptDown.y - y);
  374. if (dx > iDragMinDist || dy > iDragMinDist) {
  375. KillTimer(m_hWnd, IDTIMER_DEBOUNCE);
  376. // Create and display initial drag region
  377. m_hRgnDrag = CreateDragRgn(&m_rcPos);
  378. if ( NULL != m_hRgnDrag ) {
  379. DrawDragRgn(m_hWndParent, m_hRgnDrag);
  380. // Initialize new rect
  381. m_rectNew = m_rcPos;
  382. m_uDragMode = DRAG_ACTIVE;
  383. }
  384. }
  385. break;
  386. case DRAG_ACTIVE:
  387. dx = x - m_ptDown.x;
  388. dy = y - m_ptDown.y;
  389. // Compute new rect by applying deltas to selected edges
  390. // of original position rect
  391. uResizeFlags = uSizingTable[m_uHdlCode];
  392. if (uResizeFlags & SIZING_ALL) {
  393. m_rectNew.left = m_rcPos.left + dx;
  394. m_rectNew.top = m_rcPos.top + dy;
  395. m_rectNew.right = m_rcPos.right + dx;
  396. m_rectNew.bottom = m_rcPos.bottom + dy;
  397. } else {
  398. if (uResizeFlags & SIZING_TOP) {
  399. m_rectNew.top = m_rcPos.top + dy;
  400. if (m_rectNew.bottom - m_rectNew.top < MIN_SIZE)
  401. m_rectNew.top = m_rectNew.bottom - MIN_SIZE;
  402. }
  403. if (uResizeFlags & SIZING_BOTTOM) {
  404. m_rectNew.bottom = m_rcPos.bottom + dy;
  405. if (m_rectNew.bottom - m_rectNew.top < MIN_SIZE)
  406. m_rectNew.bottom = m_rectNew.top + MIN_SIZE;
  407. }
  408. if (uResizeFlags & SIZING_LEFT) {
  409. m_rectNew.left = m_rcPos.left + dx;
  410. if (m_rectNew.right - m_rectNew.left < MIN_SIZE)
  411. m_rectNew.left = m_rectNew.right - MIN_SIZE;
  412. }
  413. if (uResizeFlags & SIZING_RIGHT) {
  414. m_rectNew.right = m_rcPos.right + dx;
  415. if (m_rectNew.right - m_rectNew.left < MIN_SIZE)
  416. m_rectNew.right = m_rectNew.left + MIN_SIZE;
  417. }
  418. }
  419. // Compute new drag region
  420. hRgnNew = CreateDragRgn(&m_rectNew);
  421. if ( NULL != hRgnNew ) {
  422. // Repaint difference between old and new regions (No Flicker!)
  423. hRgnDiff = CreateRectRgn(0,0,0,0);
  424. if ( NULL != m_hRgnDrag
  425. && NULL != hRgnDiff ) {
  426. CombineRgn(hRgnDiff, m_hRgnDrag, hRgnNew, RGN_XOR);
  427. DrawDragRgn(m_hWndParent, hRgnDiff);
  428. } else {
  429. DrawDragRgn(m_hWndParent, hRgnNew);
  430. }
  431. if ( NULL != hRgnDiff ) {
  432. DeleteObject ( hRgnDiff );
  433. }
  434. // Update current region
  435. if ( NULL != m_hRgnDrag ) {
  436. DeleteObject(m_hRgnDrag);
  437. }
  438. m_hRgnDrag = hRgnNew;
  439. }
  440. }
  441. }
  442. void CHatchWin::OnTimer()
  443. {
  444. if ( DRAG_PENDING == m_uDragMode ) {
  445. KillTimer(m_hWnd, IDTIMER_DEBOUNCE);
  446. // Create and display initial drag region
  447. m_hRgnDrag = CreateDragRgn(&m_rcPos);
  448. if ( NULL != m_hRgnDrag ) {
  449. DrawDragRgn(m_hWndParent, m_hRgnDrag);
  450. // Initialize new rect
  451. m_rectNew = m_rcPos;
  452. m_uDragMode = DRAG_ACTIVE;
  453. }
  454. }
  455. }
  456. void CHatchWin::OnPaint()
  457. {
  458. HDC hDC;
  459. RECT rc;
  460. PAINTSTRUCT ps;
  461. INT iWidth, iHeight;
  462. hDC = BeginPaint(m_hWnd, &ps);
  463. // setup hatch rect in window's coord system
  464. iWidth = m_rcPos.right - m_rcPos.left + 2 * m_iBorder;
  465. iHeight = m_rcPos.bottom - m_rcPos.top + 2 * m_iBorder;
  466. SetRect(&rc, m_ptHatchOrg.x, m_ptHatchOrg.y,
  467. m_ptHatchOrg.x + iWidth,
  468. m_ptHatchOrg.y + iHeight);
  469. DrawShading(hDC, &rc);
  470. DrawHandles(hDC, &rc);
  471. EndPaint(m_hWnd, &ps);
  472. }
  473. /*
  474. * CHatchWin::ShowHatch
  475. *
  476. * Purpose:
  477. * Turns hatching on and off; turning the hatching off changes
  478. * the size of the window to be exactly that of the child, leaving
  479. * everything else the same. The result is that we don't have
  480. * to turn off drawing because our own WM_PAINT will never be
  481. * called.
  482. *
  483. * Parameters:
  484. * fHatch BOOL indicating to show (TRUE) or hide (FALSE)
  485. the hatching.
  486. *
  487. * Return Value:
  488. * None
  489. */
  490. void CHatchWin::ShowHatch(BOOL fHatch)
  491. {
  492. /*
  493. * All we have to do is set the border to zero and
  494. * call SetRects again with the last rectangles the
  495. * child sent to us.
  496. */
  497. m_iBorder = fHatch ? iBorder : 0;
  498. RectsSet(NULL, NULL);
  499. return;
  500. }
  501. /*
  502. * CHatchWin::Window
  503. *
  504. * Purpose:
  505. * Returns the window handle associated with this object.
  506. *
  507. * Return Value:
  508. * HWND Window handle for this object
  509. */
  510. HWND CHatchWin::Window(void)
  511. {
  512. return m_hWnd;
  513. }
  514. /*
  515. * HatchWndProc
  516. *
  517. * Purpose:
  518. * Standard window procedure for the Hatch Window
  519. */
  520. LRESULT APIENTRY HatchWndProc(HWND hWnd, UINT iMsg
  521. , WPARAM wParam, LPARAM lParam)
  522. {
  523. PCHatchWin phw;
  524. phw = (PCHatchWin)GetWindowLongPtr(hWnd, HWWL_STRUCTURE);
  525. switch (iMsg)
  526. {
  527. case WM_CREATE:
  528. phw = (PCHatchWin)((LPCREATESTRUCT)lParam)->lpCreateParams;
  529. SetWindowLongPtr(hWnd, HWWL_STRUCTURE, (INT_PTR)phw);
  530. break;
  531. case WM_DESTROY:
  532. phw->m_hWnd = NULL;
  533. break;
  534. case WM_PAINT:
  535. phw->OnPaint();
  536. break;
  537. case WM_SIZE:
  538. // If this resize is not due to RectsSet then forward it
  539. // to adjust our internal control window
  540. if (!phw->m_bResizeInProgress)
  541. {
  542. RECT rc;
  543. POINT pt;
  544. // Get new rect in container coords
  545. GetWindowRect(hWnd, &rc);
  546. // Convert to parent client coords
  547. pt.x = pt.y = 0;
  548. ClientToScreen(GetParent(hWnd), &pt);
  549. OffsetRect(&rc,-pt.x, -pt.y);
  550. // Resize control
  551. phw->RectsSet(&rc, NULL);
  552. }
  553. break;
  554. case WM_MOUSEMOVE:
  555. phw->OnMouseMove((short)LOWORD(lParam),(short)HIWORD(lParam));
  556. break;
  557. case WM_LBUTTONDOWN:
  558. phw->OnLeftDown((short)LOWORD(lParam),(short)HIWORD(lParam));
  559. break;
  560. case WM_LBUTTONUP:
  561. phw->OnLeftUp();
  562. break;
  563. case WM_TIMER:
  564. phw->OnTimer();
  565. break;
  566. case WM_SETFOCUS:
  567. //We need this since the container will SetFocus to us.
  568. if (NULL != phw->m_hWndKid)
  569. SetFocus(phw->m_hWndKid);
  570. break;
  571. case WM_LBUTTONDBLCLK:
  572. /*
  573. * If the double click was within m_dBorder of an
  574. * edge, send the HWN_BORDERDOUBLECLICKED notification.
  575. *
  576. * Because we're always sized just larger than our child
  577. * window by the border width, we can only *get* this
  578. * message when the mouse is on the border. So we can
  579. * just send the notification.
  580. */
  581. if (NULL!=phw->m_hWndAssociate)
  582. {
  583. SendMessage(phw->m_hWndAssociate, WM_COMMAND,
  584. MAKEWPARAM(phw->m_uID,HWN_BORDERDOUBLECLICKED),
  585. (LPARAM)hWnd);
  586. }
  587. break;
  588. default:
  589. return DefWindowProc(hWnd, iMsg, wParam, lParam);
  590. }
  591. return 0L;
  592. }
  593. HRGN CreateDragRgn(LPRECT pRect)
  594. {
  595. HRGN hRgnIn;
  596. HRGN hRgnOut;
  597. HRGN hRgnRet = NULL;
  598. if ( NULL != pRect ) {
  599. hRgnRet = CreateRectRgn(0,0,0,0);
  600. hRgnIn = CreateRectRgn(pRect->left, pRect->top,pRect->right, pRect->bottom);
  601. hRgnOut = CreateRectRgn(pRect->left - iBorder, pRect->top - iBorder,
  602. pRect->right + iBorder, pRect->bottom + iBorder);
  603. if ( NULL != hRgnOut
  604. && NULL != hRgnIn
  605. && NULL != hRgnRet ) {
  606. CombineRgn(hRgnRet, hRgnOut, hRgnIn, RGN_DIFF);
  607. }
  608. if ( NULL != hRgnIn ) {
  609. DeleteObject(hRgnIn);
  610. }
  611. if ( NULL != hRgnOut ) {
  612. DeleteObject(hRgnOut);
  613. }
  614. }
  615. return hRgnRet;
  616. }
  617. void DrawDragRgn(HWND hWnd, HRGN hRgn)
  618. {
  619. LONG lWndStyle;
  620. INT iMapMode;
  621. HDC hDC;
  622. RECT rc;
  623. HBRUSH hBr;
  624. COLORREF crText;
  625. // Turn off clipping by children
  626. lWndStyle = GetWindowLong(hWnd, GWL_STYLE);
  627. SetWindowLong(hWnd, GWL_STYLE, lWndStyle & ~WS_CLIPCHILDREN);
  628. // Prepare DC
  629. hDC = GetDC(hWnd);
  630. if ( NULL != hDC ) {
  631. iMapMode = SetMapMode(hDC, MM_TEXT);
  632. hBr = (HBRUSH)SelectObject(hDC, hBrGray);
  633. crText = SetTextColor(hDC, RGB(255, 255, 255));
  634. SelectClipRgn(hDC, hRgn);
  635. GetClipBox(hDC, &rc);
  636. PatBlt(hDC, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATINVERT);
  637. // Restore DC
  638. SelectObject(hDC, hBr);
  639. SetTextColor(hDC, crText);
  640. SetMapMode(hDC, iMapMode);
  641. SelectClipRgn(hDC, NULL);
  642. ReleaseDC(hWnd, hDC);
  643. }
  644. SetWindowLong(hWnd, GWL_STYLE, lWndStyle);
  645. }
  646. /*
  647. * DrawShading
  648. *
  649. * Purpose:
  650. * Draw a hatch border ourside the rectable given.
  651. *
  652. * Parameters:
  653. * prc LPRECT containing the rectangle.
  654. * hDC HDC on which to draw.
  655. * cWidth UINT width of the border to draw. Ignored
  656. * if dwFlags has UI_SHADE_FULLRECT.
  657. *
  658. * Return Value:
  659. * None
  660. */
  661. void DrawShading(HDC hDC, LPRECT prc)
  662. {
  663. HBRUSH hBROld;
  664. RECT rc;
  665. UINT cx, cy;
  666. COLORREF crText;
  667. COLORREF crBk;
  668. const DWORD dwROP = 0x00A000C9L; //DPa
  669. if (NULL==prc || NULL==hDC)
  670. return;
  671. hBROld = (HBRUSH)SelectObject(hDC, hBrHatch);
  672. rc = *prc;
  673. cx = rc.right - rc.left;
  674. cy = rc.bottom - rc.top;
  675. crText = SetTextColor(hDC, RGB(255, 255, 255));
  676. crBk = SetBkColor(hDC, RGB(0, 0, 0));
  677. PatBlt(hDC, rc.left, rc.top, cx, iBorder, dwROP);
  678. PatBlt(hDC, rc.left, rc.top, iBorder, cy, dwROP);
  679. PatBlt(hDC, rc.right-iBorder, rc.top, iBorder, cy, dwROP);
  680. PatBlt(hDC, rc.left, rc.bottom-iBorder, cx, iBorder, dwROP);
  681. SetTextColor(hDC, crText);
  682. SetBkColor(hDC, crBk);
  683. SelectObject(hDC, hBROld);
  684. return;
  685. }
  686. void DrawHandles (HDC hDC, LPRECT prc)
  687. {
  688. HPEN hPenOld;
  689. HBRUSH hBROld;
  690. INT left,right,top,bottom;
  691. #define DrawHandle(x,y) Rectangle(hDC, x, y, (x) + iBorder + 1, (y) + iBorder + 1)
  692. hPenOld = (HPEN)SelectObject(hDC, (HPEN)GetStockObject(BLACK_PEN));
  693. hBROld = (HBRUSH)SelectObject(hDC, (HBRUSH)GetStockObject(BLACK_BRUSH));
  694. left = prc->left;
  695. right = prc->right - iBorder;
  696. top = prc->top;
  697. bottom = prc->bottom - iBorder;
  698. DrawHandle(left, top);
  699. DrawHandle(left, (top + bottom)/2);
  700. DrawHandle(left, bottom);
  701. DrawHandle(right, top);
  702. DrawHandle(right, (top + bottom)/2);
  703. DrawHandle(right, bottom);
  704. DrawHandle((left + right)/2, top);
  705. DrawHandle((left + right)/2, bottom);
  706. SelectObject(hDC, hPenOld);
  707. SelectObject(hDC, hBROld);
  708. }