home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / win_sdk / cursor / cursor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-01  |  14.3 KB  |  482 lines

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