home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / ipc / ddeml / client / track.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  9.3 KB  |  253 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. /***************************************************************************
  13.  *                                                                         *
  14.  *  MODULE      : track.c                                                  *
  15.  *                                                                         *
  16.  *  PURPOSE     : Generic tracking code.                                   *
  17.  *                                                                         *
  18.  ***************************************************************************/
  19. #include <windows.h>
  20. #include "track.h"
  21.  
  22. RECT  rcTrack;
  23. RECT  rcDelta;
  24. POINT ptOrg;
  25. POINT ptPrev;
  26. DWORD  fsTrack;
  27. RECT  rcBoundary;
  28. INT cxMinTrack;
  29. INT cyMinTrack;
  30.  
  31. VOID DrawTrackRect(HWND hwnd, LPRECT prcOld, LPRECT prcNew);
  32. VOID HorzUpdate(HDC hdc, INT yOld, INT yNew, INT x1Old, INT x1New, INT x2Old,
  33.         INT x2New);
  34. VOID VertUpdate(HDC hdc, INT xOld, INT xNew, INT y1Old, INT y1New, INT y2Old,
  35.         INT y2New);
  36. LONG  APIENTRY TrackingWndProc(HWND hwnd, DWORD msg, WPARAM wParam, LPARAM lParam);
  37.  
  38. /****************************************************************************
  39.  *                                                                          *
  40.  *  FUNCTION   : TrackRect()                                                *
  41.  *                                                                          *
  42.  *  PURPOSE    : Implements functionality similiar to the PM WinTrackRect() *
  43.  *                                                                          *
  44.  *  RETURNS    : TRUE on success, FALSE if tracking was canceled.           *
  45.  *               prcResult contains the resulting rectangle.                *
  46.  *                                                                          *
  47.  ****************************************************************************/
  48. BOOL TrackRect(
  49. HANDLE hInst,
  50. HWND   hwnd,        // bounding window
  51. INT    left,        // rectangle to track in bounding window coords.
  52. INT    top,
  53. INT    right,
  54. INT    bottom,
  55. INT    cxMin,
  56. INT    cyMin,
  57. DWORD   fs,
  58. LPRECT prcResult)   // result rect in bounding window coords.
  59. {
  60.     static BOOL fTracking = 0;
  61.     FARPROC lpOrgWndProc, lpTrackWndProc;
  62.     HWND hwndOldCapture, hwndOldFocus;
  63.     MSG msg;
  64.  
  65.     if (fTracking)
  66.         return FALSE;
  67.  
  68.     fTracking = TRUE;
  69.  
  70.     lpOrgWndProc = (FARPROC)GetWindowLong(hwnd, GWL_WNDPROC);
  71.     lpTrackWndProc = MakeProcInstance((FARPROC)TrackingWndProc, hInst);
  72.     SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)lpTrackWndProc);
  73.  
  74.     hwndOldCapture = GetCapture();
  75.     SetCapture(hwnd);
  76.  
  77.     hwndOldFocus = SetFocus(hwnd);
  78.     UpdateWindow(hwnd);
  79.  
  80.     GetCursorPos(&ptOrg);
  81.     ScreenToClient(hwnd, &ptOrg);
  82.  
  83.     if (fs & TF_SETPOINTERPOS) {
  84.  
  85.         if (fs & TF_LEFT && fs & TF_RIGHT)
  86.             ptOrg.x = (left + right) / 2;
  87.         else if (fs & TF_LEFT)
  88.             ptOrg.x = left;
  89.         else if (fs & TF_RIGHT)
  90.             ptOrg.x = right;
  91.  
  92.         if (fs & TF_TOP && fs & TF_BOTTOM)
  93.             ptOrg.y = (top + bottom) / 2;
  94.         else if (fs & TF_TOP)
  95.             ptOrg.y = top;
  96.         else if (fs & TF_BOTTOM)
  97.             ptOrg.y = bottom;
  98.  
  99.         ClientToScreen(hwnd, &ptOrg);
  100.         SetCursorPos(ptOrg.x, ptOrg.y);
  101.         ScreenToClient(hwnd, &ptOrg);
  102.     }
  103.  
  104.     ptPrev = ptOrg;
  105.     cxMinTrack = cxMin;
  106.     cyMinTrack = cyMin;
  107.     GetClientRect(hwnd, &rcBoundary);
  108.     fsTrack = fs;
  109.     SetRect(&rcTrack, left, top, right, bottom);
  110.     SetRect(&rcDelta, left - ptOrg.x, top - ptOrg.y, right - ptOrg.x,
  111.             bottom - ptOrg.y);
  112.     DrawTrackRect(hwnd, &rcTrack, NULL);
  113.  
  114.     while (GetMessage(&msg, NULL, 0, 0))
  115.         DispatchMessage(&msg);
  116.  
  117.     DrawTrackRect(hwnd, &rcTrack, NULL);
  118.  
  119.     SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)lpOrgWndProc);
  120.     FreeProcInstance(lpTrackWndProc);
  121.  
  122.     SetFocus(hwndOldFocus);
  123.     SetCapture(hwndOldCapture);
  124.     CopyRect(prcResult, &rcTrack);
  125.  
  126.     fTracking = FALSE;
  127. }
  128.  
  129.  
  130.  
  131.  
  132.  
  133. /****************************************************************************
  134.  *                                                                          *
  135.  *  FUNCTION   : DrawTrackRect()                                            *
  136.  *                                                                          *
  137.  *  PURPOSE    : XOR draws whats needed to move a selection from prcOld to  *
  138.  *               prcNew.  If prcNew == NULL this is considered a            *
  139.  *               first-time draw or last time erase.                        *
  140.  *                                                                          *
  141.  ****************************************************************************/
  142. VOID DrawTrackRect(
  143. HWND hwnd,
  144. LPRECT prcOld,
  145. LPRECT prcNew)
  146. {
  147.     HDC hdc;
  148.  
  149.     hdc = GetDC(hwnd);
  150.     SetROP2(hdc, R2_NOT);
  151.         // erase/draw the whole thing
  152.         MoveToEx(hdc, prcOld->left, prcOld->top, NULL);
  153.         LineTo(hdc, prcOld->right, prcOld->top);
  154.         LineTo(hdc, prcOld->right, prcOld->bottom);
  155.         LineTo(hdc, prcOld->left, prcOld->bottom);
  156.         LineTo(hdc, prcOld->left, prcOld->top);
  157.         if (prcNew) {
  158.             MoveToEx(hdc, prcNew->left, prcNew->top, NULL);
  159.             LineTo(hdc, prcNew->right, prcNew->top);
  160.             LineTo(hdc, prcNew->right, prcNew->bottom);
  161.             LineTo(hdc, prcNew->left, prcNew->bottom);
  162.             LineTo(hdc, prcNew->left, prcNew->top);
  163.         }
  164.     ReleaseDC(hwnd, hdc);
  165. }
  166.  
  167.  
  168.  
  169. /****************************************************************************
  170.  *                                                                          *
  171.  *  FUNCTION   : TrackingWndProc()                                          *
  172.  *                                                                          *
  173.  *  PURPOSE    : Window procedure that subclasses the given parent window.  *
  174.  *               This handles the mouse tracking and rectangle updates.     *
  175.  *                                                                          *
  176.  ****************************************************************************/
  177. LONG  APIENTRY TrackingWndProc(
  178. HWND hwnd,
  179. DWORD msg,
  180. WPARAM wParam,
  181. LPARAM lParam)
  182. {
  183.     switch (msg) {
  184.     case WM_MOUSEMOVE:
  185.         {
  186.             RECT rcNow, rcTest;
  187.  
  188.             if (ptPrev.x == (short)LOWORD(lParam) && ptPrev.y == (short)HIWORD(lParam))
  189.                 return 0;
  190.             CopyRect(&rcNow, &rcTrack);
  191.             if (fsTrack & TF_LEFT)
  192.                 rcNow.left = (short)LOWORD(lParam) + rcDelta.left;
  193.             if (fsTrack & TF_RIGHT)
  194.                 rcNow.right = (short)LOWORD(lParam) + rcDelta.right;
  195.             if (fsTrack & TF_TOP)
  196.                 rcNow.top = (short)HIWORD(lParam) + rcDelta.top;
  197.             if (fsTrack & TF_BOTTOM)
  198.                 rcNow.bottom = (short)HIWORD(lParam) + rcDelta.bottom;
  199.  
  200.             if (rcNow.left > rcNow.right - cxMinTrack)
  201.                 if (fsTrack & TF_LEFT)
  202.                     rcNow.left = rcNow.right - cxMinTrack;
  203.                 else
  204.                     rcNow.right = rcNow.left + cxMinTrack;
  205.  
  206.             if (rcNow.top > rcNow.bottom - cyMinTrack)
  207.                 if (fsTrack & TF_TOP)
  208.                     rcNow.top = rcNow.bottom - cyMinTrack;
  209.                 else
  210.                     rcNow.bottom = rcNow.top + cyMinTrack;
  211.  
  212.             if (fsTrack & TF_ALLINBOUNDARY) {
  213.                 if ((fsTrack & TF_MOVE) == TF_MOVE) {
  214.                     IntersectRect(&rcTest, &rcNow, &rcBoundary);
  215.                     if (!EqualRect(&rcTest, &rcNow)) {
  216.                         if (rcNow.left < rcBoundary.left)
  217.                             OffsetRect(&rcNow, rcBoundary.left - rcNow.left, 0);
  218.                         if (rcNow.right > rcBoundary.right)
  219.                             OffsetRect(&rcNow, rcBoundary.right - rcNow.right, 0);
  220.                         if (rcNow.top < rcBoundary.top)
  221.                             OffsetRect(&rcNow, 0, rcBoundary.top - rcNow.top);
  222.                         if (rcNow.bottom > rcBoundary.bottom)
  223.                             OffsetRect(&rcNow, 0, rcBoundary.bottom - rcNow.bottom);
  224.                     }
  225.                 } else
  226.                     IntersectRect(&rcNow, &rcNow, &rcBoundary);
  227.             }
  228.  
  229.             if (EqualRect(&rcNow, &rcTrack))
  230.                 return 0;
  231.  
  232.             DrawTrackRect(hwnd, &rcTrack, &rcNow);
  233.  
  234.             CopyRect(&rcTrack, &rcNow);
  235.             ((ptPrev).x = ((*((POINTS *)&(lParam)))).x, (ptPrev).y = ((*((POINTS *)&(lParam)))).y);
  236.         }
  237.         break;
  238.  
  239.     case WM_LBUTTONUP:
  240.         SendMessage(hwnd, WM_MOUSEMOVE, wParam, lParam);
  241.         PostMessage(hwnd, WM_QUIT, 0, 0);       // pop out of modal loop
  242.         return 0;
  243.         break;
  244.  
  245.     default:
  246.     return(DefWindowProc(hwnd, msg, wParam, lParam));
  247.         break;
  248.     }
  249.     return 0;
  250. }
  251.  
  252.  
  253.