|
|
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.