|
|
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
1.1.1.3 ! root 14: sieve() - time consuming function, generates primes
1.1 root 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: {
1.1.1.3 ! root 53: MSG msg; /* message */
1.1 root 54:
55: UNREFERENCED_PARAMETER( lpCmdLine );
56:
57: if (!hPrevInstance)
58: if (!InitApplication(hInstance))
59: return (FALSE);
60:
61: if (!InitInstance(hInstance, nCmdShow))
1.1.1.3 ! root 62: return (FALSE);
1.1 root 63:
64: MessageBox (
1.1.1.3 ! root 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
1.1 root 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(
1.1.1.3 ! root 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
1.1 root 140: );
141:
142: if (!hWnd)
1.1.1.3 ! root 143: return (FALSE);
1.1 root 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)
1.1.1.3 ! root 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
1.1 root 167: WM_DESTROY - destroy window
168:
169: COMMENTS:
170:
1.1.1.3 ! root 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.
1.1 root 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,
1.1.1.2 root 201: lpProcAbout);
1.1 root 202:
203: FreeProcInstance(lpProcAbout);
204: break;
205: }
206: else
207: return (DefWindowProc(hWnd, message, wParam, lParam));
208:
1.1.1.3 ! root 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 */
1.1 root 276: MoveToEx(hDC, OrgX, OrgY, NULL);
1.1.1.3 ! root 277: LineTo(hDC, OrgX, PrevY);
! 278: LineTo(hDC, PrevX, PrevY);
! 279: LineTo(hDC, PrevX, OrgY);
! 280: LineTo(hDC, OrgX, OrgY);
1.1 root 281:
1.1.1.3 ! root 282: /* Get the current mouse position */
1.1 root 283:
1.1.1.3 ! root 284: PrevX = NextX;
! 285: PrevY = NextY;
1.1 root 286: MoveToEx(hDC, OrgX, OrgY, NULL); /* Draws the new box */
1.1.1.3 ! root 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;
1.1 root 296:
1.1.1.3 ! root 297: case WM_LBUTTONUP:
! 298: bTrack = FALSE; /* No longer creating a selection */
! 299: ReleaseCapture(); /* Releases hold on mouse input */
1.1 root 300:
1.1.1.3 ! root 301: X = LOWORD(lParam); /* Saves the current value */
! 302: Y = HIWORD(lParam);
! 303: break;
1.1 root 304:
1.1.1.3 ! root 305: case WM_KEYDOWN:
! 306: if (wParam != VK_LEFT && wParam != VK_RIGHT
! 307: && wParam != VK_UP && wParam != VK_DOWN)
! 308: break;
1.1 root 309:
1.1.1.3 ! root 310: MPOINT2POINT(ptCursor, pt);
! 311: GetCursorPos(&pt);
1.1 root 312:
1.1.1.3 ! root 313: /* Convert screen coordinates to client coordinates */
1.1 root 314:
1.1.1.3 ! root 315: ScreenToClient(hWnd, &pt);
! 316: POINT2MPOINT(pt, ptCursor);
! 317: repeat++; /* Increases the repeat rate */
1.1 root 318:
1.1.1.3 ! root 319: switch (wParam) {
1.1 root 320:
1.1.1.3 ! root 321: /* Adjust cursor position according to which key was pressed. */
1.1 root 322:
1.1.1.3 ! root 323: case VK_LEFT:
! 324: ptCursor.x -= repeat;
! 325: break;
1.1 root 326:
1.1.1.3 ! root 327: case VK_RIGHT:
! 328: ptCursor.x += repeat;
! 329: break;
1.1 root 330:
1.1.1.3 ! root 331: case VK_UP:
! 332: ptCursor.y -= repeat;
! 333: break;
1.1 root 334:
1.1.1.3 ! root 335: case VK_DOWN:
! 336: ptCursor.y += repeat;
! 337: break;
1.1 root 338:
1.1.1.3 ! root 339: }
1.1 root 340:
1.1.1.3 ! root 341: /* Get the client boundaries */
1.1 root 342:
1.1.1.3 ! root 343: GetClientRect(hWnd, &Rect);
1.1 root 344:
1.1.1.3 ! root 345: /* Do not draw outside the window's client area */
1.1 root 346:
1.1.1.3 ! root 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;
1.1 root 356:
1.1.1.3 ! root 357: /* Convert the coordinates to screen coordinates */
1.1 root 358:
1.1.1.3 ! root 359: ClientToScreen(hWnd, &pt);
! 360: SetCursorPos(pt.x, pt.y);
! 361: break;
1.1 root 362:
1.1.1.3 ! root 363: case WM_KEYUP:
! 364: repeat = 1; /* Clears the repeat count. */
! 365: break;
1.1 root 366:
1.1.1.3 ! root 367: case WM_ACTIVATE:
1.1 root 368: if (!GetSystemMetrics(SM_MOUSEPRESENT)) {
369: if (!HIWORD(wParam)) {
370: // LOWORD added for portability
371: if (LOWORD(wParam)) {
1.1.1.3 ! root 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;
1.1 root 386:
1.1.1.3 ! root 387: hDC = BeginPaint (hWnd, &ps);
! 388: if (OrgX != PrevX || OrgY != PrevY) {
1.1 root 389: MoveToEx(hDC, OrgX, OrgY, NULL);
1.1.1.3 ! root 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;
1.1 root 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:
1.1.1.3 ! root 461: #define NITER 20 /* number of iterations */
! 462: #define SIZE 8190
1.1 root 463:
464: CHAR flags[SIZE+1]={ 0};
465:
466: INT sieve() {
467: INT i,k;
468: INT iter, count;
469:
1.1.1.3 ! root 470: for (iter = 1; iter <= NITER; iter++) { /* Does sieve NITER times */
1.1 root 471: count = 0;
1.1.1.3 ! root 472: for (i = 0; i <= SIZE; i++) /* Sets all flags TRUE */
1.1 root 473: flags[i] = TRUE;
474:
475: for (i = 2; i <= SIZE; i++) {
1.1.1.3 ! root 476: if (flags[i] ) { /* Found a prime? */
1.1 root 477: for (k = i + i; k <= SIZE; k += i)
1.1.1.3 ! root 478: flags[k] = FALSE; /* Cancelsits multiples */
1.1 root 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.