|
|
1.1 ! root 1: ! 2: /******************************************************************************\ ! 3: * This is a part of the Microsoft Source Code Samples. ! 4: * Copyright (C) 1993 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: 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: HANDLE hInstance, ! 59: HANDLE 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: FARPROC lpProcAbout; ! 200: POINT pt; ! 201: HDC hDC; ! 202: ! 203: switch (message) { ! 204: case WM_COMMAND: ! 205: // LOWORD added for portability ! 206: if (LOWORD(wParam) == IDM_ABOUT) { ! 207: lpProcAbout = MakeProcInstance((FARPROC)About, hInst); ! 208: ! 209: DialogBox(hInst, ! 210: "AboutBox", ! 211: hWnd, ! 212: lpProcAbout); ! 213: ! 214: FreeProcInstance(lpProcAbout); ! 215: break; ! 216: } ! 217: else ! 218: return (DefWindowProc(hWnd, message, wParam, lParam)); ! 219: ! 220: case WM_CHAR: ! 221: if (wParam == '\r') { ! 222: SetCapture(hWnd); ! 223: ! 224: /* Set the cursor to an hourglass */ ! 225: ! 226: hSaveCursor = SetCursor(hHourGlass); ! 227: ! 228: strcpy (str, "Calculating prime numbers..."); ! 229: InvalidateRect (hWnd, NULL, TRUE); ! 230: UpdateWindow (hWnd); ! 231: wsprintf(str, "Calculated %d primes. ", sieve()); ! 232: InvalidateRect (hWnd, NULL, TRUE); ! 233: UpdateWindow (hWnd); ! 234: ! 235: SetCursor(hSaveCursor); /* Restores previous cursor */ ! 236: ReleaseCapture(); ! 237: } ! 238: break; ! 239: ! 240: case WM_LBUTTONDOWN: ! 241: bTrack = TRUE; ! 242: strcpy (str, ""); ! 243: PrevX = LOWORD(lParam); ! 244: PrevY = HIWORD(lParam); ! 245: if (!(wParam & MK_SHIFT)) { /* If shift key is not pressed */ ! 246: OrgX = LOWORD(lParam); ! 247: OrgY = HIWORD(lParam); ! 248: } ! 249: InvalidateRect (hWnd, NULL, TRUE); ! 250: UpdateWindow (hWnd); ! 251: ! 252: /* Capture all input even if the mouse goes outside of window */ ! 253: ! 254: SetCapture(hWnd); ! 255: break; ! 256: ! 257: case WM_MOUSEMOVE: ! 258: { ! 259: RECT rectClient; ! 260: INT NextX; ! 261: INT NextY; ! 262: ! 263: if (bTrack) { ! 264: NextX = (SHORT)LOWORD(lParam); ! 265: NextY = (SHORT)HIWORD(lParam); ! 266: ! 267: /* Do not draw outside the window's client area */ ! 268: ! 269: GetClientRect (hWnd, &rectClient); ! 270: if (NextX < rectClient.left) { ! 271: NextX = rectClient.left; ! 272: } else if (NextX >= rectClient.right) { ! 273: NextX = rectClient.right - 1; ! 274: } ! 275: if (NextY < rectClient.top) { ! 276: NextY = rectClient.top; ! 277: } else if (NextY >= rectClient.bottom) { ! 278: NextY = rectClient.bottom - 1; ! 279: } ! 280: ! 281: /* If the mouse position has changed, then clear the */ ! 282: /* previous rectangle and draw the new one. */ ! 283: ! 284: if ((NextX != PrevX) || (NextY != PrevY)) { ! 285: hDC = GetDC(hWnd); ! 286: SetROP2(hDC, R2_NOT); /* Erases the previous box */ ! 287: MoveToEx(hDC, OrgX, OrgY, NULL); ! 288: LineTo(hDC, OrgX, PrevY); ! 289: LineTo(hDC, PrevX, PrevY); ! 290: LineTo(hDC, PrevX, OrgY); ! 291: LineTo(hDC, OrgX, OrgY); ! 292: ! 293: /* Get the current mouse position */ ! 294: ! 295: PrevX = NextX; ! 296: PrevY = NextY; ! 297: MoveToEx(hDC, OrgX, OrgY, NULL); /* Draws the new box */ ! 298: LineTo(hDC, OrgX, PrevY); ! 299: LineTo(hDC, PrevX, PrevY); ! 300: LineTo(hDC, PrevX, OrgY); ! 301: LineTo(hDC, OrgX, OrgY); ! 302: ReleaseDC(hWnd, hDC); ! 303: } ! 304: } ! 305: } ! 306: break; ! 307: ! 308: case WM_LBUTTONUP: ! 309: bTrack = FALSE; /* No longer creating a selection */ ! 310: ReleaseCapture(); /* Releases hold on mouse input */ ! 311: ! 312: X = LOWORD(lParam); /* Saves the current value */ ! 313: Y = HIWORD(lParam); ! 314: break; ! 315: ! 316: case WM_KEYDOWN: ! 317: if (wParam != VK_LEFT && wParam != VK_RIGHT ! 318: && wParam != VK_UP && wParam != VK_DOWN) ! 319: break; ! 320: ! 321: MPOINT2POINT(ptCursor, pt); ! 322: GetCursorPos(&pt); ! 323: ! 324: /* Convert screen coordinates to client coordinates */ ! 325: ! 326: ScreenToClient(hWnd, &pt); ! 327: POINT2MPOINT(pt, ptCursor); ! 328: repeat++; /* Increases the repeat rate */ ! 329: ! 330: switch (wParam) { ! 331: ! 332: /* Adjust cursor position according to which key was pressed. */ ! 333: ! 334: case VK_LEFT: ! 335: ptCursor.x -= repeat; ! 336: break; ! 337: ! 338: case VK_RIGHT: ! 339: ptCursor.x += repeat; ! 340: break; ! 341: ! 342: case VK_UP: ! 343: ptCursor.y -= repeat; ! 344: break; ! 345: ! 346: case VK_DOWN: ! 347: ptCursor.y += repeat; ! 348: break; ! 349: ! 350: } ! 351: ! 352: /* Get the client boundaries */ ! 353: ! 354: GetClientRect(hWnd, &Rect); ! 355: ! 356: /* Do not draw outside the window's client area */ ! 357: ! 358: MPOINT2POINT(ptCursor, pt); ! 359: if (pt.x >= Rect.right) ! 360: pt.x = Rect.right - 1; ! 361: else if (pt.x < Rect.left) ! 362: pt.x = Rect.left; ! 363: if (pt.y >= Rect.bottom) ! 364: pt.y = Rect.bottom - 1; ! 365: else if (pt.y < Rect.top) ! 366: pt.y = Rect.top; ! 367: ! 368: /* Convert the coordinates to screen coordinates */ ! 369: ! 370: ClientToScreen(hWnd, &pt); ! 371: SetCursorPos(pt.x, pt.y); ! 372: break; ! 373: ! 374: case WM_KEYUP: ! 375: repeat = 1; /* Clears the repeat count. */ ! 376: break; ! 377: ! 378: case WM_ACTIVATE: ! 379: if (!GetSystemMetrics(SM_MOUSEPRESENT)) { ! 380: if (!HIWORD(wParam)) { ! 381: // LOWORD added for portability ! 382: if (LOWORD(wParam)) { ! 383: SetCursor(LoadCursor(hInst, "bullseye")); ! 384: pt.x = X; ! 385: pt.y = Y; ! 386: ClientToScreen(hWnd, &pt); ! 387: SetCursorPos(pt.x, pt.y); ! 388: } ! 389: ShowCursor(wParam); ! 390: } ! 391: } ! 392: break; ! 393: ! 394: case WM_PAINT: ! 395: { ! 396: PAINTSTRUCT ps; ! 397: ! 398: hDC = BeginPaint (hWnd, &ps); ! 399: if (OrgX != PrevX || OrgY != PrevY) { ! 400: MoveToEx(hDC, OrgX, OrgY, NULL); ! 401: LineTo(hDC, OrgX, PrevY); ! 402: LineTo(hDC, PrevX, PrevY); ! 403: LineTo(hDC, PrevX, OrgY); ! 404: LineTo(hDC, OrgX, OrgY); ! 405: } ! 406: TextOut (hDC, 1, 1, str, strlen (str)); ! 407: EndPaint (hWnd, &ps); ! 408: } ! 409: break; ! 410: ! 411: case WM_DESTROY: ! 412: PostQuitMessage(0); ! 413: break; ! 414: ! 415: default: ! 416: return (DefWindowProc(hWnd, message, wParam, lParam)); ! 417: } ! 418: return (0); ! 419: } ! 420: ! 421: ! 422: /**************************************************************************** ! 423: ! 424: FUNCTION: About(HWND, unsigned, WORD, LONG) ! 425: ! 426: PURPOSE: Processes messages for "About" dialog box ! 427: ! 428: MESSAGES: ! 429: ! 430: WM_INITDIALOG - initialize dialog box ! 431: WM_COMMAND - Input received ! 432: ! 433: ****************************************************************************/ ! 434: ! 435: BOOL APIENTRY About(HWND hDlg, UINT message, UINT wParam, LONG lParam) ! 436: { ! 437: switch (message) { ! 438: case WM_INITDIALOG: ! 439: return (TRUE); ! 440: ! 441: case WM_COMMAND: ! 442: // LOWORD added for portability ! 443: if (LOWORD(wParam) == IDOK ! 444: || LOWORD(wParam) == IDCANCEL) { ! 445: EndDialog(hDlg, TRUE); ! 446: return (TRUE); ! 447: } ! 448: break; ! 449: } ! 450: return (FALSE); ! 451: UNREFERENCED_PARAMETER(lParam); ! 452: } ! 453: ! 454: ! 455: /**************************************************************************** ! 456: ! 457: FUNCTION: Sieve() ! 458: ! 459: PURPOSE: Example of time consuming process ! 460: ! 461: COMMENTS: ! 462: ! 463: Sieve of Eratosthenes, BYTE, Volume 8, Number 1, by Jim Gilbreath ! 464: and Gary Gilbreath. Code changed to give correct results. ! 465: ! 466: One could return the count, and after restoring the cursor, use ! 467: sprintf() to copy the information to a string which could then be ! 468: put up in a MessageBox(). ! 469: ! 470: ****************************************************************************/ ! 471: ! 472: #define NITER 20 /* number of iterations */ ! 473: #define SIZE 8190 ! 474: ! 475: CHAR flags[SIZE+1]={ 0}; ! 476: ! 477: INT sieve() { ! 478: INT i,k; ! 479: INT iter, count; ! 480: ! 481: for (iter = 1; iter <= NITER; iter++) { /* Does sieve NITER times */ ! 482: count = 0; ! 483: for (i = 0; i <= SIZE; i++) /* Sets all flags TRUE */ ! 484: flags[i] = TRUE; ! 485: ! 486: for (i = 2; i <= SIZE; i++) { ! 487: if (flags[i] ) { /* Found a prime? */ ! 488: for (k = i + i; k <= SIZE; k += i) ! 489: flags[k] = FALSE; /* Cancelsits multiples */ ! 490: count++; ! 491: } ! 492: } ! 493: } ! 494: return (count); ! 495: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.