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