home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / BOCOLE.PAK / BHATCH.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  27.0 KB  |  820 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // Copyright (c) 1994, 1996 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.7  $
  6. //
  7. // An implementation of the hatched border around inplace active windows.
  8. //
  9. //  Modifications to OLE2UI version:
  10. //    - C++ version
  11. //    - removed restriction that parent must be non-null in CreateHatchWindow
  12. //    - changed window from a child to a popup to allow null parent
  13. //    - "extra bytes" removed in favor of member data
  14. //    - added Paint() and InitWidth() to unclutter wnd proc
  15. //    - added hit testing and correct cursors for handles
  16. //    - added resizing for handles
  17. //    - added NegotiateSize() to mediate inplace size negotiations between
  18. //      the container and the server
  19. //----------------------------------------------------------------------------
  20. #include "BOle.h"
  21.  
  22. #define STRICT
  23. #include "OLE2UI.h"
  24. #include "BHatch.h"
  25.  
  26. // class name of hatch window
  27.   #define CLASS_HATCH TEXT("BOle Hatch Window")
  28.  
  29. // local function prototypes
  30. LRESULT FAR PASCAL EXPORT BOleHatchWndProc (HWND, UINT, WPARAM, LPARAM);
  31.  
  32. // static initializer
  33. UINT BOleHatchWindow::hatchWidth = 0;
  34.  
  35. // global functions
  36. void SetRectExt (LPRECT r, UINT x, UINT y, UINT extent)
  37. {
  38.     r->left = x;
  39.     r->top = y;
  40.     r->right = x + extent;
  41.     r->bottom = y + extent;
  42. }
  43.  
  44. BOleHatchWindow::BOleHatchWindow(HWND hWndParent, HINSTANCE hInst, BOleSite *p)
  45. {
  46.   pBack = p; // assign BOleSite
  47.   hWndHatch = ::CreateWindowEx(
  48.     0,
  49.     CLASS_HATCH,    // Class name
  50.     TEXT ("Hatch Window"), // Window name
  51.     WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  52.     0, 0, 0, 0,
  53.     GetDesktopWindow(),
  54.     (HMENU)NULL,
  55.     hInst,
  56.     this
  57.   );
  58.  
  59.   hatchRect.left = hatchRect.top = hatchRect.bottom = hatchRect.right = 0;
  60.   MoveRect.left = MoveRect.top = MoveRect.bottom = MoveRect.right = 0;
  61.   nClippedFlag = 0;
  62.   pSite = NULL;
  63.   fInMouseDown = FALSE;
  64.   GrayFrame = NULL;
  65. }
  66.  
  67. //***************************************************************************
  68. // Destructor: ~BOleHatchWindow
  69. //
  70. // Purpose:
  71. //              Public destructor to destroy the hWnd
  72. //
  73. //***************************************************************************
  74. BOleHatchWindow::~BOleHatchWindow ()
  75. {
  76.     if (hWndHatch)
  77.         ::DestroyWindow (hWndHatch);
  78. }
  79.  
  80. //***************************************************************************
  81. // Static member function: Register
  82. //
  83. // Purpose:
  84. //      Register the hatch window
  85. //
  86. // Parameters:
  87. //      hInst                   Process instance
  88. //
  89. // Return Value:
  90. //      TRUE                    if successful
  91. //      FALSE                   if failed
  92. //
  93. //***************************************************************************
  94. BOOL BOleHatchWindow::Register (HINSTANCE hInst)
  95. {
  96.   WNDCLASS wc;
  97.  
  98.   // Register Hatch Window Class
  99.   wc.style = CS_BYTEALIGNWINDOW;
  100.   wc.lpfnWndProc = BOleHatchWndProc;
  101.   wc.cbClsExtra = 0;
  102.   wc.cbWndExtra = sizeof(BOleHatchWindow*);    // 'this' in extra bytes
  103.   wc.hInstance = hInst;
  104.   wc.hIcon = NULL;
  105.   wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  106.   wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  107.   wc.lpszMenuName = NULL;
  108.   wc.lpszClassName = CLASS_HATCH;
  109.  
  110.   if (!::RegisterClass(&wc))
  111.     return FALSE;
  112.   else
  113.     return TRUE;
  114. }
  115.  
  116. //***************************************************************************
  117. // Static member function: InitWidth
  118. //
  119. // Purpose:
  120. //              Initialize hatch border with from WIN.INI
  121. //
  122. //***************************************************************************
  123. void BOleHatchWindow::InitWidth ()
  124. {
  125.   hatchWidth = GetProfileInt (TEXT ("windows"), TEXT ("oleinplaceborderwidth"),
  126.                  DEFAULT_HATCHBORDER_WIDTH);
  127. }
  128.  
  129. //***************************************************************************
  130. // Member function: GetWidth
  131. //
  132. // Purpose:
  133. //      Get width of hatch border
  134. //
  135. // Parameters:          None
  136. //
  137. // Return Value:
  138. //    UINT                                      width of the hatch border
  139. //***************************************************************************
  140. UINT BOleHatchWindow::GetWidth ()
  141. {
  142.     if (!::IsWindow(hWndHatch))
  143.         return 0;
  144.  
  145.     return hatchWidth;
  146. }
  147.  
  148. //****************************************************************
  149. // window messages related member functions
  150. //
  151. // Purpose:
  152. //              Window Procedure dispatches all messages here.
  153. //      Each member functions got the message name.
  154. //              Do messages processing here.
  155. //              Refer to windows help to get information about messages
  156. //
  157. //****************************************************************
  158.  
  159. //****************************************************************
  160. // Member function: wmCreate
  161. //
  162. // Parameters:
  163. //                      LPCREATESTRUCT  struct containing information about the window
  164. //                                                                      to be created. Not used
  165. //
  166. // Return Value:
  167. //                      LRESULT                         0L to continue creation process
  168. //
  169. //****************************************************************
  170. LRESULT BOleHatchWindow::wmCreate (LPCREATESTRUCT)
  171. {
  172.     BOleHatchWindow::InitWidth ();
  173.     return 0L;
  174. }
  175.  
  176. //***************************************************************************
  177. // Member function: wmPaint
  178. //
  179. // Purpose:
  180. //              Draw hatched border and handles
  181. //
  182. // Parameters:                          None
  183. //
  184. // Return Value:
  185. //                      LRESULT                         0L
  186. //
  187. //***************************************************************************
  188. LRESULT BOleHatchWindow::wmPaint ()
  189. {
  190.     HDC hDC;
  191.     PAINTSTRUCT ps;
  192.     RECT rcHatchRect;
  193.  
  194.     hDC = ::BeginPaint(hWndHatch, &ps);
  195.     // get hatchRect to paint hatch border
  196.     //rcHatchRect = hatchRect;
  197.     ::CopyRect (&rcHatchRect, &hatchRect);
  198.     OleUIDrawShading(&rcHatchRect, hDC, OLEUI_SHADE_BORDERIN, hatchWidth);
  199.  
  200.     // get the real visible rect to draw handles
  201.     GetWindowRect(hWndHatch, (LPRECT)&rcHatchRect);
  202.     SetRect((LPRECT)&rcHatchRect,0, 0, rcHatchRect.right-rcHatchRect.left,
  203.                                     rcHatchRect.bottom-rcHatchRect.top);
  204.     ::InflateRect ((LPRECT)&rcHatchRect, -hatchWidth, -hatchWidth);
  205.     OleUIDrawHandles (&rcHatchRect, hDC, OLEUI_HANDLES_OUTSIDE,
  206.         hatchWidth+1, TRUE);
  207.     ::EndPaint (hWndHatch, &ps);
  208.     return 0L;
  209. }
  210.  
  211. //****************************************************************
  212. // Member function: wmNCHitTest
  213. //
  214. // Purpose:
  215. //                      Find out which handle the cursor is over
  216. //
  217. // Parameters:
  218. //       LPPOINT                mouse position
  219. //
  220. // Return Value:
  221. //       UINT                   a value indicating the position of the cursor
  222. //
  223. //****************************************************************
  224. UINT BOleHatchWindow::wmNCHitTest (LPPOINT lpPoint)
  225. {
  226.     RECT handleRect;
  227.     RECT rc; // contain hatch window rect
  228.  
  229.     // we want lpPoint to be in client coordinates
  230.     ::ScreenToClient (hWndHatch, lpPoint);
  231.  
  232.     GetWindowRect(hWndHatch, (LPRECT)&rc);
  233.     SetRect((LPRECT)&rc,0,0,rc.right-rc.left,rc.bottom-rc.top);
  234.  
  235.     SetRectExt (&handleRect, rc.left, rc.top, hatchWidth + 1);
  236.     if (::PtInRect(&handleRect, *lpPoint))  return HTTOPLEFT;
  237.  
  238.     SetRectExt (&handleRect, rc.left, (rc.top+rc.bottom-hatchWidth + 1)/2, hatchWidth + 1);
  239.     if (::PtInRect(&handleRect, *lpPoint))  return HTLEFT;
  240.  
  241.     SetRectExt (&handleRect, rc.left, rc.bottom - hatchWidth + 1, hatchWidth + 1);
  242.     if (::PtInRect(&handleRect, *lpPoint))  return HTBOTTOMLEFT;
  243.  
  244.     SetRectExt (&handleRect, (rc.left+rc.right-hatchWidth + 1)/2, rc.top, hatchWidth + 1);
  245.     if (::PtInRect(&handleRect, *lpPoint))  return HTTOP;
  246.  
  247.     SetRectExt (&handleRect, (rc.left+rc.right-hatchWidth + 1)/2, rc.bottom - hatchWidth + 1, hatchWidth + 1);
  248.     if (::PtInRect(&handleRect, *lpPoint))  return HTBOTTOM;
  249.  
  250.     SetRectExt (&handleRect, rc.right-hatchWidth + 1, rc.top, hatchWidth + 1);
  251.     if (::PtInRect(&handleRect, *lpPoint))  return HTTOPRIGHT;
  252.  
  253.     SetRectExt (&handleRect, rc.right-hatchWidth + 1, (rc.top+rc.bottom-hatchWidth + 1)/2, hatchWidth + 1);
  254.     if (::PtInRect(&handleRect, *lpPoint))  return HTRIGHT;
  255.  
  256.     SetRectExt (&handleRect, rc.right-hatchWidth + 1, rc.bottom-hatchWidth + 1, hatchWidth + 1);
  257.     if (::PtInRect(&handleRect, *lpPoint))  return HTBOTTOMRIGHT;
  258.  
  259.     // If we've gotten this far, the cursor is not over a handle, but it
  260.     // is over the hatch window (because we got the message). This means
  261.     // the cursor is over the hatched border. It can't be over our client
  262.     // area because the server object takes up the client area.
  263.     //
  264.     // So, by telling Windows that the cursor is over the caption bar, we
  265.     // can piggy-back on Windows' code for dragging windows around.
  266.     //
  267.     return HTCAPTION;
  268. }
  269.  
  270. //****************************************************************
  271. // Member function: wmSetCursor
  272. //
  273. //      Purpose:
  274. //                      Set the cursor bitmap to match the handle it's over.
  275. //
  276. // Parameters:
  277. //                      HWND                    handle of the window with the cursor
  278. //       UINT                   only used. Contains the value returned from wmNCHitTest
  279. //                      UINT        Mouse message number
  280. //
  281. // Return Value:
  282. //                      LRESULT         TRUE, to stop further processing
  283. //
  284. //****************************************************************
  285. LRESULT BOleHatchWindow::wmSetCursor (HWND, UINT hitTestCode, UINT)
  286. {
  287.  
  288.     switch (hitTestCode) {
  289.         case HTTOPLEFT:
  290.             ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENWSE)));
  291.             break;
  292.         case HTLEFT:
  293.             ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZEWE)));
  294.             break;
  295.         case HTBOTTOMLEFT:
  296.             ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENESW)));
  297.             break;
  298.         case HTTOP:
  299.             ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENS)));
  300.             break;
  301.         case HTBOTTOM:
  302.             ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENS)));
  303.             break;
  304.         case HTTOPRIGHT:
  305.             ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENESW)));
  306.             break;
  307.         case HTRIGHT:
  308.             ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZEWE)));
  309.             break;
  310.         case HTBOTTOMRIGHT:
  311.             ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENWSE)));
  312.             break;
  313.         default:
  314.             ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_ARROW)));
  315.     }
  316.  
  317.     return (LRESULT)TRUE;
  318. }
  319.  
  320. //****************************************************************
  321. // Member function: wmMouseActivate
  322. //
  323. // Parameters:
  324. //                      HWND                    handle of the top level parent. Not used
  325. //       UINT                   hit test code. Not used
  326. //                      UINT        Mouse message identifier. Not used
  327. //
  328. // Return Value:
  329. //                      UINT                    MA_NOACTIVATE does not activate the window
  330. //
  331. //****************************************************************
  332. UINT BOleHatchWindow::wmMouseActivate (HWND, UINT, UINT)
  333. {
  334.     return MA_NOACTIVATE;
  335. }
  336.  
  337. //****************************************************************
  338. // Member function: wmNCLButtonDown
  339. //
  340. // Parameters:
  341. //                      UINT            hit test code as returned from WM_NCHITTEST
  342. //                      LPOINT                  cursor coordinates
  343. //
  344. // Return Value:
  345. //                      LRESULT         let it process by DefWindowProc
  346. //
  347. //****************************************************************
  348. LRESULT BOleHatchWindow::wmNCLButtonDown (UINT nTestCode, LPPOINT lpPoint)
  349. {
  350.     RECT WinRect;
  351.     
  352.     GetWindowRect( hWndHatch, (LPRECT)&WinRect);
  353.  
  354.     // first resize window if needed
  355.     if (nClippedFlag & CLIPPED) {
  356.         // if clipped left or top hatchRect adjust top and/or left
  357.         if (nClippedFlag & CLIPPED_LEFT)
  358.             WinRect.left += hatchRect.left;
  359.         if (nClippedFlag & CLIPPED_TOP)
  360.             WinRect.top += hatchRect.top;
  361.     
  362.     WinRect.right = WinRect.left + hatchRect.right - hatchRect.left;
  363.     WinRect.bottom = WinRect.top + hatchRect.bottom - hatchRect.top;
  364.     }
  365.  
  366.     // set flag indicating the user is moving the window and initiating
  367.     // all space negotiation procedure
  368.     fInMouseDown=TRUE;
  369.  
  370.     //\\//\\//\\/\\//\\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  371.     ////\\//\\//\\/\\//\\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
  372.     GrayFrame = new GrayGhostRect (WinRect, nTestCode);
  373.     GrayFrame->SetStartMove (*lpPoint);
  374.     SetCapture (hWndHatch);
  375.     GrayFrame->MoveFrame (*lpPoint, FALSE);
  376.  
  377.     return 0L;
  378.     //return ::DefWindowProc (hWndHatch, WM_NCLBUTTONDOWN, nTestCode, *((long *)lpPoint));
  379. }
  380.  
  381. //****************************************************************
  382. // Member function: wmMouseMove
  383. //
  384. // Purpose:
  385. //     Move around the fake window rect in XOR with the screen
  386. //
  387. // Parameters:
  388. //     UINT            hit test code as returned from WM_NCHITTEST
  389. //  LPOINT          cursor coordinates
  390. //
  391. // Return Value:
  392. //  LRESULT         0L
  393. //
  394. //****************************************************************
  395. LRESULT BOleHatchWindow::wmMouseMove (UINT nTestCode, LPPOINT lpPoint)
  396. {
  397.     if (fInMouseDown) {
  398.         // transform point in screen coordinates
  399.         ClientToScreen (hWndHatch, lpPoint);
  400.         GrayFrame->MoveFrame (*lpPoint, TRUE);
  401.  
  402.         return 0L;
  403.     }
  404.     else {
  405.         DWORD lParam = MAKELONG((WORD)(lpPoint->x),(WORD)(lpPoint->y));
  406.         return ::DefWindowProc (hWndHatch, WM_MOUSEMOVE, nTestCode, lParam);
  407.     }
  408.  
  409. }
  410.  
  411. //****************************************************************
  412. // Member function: wmLButtonUp
  413. //
  414. // Parameters:
  415. //  UINT            hit test code as returned from WM_NCHITTEST
  416. //  LPOINT          cursor coordinates
  417. //
  418. // Return Value:
  419. //  LRESULT         0L
  420. //
  421. //****************************************************************
  422. LRESULT BOleHatchWindow::wmLButtonUp (UINT nTestCode, LPPOINT lpPoint)
  423. {
  424.     if (fInMouseDown) {
  425.         POINT TopLeft;
  426.         POINT WidthHeight;
  427.  
  428.         ClientToScreen (hWndHatch, lpPoint);
  429.         GrayFrame->MoveFrame (*lpPoint, FALSE);
  430.  
  431.         GrayFrame->UpperCorner (TopLeft);
  432.         GrayFrame->Size (WidthHeight);
  433.         ScreenToClient (GetParent (hWndHatch), (LPPOINT)&TopLeft);
  434.         // move the window now
  435.         MoveWindow (hWndHatch, TopLeft.x, TopLeft.y, WidthHeight.x, WidthHeight.y, TRUE);
  436.         InvalidateRect (hWndHatch, NULL, TRUE);
  437.  
  438.         delete GrayFrame;
  439.  
  440.         // release mouse
  441.         ReleaseCapture();
  442.     
  443.         return 0L;
  444.     }
  445.     else {
  446.         DWORD lParam = MAKELONG((WORD)(lpPoint->x),(WORD)(lpPoint->y));
  447.         return ::DefWindowProc (hWndHatch, WM_LBUTTONUP, nTestCode, lParam);
  448.     }
  449.  
  450. }
  451.  
  452. //****************************************************************
  453. // Member function: wmGetMinMaxInfo
  454. //
  455. // Parameters:
  456. //                      LPMINMAXINFO    struct containing resizing information
  457. //
  458. // Return Value:
  459. //                      LRESULT                 0L when processing this message
  460. //
  461. //****************************************************************
  462. LRESULT BOleHatchWindow::wmGetMinMaxInfo (MINMAXINFO* pMMI)
  463. {
  464.     int minWidth = (GetWidth() * 2) + 15;
  465.     pMMI->ptMinTrackSize.x = minWidth;
  466.     pMMI->ptMinTrackSize.y = minWidth;
  467.     return 0L;
  468. }
  469.  
  470. //****************************************************************
  471. // Member function: wmWindowPosChanging
  472. //
  473. // Purpose:
  474. //       Call negotiate size to activate the space negotiation
  475. //                      procedure and, in case, changes the WINDOWPOS values
  476. //                      so to accomplish the new size
  477. //
  478. // Parameters:
  479. //       LPWINDOWPOS    structure containing information about
  480. //                                                      resizing values
  481. //
  482. // Return Value:
  483. //                      LRESULT
  484. //
  485. //****************************************************************
  486. LRESULT BOleHatchWindow::wmWindowPosChanging (LPWINDOWPOS pWP)
  487. {
  488.           if (fInMouseDown) {
  489.                      int minWidth = (GetWidth() * 2) + 15;
  490.                      if (pWP->cx < minWidth) {
  491.                                 pWP->cx = minWidth;
  492.                      }
  493.                      if (pWP->cy < minWidth) {
  494.                                 pWP->cy = minWidth;
  495.                      }
  496.                      NegotiateSize (pWP);
  497.                      if (nClippedFlag & CLIPPED) {
  498.                                 pWP->x = MoveRect.left;
  499.                                 pWP->y = MoveRect.top;
  500.                                 pWP->cx = MoveRect.right;
  501.                                 pWP->cy = MoveRect.bottom;
  502.                                 pWP->flags = 0;
  503.                      }
  504.                      ::InvalidateRect(hWndHatch, NULL, TRUE);
  505.                      fInMouseDown = FALSE;
  506.                      return 0L;
  507.           }
  508.  
  509.             return ::DefWindowProc (hWndHatch, WM_WINDOWPOSCHANGING, 0, (DWORD)(LPVOID)pWP);
  510. }
  511.  
  512. //***************************************************************************
  513. // Member function: Show
  514. //
  515. // Purpose:
  516. //              Show or hide the hatch window; provide access to the site
  517. //
  518. // Parameters:
  519. //              BOOL                                    TRUE to show the hatch window, FALSE to hide it
  520. //              LPOLEINPLACESITE        Pointer to the in place site, which is used to
  521. //                                              negotiate new size when a handle is dragged
  522. //
  523. //***************************************************************************
  524. void BOleHatchWindow::Show (BOOL fShow, LPOLEINPLACESITE pS)
  525. {
  526.     pSite = pS;
  527.     ::ShowWindow (hWndHatch, fShow ? SW_SHOW : SW_HIDE);
  528. }
  529.  
  530. //***************************************************************************
  531. //      Member function: SetSize
  532. //
  533. // Purpose:
  534. //              Move/size the HatchWindow correctly given the rect required by the
  535. //              in-place server object window and the lprcClipRect imposed by the
  536. //              in-place container. both rect's are expressed in the client coord.
  537. //              of the in-place container's window (which is the parent of the
  538. //              HatchWindow). When fInMouseDown is TRUE must not use MoveWindow
  539. //                      but change the values in the WINDOWPOS struct inside the
  540. //                      WM_WINDOWPOSCHANGING message (it seems Windows code is not re-entrant
  541. //       there)
  542. //
  543. //              OLE2NOTE: the in-place server must honor the lprcClipRect specified
  544. //              by its in-place container. it must NOT draw outside of the ClipRect.
  545. //              in order to achieve this, the hatch window is sized to be
  546. //              exactly the size that should be visible (rcVisRect). the
  547. //              rcVisRect is defined as the intersection of the full size of
  548. //              the HatchRect window and the lprcClipRect.
  549. //              the ClipRect could infact clip the HatchRect on the
  550. //              right/bottom and/or on the top/left. if it is clipped on the
  551. //              right/bottom then it is sufficient to simply resize the hatch
  552. //              window. but if the HatchRect is clipped on the top/left then
  553. //              in-place server document window (child of HatchWindow) must be moved
  554. //              by the delta that was clipped. the window origin of the
  555. //              in-place server window will then have negative coordinates relative
  556. //              to its parent HatchWindow.
  557. //
  558. // Parameters:
  559. //              LPRECT                  full size of in-place server object window
  560. //              LPRECT                  clipping rect imposed by in-place container
  561. //              LPPOINT         offset required to position in-place server object
  562. //                      window properly. caller should call:
  563. //                                                              OffsetRect(&rcObjRect,lpptOffset->x,lpptOffset->y)
  564. //
  565. //      Return Value:                   None
  566. //
  567. //***************************************************************************
  568. void BOleHatchWindow::SetSize(
  569.         LPRECT      lprcIPObjRect,
  570.         LPRECT      lprcClipRect,
  571.         LPPOINT     lpptOffset)
  572. {
  573.  
  574.     RECT        rcHatchRect;
  575.     RECT        rcVisRect;
  576.     UINT        uHatchWidth;
  577.     POINT       ptOffset;
  578.  
  579.     if (!::IsWindow(hWndHatch))
  580.         return;
  581.  
  582.     rcHatchRect = *lprcIPObjRect;
  583.     uHatchWidth = GetWidth();
  584.     ::InflateRect((LPRECT)&rcHatchRect, uHatchWidth + 1, uHatchWidth + 1);
  585.  
  586.     // find the intersection between hatch (server) window and
  587.     // clipping area (area where the object is allowed to paint)
  588.     ::IntersectRect (&rcVisRect, &rcHatchRect, lprcClipRect);
  589.  
  590.     // move the hatch window at the intersection rectangle if you are not
  591.     // dragging the window around
  592.     if (!fInMouseDown) {
  593.         ::MoveWindow(
  594.                 hWndHatch,
  595.                 rcVisRect.left,
  596.                 rcVisRect.top,
  597.                 rcVisRect.right-rcVisRect.left,
  598.                 rcVisRect.bottom-rcVisRect.top,
  599.                 TRUE    /* fRepaint */
  600.         );
  601.         ::InvalidateRect(hWndHatch, NULL, TRUE);
  602.     }
  603.     else {
  604.         // this information will be used in the WM_WINDOWPOSCHANGING
  605.         // message to change WINDOWPOS structure values
  606.          ::SetRect(&MoveRect, rcVisRect.left, rcVisRect.top,
  607.                                                     rcVisRect.right-rcVisRect.left,
  608.                                                     rcVisRect.bottom-rcVisRect.top);
  609.   }
  610.  
  611.  
  612.     nClippedFlag = 0; // clear clipped flag
  613.     // store clipping information
  614.     if (!(::EqualRect (&rcVisRect, &rcHatchRect))) {
  615.         nClippedFlag |= CLIPPED;
  616.         if (rcVisRect.left != rcHatchRect.left) {
  617.             nClippedFlag |= CLIPPED_LEFT;
  618.         }
  619.         if (rcVisRect.top != rcHatchRect.top) {
  620.             nClippedFlag |= CLIPPED_TOP;
  621.         }
  622.     }
  623.  
  624.     // convert the rcHatchRect into the client coordinate system of the
  625.     // HatchWindow itself
  626.     ptOffset.x = - rcVisRect.left;
  627.     ptOffset.y = - rcVisRect.top;
  628.     ::OffsetRect(&rcHatchRect, ptOffset.x, ptOffset.y);
  629.   ::CopyRect (&hatchRect, &rcHatchRect);
  630.     //hatchRect = rcHatchRect;
  631.  
  632.     // calculate offset required to position in-place
  633.     // server doc window (output value)
  634.     lpptOffset->x = ptOffset.x;
  635.     lpptOffset->y = ptOffset.y;
  636.  
  637.     return;
  638. }
  639.  
  640. //***************************************************************************
  641. // Member function: NegotiateSize
  642. //
  643. // Purpose:
  644. //              When the user drags a handle of the hatch window, Windows attempts
  645. //              to resize the window. This routine catches that attempt and validates
  646. //              it with the client. We don't need to validate it with the server
  647. //              because the client will call the server back from OnPosRectChange to
  648. //              BOleSite::SetObjectRects.
  649. //
  650. //      Parameters:
  651. //              WINDOWPOS*                              Pointer to Windows' WINDOWPOS structure
  652. //
  653. //***************************************************************************
  654. void BOleHatchWindow::NegotiateSize (WINDOWPOS *pwp)
  655. {
  656.     RECT rcWnd; // The pre-resize size of the hatch window
  657.  
  658.     // As an optimization, get the current size of the hatch window
  659.     // and bail out if it's the same as the new size. This saves the
  660.     // potentially expensive renegotiation.
  661.     //
  662.     ::GetWindowRect (hWndHatch, &rcWnd);
  663.     HWND parent = ::GetParent (hWndHatch);
  664.     ::ScreenToClient (parent, (LPPOINT) &rcWnd.left);
  665.     ::ScreenToClient (parent, (LPPOINT) &rcWnd.right);
  666.           //if ( rcWnd.left == pwp->x && rcWnd.top == pwp->y &&
  667.           //        (rcWnd.bottom - rcWnd.top == pwp->cy) &&
  668.           //        (rcWnd.right - rcWnd.left == pwp->cx))
  669.     //        return;
  670.  
  671.     // Ask the client to resize to the new size of the window
  672.     //
  673.     RECT rcNew;
  674.  
  675.     // The new size of the server's inplace window
  676.     ::SetRect (&rcNew, pwp->x, pwp->y, pwp->x + pwp->cx, pwp->y + pwp->cy);
  677.     ::InflateRect (&rcNew, -(hatchWidth + 1), -(hatchWidth + 1));
  678.     if (pSite) {
  679.         // Ask the server to show more/less of object
  680.         //
  681.         if (!SUCCEEDED(pBack->SetSiteRect(&rcNew))) {
  682.             SIZE size;
  683.             // undo resize of the server
  684.             size.cx = rcWnd.right - rcWnd.left;
  685.             size.cy = rcWnd.bottom - rcWnd.top;
  686.             pBack->pPart->SetPartSize(&size);
  687.  
  688.             // If the client refuses the new size, give the pre-resize
  689.             // size of the hatch window, back to Windows through the WINDOWPOS
  690.             //
  691.             pwp->x = rcWnd.left;
  692.             pwp->y = rcWnd.top;
  693.             pwp->cx = rcWnd.right - rcWnd.left;
  694.             pwp->cy = rcWnd.bottom - rcWnd.top;
  695.         }
  696.     }
  697. }
  698.  
  699. //***************************************************************************
  700. //      BOleHatchWndProc
  701. //
  702. // Purpose:
  703. //                      WndProc for hatch window
  704. //
  705. // Parameters:
  706. //                      hWnd
  707. //                      Message
  708. //                      wParam
  709. //                      lParam
  710. //
  711. // Return Value:
  712. //                      message dependent
  713. //***************************************************************************
  714. LRESULT FAR PASCAL EXPORT BOleHatchWndProc (HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
  715. {
  716.   BOleHatchWindow *pHW  = (BOleHatchWindow*) ::GetWindowLong(hWnd, 0);
  717.  
  718.   // if pHW is NULL, assign it if WM_NCCREATE otherwise
  719.   // return DefWindowProc
  720.   if (!pHW) {
  721.     if (Message==WM_NCCREATE) {
  722.  
  723.       CREATESTRUCT FAR* lpcs = (CREATESTRUCT FAR*)lParam;
  724.       ::SetWindowLong(hWnd, 0, (DWORD)(LPVOID)(lpcs->lpCreateParams));
  725.     }
  726.     return ::DefWindowProc (hWnd, Message, wParam, lParam);
  727.   }
  728.  
  729.   switch (Message) {
  730.     case WM_CREATE:
  731.       return pHW->wmCreate((LPCREATESTRUCT)lParam);
  732.  
  733.     case WM_PAINT:
  734.       return pHW->wmPaint ();
  735.  
  736.     case WM_GETMINMAXINFO:
  737.       return pHW->wmGetMinMaxInfo((MINMAXINFO*)lParam);
  738.  
  739.     // The cursor setting strategy here is to catch the WM_NCHITTEST
  740.     // first to figure out which hit-test area the cursor is over.
  741.     // Then Windows calls us back with WM_SETCURSOR so we can make
  742.     // the cursor the correct shape for that hit-test area.
  743.     //
  744.     case WM_NCHITTEST:
  745.       if (pHW) {
  746.                 POINT pt;
  747.                 pt.x = LOWORD(lParam);
  748.                 pt.y = HIWORD(lParam);
  749.                 return pHW->wmNCHitTest ((LPPOINT) &pt);
  750.       }
  751.  
  752.     // Any window that is used during in-place activation
  753.     // must handle the WM_SETCURSOR message or else the cursor
  754.     // of the in-place parent will be used. if WM_SETCURSOR is
  755.     // not handled, then DefWindowProc sends the message to the
  756.     // window's parent.
  757.     //
  758.     case WM_SETCURSOR:
  759.       return pHW->wmSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
  760.  
  761.     case WM_MOUSEACTIVATE:
  762.       return pHW->wmMouseActivate((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
  763.  
  764.     // The window move/resize strategy here is:
  765.     // - Keep control so we can allow the OLE2 client app to refuse
  766.     //   the new dimensions. Don't wait until the window has already
  767.     //   been moved and then move it back.
  768.     // - In order to keep control, we catch the WM_WINDOWPOSCHANGING
  769.     //   and set appropriate flags in the WINDOWPOS struct.
  770.     // - Since WM_WINDOWPOSCHANGING is sent for both user-interface
  771.     //   initiated actions and for ::MoveWindow-initiated changes, we
  772.     //   keep a flag which prevents changes during mousedowns
  773.     //
  774.     //case WM_NCLBUTTONDOWN:
  775.     //  return pHW->wmNCLButtonDown(wParam, (LPPOINT)&lParam);
  776.  
  777.         case WM_NCLBUTTONDOWN: {
  778.             short xPos, yPos;
  779.             POINT pt;
  780.             xPos = LOWORD(lParam);
  781.             yPos = HIWORD(lParam);
  782.             pt.x = xPos;
  783.             pt.y = yPos;
  784.             return pHW->wmNCLButtonDown(wParam, (LPPOINT)&pt);
  785.             //return ::DefWindowProc(hWnd, Message, wParam, lParam);
  786.         }
  787.  
  788.         case WM_MOUSEMOVE: {
  789.             short xPos, yPos;
  790.             POINT pt;
  791.             xPos = LOWORD(lParam);
  792.             yPos = HIWORD(lParam);
  793.             pt.x = xPos;
  794.             pt.y = yPos;
  795.             return pHW->wmMouseMove(wParam, (LPPOINT)&pt);
  796.             //return ::DefWindowProc(hWnd, Message, wParam, lParam);
  797.         }
  798.  
  799.         case WM_LBUTTONUP: {
  800.             short xPos, yPos;
  801.             POINT pt;
  802.             xPos = LOWORD(lParam);
  803.             yPos = HIWORD(lParam);
  804.             pt.x = xPos;
  805.             pt.y = yPos;
  806.             return pHW->wmLButtonUp(wParam, (LPPOINT)&pt);
  807.             //return ::DefWindowProc(hWnd, Message, wParam, lParam);
  808.         }
  809.  
  810.     case WM_WINDOWPOSCHANGING:
  811.       return pHW->wmWindowPosChanging((WINDOWPOS*) lParam);
  812.  
  813.     default:
  814.       return ::DefWindowProc (hWnd, Message, wParam, lParam);
  815.   }
  816. }
  817.  
  818.  
  819.  
  820.