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