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