home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / cursor / cursor.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  16KB  |  493 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993 - 1997 Microsoft Corp.
  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.     PROGRAM: Cursor.c
  15.  
  16.     PURPOSE: Demonstrates how to manipulate a cursor and select a region
  17.  
  18.     FUNCTIONS:
  19.  
  20.         WinMain() - calls initialization function, processes message loop
  21.         InitApplication() - initializes window data and registers window
  22.         InitInstance() - saves instance handle and creates main window
  23.         MainWndProc() - processes messages
  24.         About() - processes messages for "About" dialog box
  25.         sieve() - time consuming function, generates primes
  26.  
  27. ****************************************************************************/
  28.  
  29. #include <windows.h>
  30. #include <string.h>
  31. #include "cursor.h"
  32.  
  33. HANDLE hInst;
  34.  
  35. CHAR str[255];                              /* general-purpose string buffer */
  36.  
  37. HCURSOR hSaveCursor;                        /* handle to current cursor      */
  38. HCURSOR hHourGlass;                         /* handle to hourglass cursor    */
  39.  
  40. BOOL bTrack = FALSE;                        /* TRUE if left button clicked   */
  41. INT OrgX = 0, OrgY = 0;                     /* original cursor position      */
  42. INT PrevX = 0, PrevY = 0;                   /* current cursor position       */
  43. INT X = 0, Y = 0;                           /* last cursor position          */
  44. RECT Rect;                                  /* selection rectangle           */
  45.  
  46. MPOINT ptCursor;                            /* x and y coordinates of cursor */
  47. INT repeat = 1;                             /* repeat count of keystroke     */
  48.  
  49. /****************************************************************************
  50.  
  51.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  52.  
  53.     PURPOSE: calls initialization function, processes message loop
  54.  
  55. ****************************************************************************/
  56.  
  57. int APIENTRY WinMain(
  58.     HINSTANCE hInstance,
  59.     HINSTANCE hPrevInstance,
  60.     LPSTR lpCmdLine,
  61.     int nCmdShow
  62.     )
  63. {
  64.     MSG msg;                                 /* message                      */
  65.  
  66.     UNREFERENCED_PARAMETER( lpCmdLine );
  67.  
  68.     if (!hPrevInstance)
  69.         if (!InitApplication(hInstance))
  70.             return (FALSE);
  71.  
  72.     if (!InitInstance(hInstance, nCmdShow))
  73.         return (FALSE);
  74.  
  75.     MessageBox (
  76.           GetFocus ()
  77.         , "Use the mouse button in this program for an example of graphics "
  78.                         "selection, or the <Enter> key for an example of "
  79.                         "using a special cursor to reflect a program state."
  80.         , "Cursor Sample Application"
  81.         , MB_ICONASTERISK | MB_OK
  82.     );
  83.  
  84.     while (GetMessage(&msg, NULL, 0, 0)) {
  85.         TranslateMessage(&msg);
  86.         DispatchMessage(&msg);
  87.     }
  88.     return (msg.wParam);
  89. }
  90.  
  91.  
  92. /****************************************************************************
  93.  
  94.     FUNCTION: InitApplication(HANDLE)
  95.  
  96.     PURPOSE: Initializes window data and registers window class
  97.  
  98. ****************************************************************************/
  99.  
  100. BOOL InitApplication(HANDLE hInstance)
  101. {
  102.     WNDCLASS  wc;
  103.  
  104.     wc.style = 0;
  105.     wc.lpfnWndProc = (WNDPROC) MainWndProc;
  106.     wc.cbClsExtra = 0;
  107.     wc.cbWndExtra = 0;
  108.     wc.hInstance = hInstance;
  109.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  110.     wc.hCursor = LoadCursor(hInstance, "bullseye");
  111.     wc.hbrBackground = GetStockObject(WHITE_BRUSH); 
  112.     wc.lpszMenuName =  "CursorMenu";
  113.     wc.lpszClassName = "CursorWClass";
  114.  
  115.     return (RegisterClass(&wc));
  116. }
  117.  
  118.  
  119. /****************************************************************************
  120.  
  121.     FUNCTION:  InitInstance(HANDLE, int)
  122.  
  123.     PURPOSE:  Saves instance handle and creates main window
  124.  
  125. ****************************************************************************/
  126.  
  127. BOOL InitInstance(
  128.     HANDLE          hInstance,
  129.     INT             nCmdShow)
  130. {
  131.     HWND            hWnd;
  132.  
  133.     hInst = hInstance;
  134.  
  135.     strcpy(str,"");
  136.  
  137.     hHourGlass = LoadCursor(NULL, IDC_WAIT);  
  138.  
  139.     hWnd = CreateWindow(
  140.         "CursorWClass",
  141.         "Cursor Sample Application",
  142.         WS_OVERLAPPEDWINDOW,
  143.         CW_USEDEFAULT,
  144.         CW_USEDEFAULT,
  145.         CW_USEDEFAULT,
  146.         CW_USEDEFAULT,
  147.         NULL,
  148.         NULL,
  149.         hInstance,
  150.         NULL
  151.     );
  152.  
  153.     if (!hWnd)
  154.         return (FALSE);
  155.  
  156.     ShowWindow(hWnd, nCmdShow);
  157.     UpdateWindow(hWnd);
  158.     return (TRUE);
  159.  
  160. }
  161.  
  162. /****************************************************************************
  163.  
  164.     FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
  165.  
  166.     PURPOSE:  Processes messages
  167.  
  168.     MESSAGES:
  169.  
  170.         WM_COMMAND     - application menu (About dialog box)
  171.         WM_CHAR        - ASCII key value received
  172.         WM_LBUTTONDOWN - left mouse button
  173.         WM_MOUSEMOVE   - mouse movement
  174.         WM_LBUTTONUP   - left button released
  175.         WM_KEYDOWN     - key pressed
  176.         WM_KEYUPS      - key released
  177.         WM_PAINT       - update window
  178.         WM_DESTROY     - destroy window
  179.  
  180.     COMMENTS:
  181.  
  182.         When the left mouse button is pressed, btrack is set to TRUE so that
  183.         the code for WM_MOUSEMOVE will keep track of the mouse and update
  184.         the box accordingly.  Once the button is released, btrack is set to
  185.         FALSE, and the current position is saved.  Holding the SHIFT key
  186.         while pressing the left button will extend the current box rather
  187.         then erasing it and starting a new one.
  188.  
  189.         When an arrow key is pressed, the cursor is repositioned in the
  190.         direction of the arrow key.  A repeat count is kept so that the
  191.         longer the user holds down the arrow key, the faster it will move.
  192.         As soon as the key is released, the repeat count is set to 1 for
  193.         normal cursor movement.
  194.  
  195. ****************************************************************************/
  196.  
  197. LONG APIENTRY MainWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam)
  198. {
  199.     POINT pt;
  200.     HDC hDC;
  201.  
  202.     switch (message) {
  203.         case WM_COMMAND:
  204.             // LOWORD added for portability
  205.             if (LOWORD(wParam) == IDM_ABOUT) {
  206.  
  207.                 DialogBox(hInst,
  208.                     "AboutBox",
  209.                     hWnd,
  210.             About);
  211.  
  212.                 break;
  213.             }
  214.             else
  215.                 return (DefWindowProc(hWnd, message, wParam, lParam));
  216.  
  217.         case WM_CHAR:
  218.             if (wParam == '\r') {
  219.                 SetCapture(hWnd);
  220.  
  221.                 /* Set the cursor to an hourglass */
  222.  
  223.                 hSaveCursor = SetCursor(hHourGlass);
  224.  
  225.                 strcpy (str, "Calculating prime numbers...");
  226.                 InvalidateRect (hWnd, NULL, TRUE);
  227.                 UpdateWindow (hWnd);
  228.                 wsprintf(str, "Calculated %d primes.       ", sieve());
  229.                 InvalidateRect (hWnd, NULL, TRUE);
  230.                 UpdateWindow (hWnd);
  231.  
  232.                 SetCursor(hSaveCursor);          /* Restores previous cursor */
  233.                 ReleaseCapture();
  234.             }
  235.             break;
  236.  
  237.         case WM_LBUTTONDOWN:
  238.             bTrack = TRUE;
  239.             strcpy (str, "");
  240.             PrevX = LOWORD(lParam);
  241.             PrevY = HIWORD(lParam);
  242.             if (!(wParam & MK_SHIFT)) {       /* If shift key is not pressed */
  243.                 OrgX = LOWORD(lParam);
  244.                 OrgY = HIWORD(lParam);
  245.             }
  246.             InvalidateRect (hWnd, NULL, TRUE);
  247.             UpdateWindow (hWnd);
  248.  
  249.             /* Capture all input even if the mouse goes outside of window */
  250.  
  251.             SetCapture(hWnd);
  252.             break;
  253.  
  254.         case WM_MOUSEMOVE:
  255.             {
  256.                 RECT        rectClient;
  257.                 INT         NextX;
  258.                 INT         NextY;
  259.  
  260.                 if (bTrack) {
  261.                     NextX = (SHORT)LOWORD(lParam);
  262.                     NextY = (SHORT)HIWORD(lParam);
  263.  
  264.                     /* Do not draw outside the window's client area */
  265.  
  266.                     GetClientRect (hWnd, &rectClient);
  267.                     if (NextX < rectClient.left) {
  268.                         NextX = rectClient.left;
  269.                     } else if (NextX >= rectClient.right) {
  270.                         NextX = rectClient.right - 1;
  271.                     }
  272.                     if (NextY < rectClient.top) {
  273.                         NextY = rectClient.top;
  274.                     } else if (NextY >= rectClient.bottom) {
  275.                         NextY = rectClient.bottom - 1;
  276.                     }
  277.  
  278.                     /* If the mouse position has changed, then clear the */
  279.                     /* previous rectangle and draw the new one.          */
  280.  
  281.                     if ((NextX != PrevX) || (NextY != PrevY)) {
  282.                         hDC = GetDC(hWnd);
  283.                         SetROP2(hDC, R2_NOT);          /* Erases the previous box */
  284.                         MoveToEx(hDC, OrgX, OrgY, NULL);
  285.                         LineTo(hDC, OrgX, PrevY);
  286.                         LineTo(hDC, PrevX, PrevY);
  287.                         LineTo(hDC, PrevX, OrgY);
  288.                         LineTo(hDC, OrgX, OrgY);
  289.  
  290.                         /* Get the current mouse position */
  291.  
  292.                         PrevX = NextX;
  293.                         PrevY = NextY;
  294.                         MoveToEx(hDC, OrgX, OrgY, NULL); /* Draws the new box */
  295.                         LineTo(hDC, OrgX, PrevY);
  296.                         LineTo(hDC, PrevX, PrevY);
  297.                         LineTo(hDC, PrevX, OrgY);
  298.                         LineTo(hDC, OrgX, OrgY);
  299.                         ReleaseDC(hWnd, hDC);
  300.                     }
  301.                 }
  302.             }
  303.             break;
  304.  
  305.         case WM_LBUTTONUP:
  306.             bTrack = FALSE;                 /* No longer creating a selection */
  307.             ReleaseCapture();               /* Releases hold on mouse input */
  308.  
  309.             X = LOWORD(lParam);             /* Saves the current value      */
  310.             Y = HIWORD(lParam);
  311.             break;
  312.  
  313.         case WM_KEYDOWN:
  314.             if (wParam != VK_LEFT && wParam != VK_RIGHT
  315.                     && wParam != VK_UP && wParam != VK_DOWN)
  316.                 break;
  317.  
  318.             MPOINT2POINT(ptCursor, pt);
  319.             GetCursorPos(&pt);
  320.  
  321.             /* Convert screen coordinates to client coordinates */
  322.  
  323.             ScreenToClient(hWnd, &pt);
  324.             POINT2MPOINT(pt, ptCursor);
  325.             repeat++;                           /* Increases the repeat rate */
  326.  
  327.             switch (wParam) {
  328.  
  329.             /* Adjust cursor position according to which key was pressed. */
  330.  
  331.                 case VK_LEFT:
  332.                     ptCursor.x -= repeat;
  333.                     break;
  334.  
  335.                 case VK_RIGHT:
  336.                     ptCursor.x += repeat;
  337.                     break;
  338.  
  339.                 case VK_UP:
  340.                     ptCursor.y -= repeat;
  341.                     break;
  342.  
  343.                 case VK_DOWN:
  344.                     ptCursor.y += repeat;
  345.                     break;
  346.  
  347.             }
  348.  
  349.             /* Get the client boundaries */
  350.  
  351.             GetClientRect(hWnd, &Rect);
  352.  
  353.             /* Do not draw outside the window's client area */
  354.  
  355.             MPOINT2POINT(ptCursor, pt);
  356.             if (pt.x >= Rect.right)
  357.                 pt.x = Rect.right - 1;
  358.             else if (pt.x < Rect.left)
  359.                 pt.x = Rect.left;
  360.             if (pt.y >= Rect.bottom)
  361.                 pt.y = Rect.bottom - 1;
  362.             else if (pt.y < Rect.top)
  363.                 pt.y = Rect.top;
  364.  
  365.             /* Convert the coordinates to screen coordinates */
  366.  
  367.             ClientToScreen(hWnd, &pt);
  368.             SetCursorPos(pt.x, pt.y);
  369.             break;
  370.  
  371.         case WM_KEYUP:
  372.             repeat = 1;                          /* Clears the repeat count. */
  373.             break;
  374.  
  375.         case WM_ACTIVATE:
  376.             if (!GetSystemMetrics(SM_MOUSEPRESENT)) {
  377.                 if (!HIWORD(wParam)) {
  378.                     // LOWORD added for portability
  379.                     if (LOWORD(wParam)) {
  380.                         SetCursor(LoadCursor(hInst, "bullseye"));
  381.                         pt.x = X;
  382.                         pt.y = Y;
  383.                         ClientToScreen(hWnd, &pt);
  384.                         SetCursorPos(pt.x, pt.y);
  385.                     }
  386.                     ShowCursor(wParam);
  387.                 }
  388.             }
  389.             break;
  390.  
  391.         case WM_PAINT:
  392.             {
  393.                 PAINTSTRUCT     ps;
  394.  
  395.                 hDC = BeginPaint (hWnd, &ps);
  396.                 if (OrgX != PrevX || OrgY != PrevY) {
  397.                     MoveToEx(hDC, OrgX, OrgY, NULL);
  398.                     LineTo(hDC, OrgX, PrevY);
  399.                     LineTo(hDC, PrevX, PrevY);
  400.                     LineTo(hDC, PrevX, OrgY);
  401.                     LineTo(hDC, OrgX, OrgY);
  402.                 }
  403.                 TextOut (hDC, 1, 1, str, strlen (str));
  404.                 EndPaint (hWnd, &ps);
  405.             }
  406.             break;
  407.  
  408.         case WM_DESTROY:
  409.             PostQuitMessage(0);
  410.             break;
  411.  
  412.         default:
  413.             return (DefWindowProc(hWnd, message, wParam, lParam));
  414.     }
  415.     return (0);
  416. }
  417.  
  418.  
  419. /****************************************************************************
  420.  
  421.     FUNCTION: About(HWND, unsigned, WORD, LONG)
  422.  
  423.     PURPOSE:  Processes messages for "About" dialog box
  424.  
  425.     MESSAGES:
  426.  
  427.         WM_INITDIALOG - initialize dialog box
  428.         WM_COMMAND    - Input received
  429.  
  430. ****************************************************************************/
  431.  
  432. BOOL APIENTRY About(HWND hDlg, UINT message, UINT wParam, LONG lParam)
  433. {
  434.     switch (message) {
  435.         case WM_INITDIALOG:
  436.             return (TRUE);
  437.  
  438.         case WM_COMMAND:
  439.             // LOWORD added for portability
  440.             if (LOWORD(wParam) == IDOK
  441.                 || LOWORD(wParam) == IDCANCEL) {
  442.                 EndDialog(hDlg, TRUE);
  443.                 return (TRUE);
  444.             }
  445.             break;
  446.     }
  447.     return (FALSE);
  448.         UNREFERENCED_PARAMETER(lParam);
  449. }
  450.  
  451.  
  452. /****************************************************************************
  453.  
  454.     FUNCTION: Sieve()
  455.  
  456.     PURPOSE:  Example of time consuming process
  457.  
  458.     COMMENTS:
  459.  
  460.         Sieve of Eratosthenes, BYTE, Volume 8, Number 1, by Jim Gilbreath
  461.         and Gary Gilbreath.  Code changed to give correct results.
  462.  
  463.         One could return the count, and after restoring the cursor, use
  464.         sprintf() to copy the information to a string which could then be
  465.         put up in a MessageBox().
  466.  
  467. ****************************************************************************/
  468.  
  469. #define NITER   20                                 /* number of iterations */
  470. #define SIZE    8190
  471.  
  472. CHAR flags[SIZE+1]={ 0};
  473.  
  474. INT sieve() {
  475.     INT i,k;
  476.     INT iter, count;
  477.  
  478.     for (iter = 1; iter <= NITER; iter++) {      /* Does sieve NITER times */
  479.         count = 0;
  480.         for (i = 0; i <= SIZE; i++)              /* Sets all flags TRUE    */
  481.             flags[i] = TRUE;
  482.  
  483.         for (i = 2; i <= SIZE; i++) {
  484.             if (flags[i] ) {                        /* Found a prime?       */
  485.                 for (k = i + i; k <= SIZE; k += i)
  486.                     flags[k] = FALSE;              /* Cancelsits multiples */
  487.                 count++;
  488.             }
  489.         }
  490.     }
  491.     return (count);
  492. }
  493.