|
|
1.1 root 1: /*************************************************************************\
2: * PROGRAM: Threads.c
3: *
4: * PURPOSE:
5: *
6: * To demonstrate suspending, resuming, and setting the priorities
7: * of threads.
8: *
9: * FUNCTIONS:
10: *
11: * WinMain() - Initializes the window, and process the message loop.
12: * MainWndProc() - Process messages, launches server & client threads.
13: * ThreadProc() - Draws rectangles to the window, demonstrating the
14: * threads performance.
15: *
16: * COMMENTS:
17: *
18: * To Use:
19: * When starting this application, two threads are created. The
20: * first draws a green box, the second a red. Both boxes are moved
21: * about the screen as their individual threads calculate a new
22: * position and redraws the box. The user can Suspend either thread,
23: * Resume them, or change their priority through the menu selections.
24: * The colored boxes will respond accordingly.
25: *
26: * Note through out the sample "red thread" or "green thread" are
27: * referred to. This simply indicates the thread which draws either the
28: * red or green rectangle.
29: *
30: \*************************************************************************/
31:
32:
33: #include <windows.h>
34: #include <stdlib.h>
35: #include <time.h>
36: #include "threads.h"
37:
38:
39: HANDLE hInst;
40: HANDLE hWnd;
41:
42: /*************************************************************************\
43: *
44: * FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
45: *
46: * PURPOSE: calls initialization function, processes message loop
47: *
48: * COMMENTS:
49: *
50: \*************************************************************************/
51: int APIENTRY WinMain (HANDLE hInstance,
52: HANDLE hPrevInstance,
53: LPSTR lpCmdLine,
54: int nCmdShow)
55: {
56: MSG msg;
57: WNDCLASS wc;
58:
59: UNREFERENCED_PARAMETER( lpCmdLine );
60: UNREFERENCED_PARAMETER( hPrevInstance );
61:
62: hInst = hInstance;
63:
64: wc.style = NULL; // Replaces CS_SIZEREDRAW.
65: wc.lpfnWndProc = (WNDPROC)MainWndProc; // The client window procedure.
66: wc.cbClsExtra = 0; // No room reserved for extra data.
67: wc.cbWndExtra = 0;
68: wc.hInstance = hInstance;
69: wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
70: wc.hCursor = LoadCursor (NULL, IDC_ARROW);
71: wc.hbrBackground = GetStockObject (WHITE_BRUSH);
72: wc.lpszMenuName = "Thread_Menu";
73: wc.lpszClassName = "ThreadsWClass";
74:
75: RegisterClass(&wc);
76:
77:
78: hWnd = CreateWindow ("ThreadsWClass",
79: "Threads Sample",
80: WS_OVERLAPPEDWINDOW,
81: CW_USEDEFAULT,
82: CW_USEDEFAULT,
83: CW_USEDEFAULT,
84: CW_USEDEFAULT,
85: NULL,
86: NULL,
87: hInstance,
88: NULL);
89:
90:
91: ShowWindow(hWnd, nCmdShow);
92: while (GetMessage (&msg, NULL, NULL, NULL))
93: DispatchMessage (&msg); // Dispatch message to window.
94:
95: return (msg.wParam); // Returns value from PostQuitMessage.
96:
97: }
98:
99: /*************************************************************************\
100: *
101: * FUNCTION: MainWndProc (HWND, UINT, UINT, LONG)
102: *
103: * PURPOSE: To process the windows messages. This procedure totally
104: * controls the priority and suspension/resumption of the
105: * thread.
106: *
107: * VARIABLES USED:
108: *
109: * - hThread1, hThread2:
110: * Static handles to the two created threads.
111: *
112: * - ThreadID1 ThreadID2:
113: * DWORDs used in the CreateThread call.
114: *
115: * - pColor1, pColor2:
116: * DWORDs used to allocate some memory to use as a parameter
117: * to pass color values to the threads. This memory was
118: * allocated so that the threads wouldn't have to rely on this
119: * procedures stack for the values.
120: *
121: * - Buf[80]:
122: * Character buffer used to write messages to the user.
123: *
124: * - RedSuspendCnt, GreenSuspendCnt:
125: * Static DWORDs used to track the count of suspension put
126: * on the specific thread.
127: *
128: * MESSAGES:
129: *
130: * WM_DESTROY: - Terminates the threads and post the quit message.
131: * WM_CREATE: - Allocates memory to hold some color values, and
132: * creates the two threads.
133: * WM_COMMAND
134: *
135: * IDM_SUSPEND***:
136: * Suspends the specified thread, updates the globally kept
137: * count (number of times the thread has been suspended),
138: * and then produces a message box telling the user the
139: * number of suspensions.
140: *
141: * IDM_RESUME***:
142: * Resumes the specified thread, updates the gobally kept
143: * count (number of times the thread has been suspended),
144: * and then produces a message box telling the user the
145: * number of suspensions.
146: *
147: * IDM_G***:
148: * These 5 messages use SetThreadPriority to set the
149: * priority of the Green Thread.
150: *
151: * IDM_R***:
152: * These 5 messages use SetThreadPriority to set the
153: * priority of the Red Thread.
154: *
155: * CALLED BY:
156: *
157: * WinMain();
158: *
159: * CALLS TO:
160: *
161: * ThreadProc();
162: *
163: * COMMENTS:
164: *
165: *
166: \*************************************************************************/
167:
168:
169: LONG APIENTRY MainWndProc (HWND hwnd,
170: UINT message,
171: UINT wParam,
172: LONG lParam)
173: {
174: static HANDLE hThread1, hThread2;
175: DWORD ThreadID1, ThreadID2;
176: CHAR Buf[80];
177: static DWORD RedSuspendCnt = 0;
178: static DWORD GreenSuspendCnt = 0;
179: static DWORD *pColor1, *pColor2;
180:
181: switch (message)
182: {
183:
184: case WM_CREATE :
185:
186: pColor1 = malloc(sizeof(DWORD));
187: *pColor1 = GREEN;
188: hThread1 = CreateThread (NULL, 0,
189: (LPTHREAD_START_ROUTINE)ThreadProc,
190: (LPVOID)pColor1, NULL,
191: (LPDWORD)&ThreadID1);
192:
193: if (!hThread1)
194: {
195: wsprintf(Buf, "Error in creating Green thread: %d",
196: GetLastError());
197: MessageBox (hwnd, Buf, "WM_CREATE", MB_OK);
198: }
199:
200: Sleep (500); // Allow some time/distance between the
201: // thread boxes.
202:
203: pColor2 = malloc(sizeof(DWORD));
204: *pColor2 = RED;
205: hThread2 = CreateThread (NULL, 0,
206: (LPTHREAD_START_ROUTINE)ThreadProc,
207: (LPVOID)pColor2, NULL,
208: (LPDWORD)&ThreadID2);
209: if (!hThread2)
210: {
211: wsprintf(Buf, "Error in creating Red thread: %d",
212: GetLastError());
213: MessageBox (hwnd, Buf, "WM_CREATE", MB_OK);
214: }
215:
216:
217: return (0);
218:
219: case WM_COMMAND:
220: switch (LOWORD(wParam))
221: {
222: case IDM_SUSPENDGREEN: // Suspends green thread.
223: SuspendThread (hThread1);
224: GreenSuspendCnt++;
225: wsprintf(Buf, "The suspension count for the green thread is now %d",
226: GreenSuspendCnt);
227: MessageBox(hWnd, Buf, "Suspension Count", MB_OK);
228: return (0);
229:
230: case IDM_SUSPENDRED: // Suspends red thread.
231: SuspendThread (hThread2);
232: RedSuspendCnt++;
233: wsprintf(Buf, "The suspension count for the red thread is now %d",
234: RedSuspendCnt);
235: MessageBox(hWnd, Buf, "Suspension Count", MB_OK);
236: return (0);
237:
238: case IDM_RESUMEGREEN: // Resumes green thread.
239: ResumeThread (hThread1);
240: if (GreenSuspendCnt > 0)
241: GreenSuspendCnt--;
242: wsprintf(Buf, "The suspension count for the green thread is now %d",
243: GreenSuspendCnt);
244: MessageBox(hWnd, Buf, "Suspension Count", MB_OK);
245: return (0);
246:
247: case IDM_RESUMERED: // Resumes red thread.
248: ResumeThread (hThread2);
249: if (RedSuspendCnt > 0)
250: RedSuspendCnt--;
251: wsprintf(Buf, "The suspension count for the red thread is now %d",
252: RedSuspendCnt);
253: MessageBox(hWnd, Buf, "Suspension Count", MB_OK);
254: return (0);
255:
256:
257: case IDM_GLOW: // Sets green lowest possible.
258: SetThreadPriority (hThread1, THREAD_PRIORITY_LOWEST);
259: return (0);
260:
261: case IDM_GBNORM: // Sets green below normal.
262: SetThreadPriority (hThread1, THREAD_PRIORITY_BELOW_NORMAL);
263: return (0);
264:
265: case IDM_GNORM: // Sets green to normal.
266: SetThreadPriority (hThread1, THREAD_PRIORITY_NORMAL);
267: return (0);
268:
269: case IDM_GANORM: // Sets green above normal.
270: SetThreadPriority (hThread1, THREAD_PRIORITY_ABOVE_NORMAL);
271: return (0);
272:
273: case IDM_GHIGH: // Sets green to highest possible.
274: SetThreadPriority (hThread1, THREAD_PRIORITY_HIGHEST);
275: return (0);
276:
277:
278: case IDM_RLOW: // Sets red to lowest possible
279: SetThreadPriority (hThread2, THREAD_PRIORITY_LOWEST);
280: return (0);
281:
282: case IDM_RBNORM: // Sets red below normal.
283: SetThreadPriority (hThread2, THREAD_PRIORITY_BELOW_NORMAL);
284: return (0);
285:
286: case IDM_RNORM: // Sets red to normal.
287: SetThreadPriority (hThread2, THREAD_PRIORITY_NORMAL);
288: return (0);
289:
290: case IDM_RANORM: // Sets red above normal.
291: SetThreadPriority (hThread2, THREAD_PRIORITY_ABOVE_NORMAL);
292: return (0);
293:
294: case IDM_RHIGH: // Sets red to highest.
295: SetThreadPriority (hThread2, THREAD_PRIORITY_HIGHEST);
296: return (0);
297:
298: default:
299: return (0);
300:
301:
302: }
303:
304: case WM_DESTROY :
305: TerminateThread(hThread1, 0);
306: TerminateThread(hThread2, 0);
307: free (pColor1);
308: free (pColor2);
309: PostQuitMessage (0);
310: return (0);
311:
312: }
313: return DefWindowProc (hwnd, message, wParam, lParam);
314: }
315:
316: /*************************************************************************\
317: *
318: * FUNCTION: ThreadProc (LPVOID)
319: *
320: * PURPOSE: A thread procedure which calculates position on the window
321: * and draws a colored rectangle. The color of the rectangle
322: * is determined by the input parameter, it's border is
323: * always black (or whatever the pen color is); and since
324: * the window does not paint between rectangle draws, the
325: * rectangle leaves a black path in it's wake.
326: *
327: * VARIABLES USED:
328: *
329: * - horizontal, vertical:
330: * Local int used to indicate the next directional move the
331: * rectangle will make.
332: *
333: * - ulx, uly:
334: * Local DWORD used for the Upper Left X corner and Upper
335: * Upper Left Y position of the rectangle.
336: *
337: * - rect: A RECT structure used to determin the current size of the
338: * window (in case the user resizes it).
339: *
340: * - hdc: HDC of the rectangle.
341: *
342: * - Time: A SYSTEMTIME structure. It's milli-second field is used
343: * to create an apparent random starting point for the
344: * rectangles.
345: *
346: * -hBrush: A handle to a Brush object, used to set the color of the
347: * rectangle.
348: *
349: * -width, height:
350: * Local DWORDs used for the width and height of the rectangles.
351: *
352: * CALLED BY:
353: *
354: * MainWndProc();
355: *
356: \*************************************************************************/
357:
358:
359: VOID ThreadProc ( LPVOID *Color)
360: {
361: int horizontal, vertical;
362: DWORD ulx, uly;
363: RECT rect;
364: HDC hDC;
365: SYSTEMTIME Time;
366: HANDLE hBrush;
367: DWORD width, height;
368:
369: width = 10;
370: height = 10;
371:
372: GetSystemTime (&Time); // Get the time.
373:
374: do{}while(!GetClientRect(hWnd, &rect)); // Loop, making sure window
375: // exists.
376:
377: ulx = (Time.wMilliseconds % rect.right); // Use MOD to get a random
378: uly = (Time.wMilliseconds % rect.bottom); // position.
379:
380: if(Time.wMilliseconds % 2 == 0) // Use MOD to pick random
381: { // directions.
382: horizontal = 1;
383: vertical = 1;
384: }
385: else
386: {
387: horizontal = 1;
388: vertical = -1;
389: }
390: // Set color as per input
391: // parameter.
392: hBrush = CreateSolidBrush((COLORREF)*Color);
393:
394: do
395: { // do forever ...
396: GetClientRect( hWnd, &rect);
397:
398: if ( (ulx+width) > (DWORD)rect.right) // ... check for right edge,
399: {
400: ulx = rect.right - width;
401: horizontal = -1; // ... if so change direction;
402: }
403:
404: if ((uly+height) > (DWORD)rect.bottom) // ... check for bottom edge,
405: {
406: uly = rect.bottom - height; // ... if so change dir.
407: vertical = -1;
408: }
409:
410: if (uly <= 1) // ... check for right edge,
411: {
412: uly = 1;
413: vertical = 1;
414: }
415:
416: if (ulx <= 1)
417: { // ... check for top edge;
418: ulx = 1;
419: horizontal = 1;
420: }
421:
422: hDC = GetDC(hWnd); // ... Get DC,
423: SelectObject( hDC, hBrush); // ... Set brush color,
424: // ... Draw rectangle,
425: Rectangle (hDC, ulx, uly, ulx+width, uly+height);
426: ReleaseDC(hWnd, hDC); // ... Release DC
427: ulx += horizontal; // ... Increment/decrement
428: uly += vertical; // ... position.
429:
430: }while(1);
431: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.