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