|
|
1.1 root 1: /****************************** Module Header ******************************\
2: * Module Name: demo.c
3: *
4: * Copyright (c) 1991, Microsoft Corporation
5: *
6: * Yet another User test program.
7: *
8: * History:
9: * 04-17-90 ??????? Created.
10:
11: * 09-09-91 PetrusW Rewrote.
12: * create as many threads (windows) as we wish
13: * change the UI to MDI
14: \***************************************************************************/
15:
16:
17: /* ******MULTI-THREADED GUIDE********
18:
19:
20: There are aspects to a multi-threaded app, that need be explained,
21: so that a programmer understand the pitfalls of a multi-threaded app,
22: and avoid future problems in a multi-threaded application.
23:
24: The primary pifalls involve the usage of GDI objects. (DC's, regions, etc).
25: GDI is the only subsytem in NT win32, that does NOT serialize access
26: to its objects. This is for speed/throughput reasons. The premise
27: of GDI objects, is that an object is per process owned, per thread locked.
28:
29: This means if you have multiple threads, accessing the same GDI object,
30: you will have MAJOR headaches, because while one thread deletes an object,
31: the other may be using it. The model we put forward towards developers, is
32: the following model.
33:
34: Seperate threads for
35:
36: > Input
37: > File IO
38: > Printing
39: > Graphics * Note its ok to have graphics/Printing threads, because
40: The use a different device.
41:
42:
43: Note that you can be single threaded, and have no GDI object serialization
44: problems. What types of problems occur, is when seperate threads attempt
45: to delete/use a GDI object, or share an object between multiple threads.
46: Since an object is per thread locked, means you will get an unexpected
47: error within the other thread. Many windows programmers, do not expect
48: certain calls to ever fail, but a poorly constructed multi-threaded app
49: under win32 (given the above scenerios) may fail, and if not checked,
50: will cause subsequent GDI calls to fail, ultimately causing the GDI client
51: side server to die, taking the app with it.
52:
53: Thus its most important to realize that while multi-threaded apps are cool,
54: they must be programmed with respect to the above guidelines.
55:
56: */
57:
58:
59: #include <stdlib.h>
60:
61: #include "mltithrd.h"
62: #include <stdarg.h>
63:
64: #define CCOLORS 16
65: #define CPOINTS 20
66: #define COBJS 1
67:
68:
69: /*
70: * Some handy globals.
71: */
72: HANDLE ghModule;
73: HWND ghwndMain = NULL;
74: HBRUSH ghbrWhite, ghbrBlack;
75: HBRUSH gahbrColor[CCOLORS];
76: int cmdDemo = 0;
77: BOOL bKillMe = FALSE;
78:
79: HMENU hMenu, hMenuWindow;
80:
81: DWORD aclr[CCOLORS] = {
82: 0x00000000, // black
83: 0x007F0000, // red
84: 0x00007F00, // green
85: 0x007F7F00, // mustard/brown
86: 0x0000007F, // blue
87: 0x007F007F, // magenta
88: 0x00007F7F, // cyan
89: 0x00BFBFBF, // light gray
90: 0x007F7F7F, // dark gray
91: 0x00FF0000, // bright red
92: 0x0000FF00, // bright green
93: 0x00FFFF00, // bright yellow
94: 0x000000FF, // bright blue
95: 0x00FF00FF, // bright magenta
96: 0x0000FFFF, // bright cyan
97: 0x00FFFFFF // bright white
98: };
99:
100:
101: typedef struct _b {
102: POINT apt[CPOINTS];
103: int dx;
104: int dy;
105: int vx;
106: int vy;
107: int ax;
108: int ay;
109: int iColor;
110: } B;
111:
112:
113: typedef struct _ThreadBlockInfo {
114: HANDLE hThread;
115: BOOL bKillThrd;
116: HWND hwndClient;
117: HWND hwndThreadWindow;
118: LONG lThreadId;
119: char CaptionBarText[SIZEOFCAPTIONTEXT];
120: B gab[COBJS];
121: RECT rcClient;
122: HDC hdcThreadWindow;
123: } THREADBLOCKINFO, *PTHREADBLOCKINFO;
124:
125:
126: typedef struct _node {
127: THREADBLOCKINFO ThreadWindow;
128: HANDLE hNext;
129: } NODE, *PNODE;
130:
131:
132: /*
133: * Forward declarations.
134: */
135: BOOL InitializeApp (void);
136: LONG MainWndProc (HWND, UINT, DWORD, LONG);
137: LONG ThreadWndProc (HWND, UINT, DWORD, LONG);
138: LONG About (HWND, UINT, DWORD, LONG);
139:
140: LONG StartBounce (PTHREADBLOCKINFO);
141: void DrawBox (int, int, HBRUSH, PTHREADBLOCKINFO);
142: void MoveBox (int *px, int *py, int *pdx, int *pdy, int *pvx, int *pvy, int ax, int ay, PTHREADBLOCKINFO pThreadBlockInfo);
143: void BounceProc (PTHREADBLOCKINFO);
144: BOOL StartDemo (int, PTHREADBLOCKINFO);
145: int GetRandomVector ();
146: void InitializeBoxes (BOOL, PTHREADBLOCKINFO);
147:
148: /***************************************************************************\
149: * main
150: *
151: *
152: * History:
153: * 04-17-91 ??????? Created.
154:
155: \***************************************************************************/
156:
157: int WinMain(
158: HANDLE hInstance,
159: HANDLE hPrevInstance,
160: LPSTR lpCmdLine,
161: int nShowCmd)
162: {
163: MSG msg;
164:
165: // this will change to something more reasonable
166:
167: ghModule = GetModuleHandle(NULL);
168:
169: if (!InitializeApp()) {
170: MessageBox(ghwndMain, "MLTITHRD: InitializeApp failure!", "Error", MB_OK);
171: return 0;
172: }
173:
174: while (GetMessage(&msg, NULL, 0, 0)) {
175: TranslateMessage(&msg);
176: DispatchMessage(&msg);
177: }
178:
179: return 1;
180:
181: hInstance;
182: hPrevInstance;
183: lpCmdLine;
184: nShowCmd;
185: }
186:
187:
188: /***************************************************************************\
189: * InitializeApp
190: *
191: * History:
192: * 04-17-91 ??????? Created.
193:
194: * 09-09-91 PetrusW Rewrote.
195: \***************************************************************************/
196:
197: BOOL InitializeApp(void)
198: {
199: WNDCLASS wc;
200: int i;
201:
202: srand(51537);
203:
204: for (i = 0; i < CCOLORS; i++) {
205: gahbrColor[i] = CreateSolidBrush(aclr[i]);
206: }
207:
208: ghbrWhite = CreateSolidBrush(0x00FFFFFF);
209: ghbrBlack = CreateSolidBrush(0x00000000);
210:
211: wc.style = CS_OWNDC;
212: wc.lpfnWndProc = MainWndProc;
213: wc.cbClsExtra = 0;
214: wc.cbWndExtra = sizeof(LONG);
215: wc.hInstance = ghModule;
216: wc.hIcon = LoadIcon(ghModule,MAKEINTRESOURCE(APPICON));
217: wc.hCursor = LoadCursor(NULL, IDC_ARROW);
218: wc.hbrBackground = ghbrWhite;
219: wc.lpszMenuName = "MainMenu";
220: wc.lpszClassName = "MltithrdClass";
221:
222: if (!RegisterClass(&wc))
223: return FALSE;
224:
225: wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
226: wc.lpfnWndProc = ThreadWndProc;
227: wc.cbClsExtra = 0;
228: wc.cbWndExtra = 0;
229: wc.hInstance = ghModule;
230: wc.hIcon = LoadIcon(ghModule,MAKEINTRESOURCE(APPICON));
231: wc.hCursor = LoadCursor(NULL, IDC_ARROW);
232: wc.hbrBackground = ghbrWhite;
233: wc.lpszMenuName = NULL;
234: wc.lpszClassName = "ThreadClass";
235:
236: if (!RegisterClass(&wc))
237: return FALSE;
238:
239: hMenu = LoadMenu(ghModule, "MainMenu");
240: hMenuWindow = GetSubMenu(hMenu, 1);
241:
242: ghwndMain = CreateWindowEx(0L, "MltithrdClass", "Mltithrd",
243: WS_OVERLAPPED | WS_CAPTION | WS_BORDER | WS_THICKFRAME |
244: WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_CLIPCHILDREN |
245: WS_VISIBLE | WS_SYSMENU,
246: 80, 70, 400, 300,
247: NULL, hMenu, ghModule, NULL);
248:
249: if (ghwndMain == NULL)
250: return FALSE;
251:
252: SetWindowLong(ghwndMain, GWL_USERDATA, 0L);
253:
254: SetFocus(ghwndMain); /* set initial focus */
255:
256: return TRUE;
257: }
258:
259:
260: /***************************************************************************\
261: * MainWndProc
262: *
263: * History:
264: * 04-17-91 ??????? Created.
265:
266: * 09-09-91 PetrusW Rewrote.
267: \***************************************************************************/
268:
269: long MainWndProc(
270: HWND hwnd,
271: UINT message,
272: DWORD wParam,
273: LONG lParam)
274: {
275: static int iCount=1;
276: static HWND hwndClient;
277: CLIENTCREATESTRUCT clientcreate;
278: HWND hwndChildWindow;
279:
280:
281: switch (message) {
282:
283:
284: case WM_CREATE:
285: SetWindowLong(hwnd, 0, (LONG)NULL);
286:
287: clientcreate.hWindowMenu = hMenuWindow;
288: clientcreate.idFirstChild = 1;
289:
290: hwndClient = CreateWindow("MDICLIENT", NULL,
291: WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
292: 0,0,0,0,
293: hwnd, NULL, ghModule, (LPVOID)&clientcreate);
294: return 0L;
295:
296: case WM_DESTROY: {
297: HANDLE hHead, hTmp;
298: PNODE pHead;
299:
300: bKillMe = TRUE;
301:
302: hHead = (HANDLE) GetWindowLong(hwnd, 0);
303: if (hHead) {
304: if ((pHead = (PNODE) LocalLock(hHead))==NULL)
305: MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK);
306: while (pHead->hNext != NULL) {
307:
308: hTmp = hHead;
309: hHead = pHead->hNext;
310: LocalUnlock(hTmp);
311:
312: if (LocalFree(hTmp)!=NULL)
313: MessageBox(ghwndMain, "Failed in LocalFree!", "Error", MB_OK);
314: if ((pHead = (PNODE) LocalLock(hHead))==NULL)
315: MessageBox(ghwndMain, "Failed in LocalLock, hHead!", "Error", MB_OK);
316: }
317: LocalUnlock(hHead);
318:
319: if (LocalFree(hHead)!=NULL)
320: MessageBox(ghwndMain, "LocalFree failed to free hHead!", "Error", MB_OK);
321: }
322: PostQuitMessage(0);
323: return 0L;
324: }
325:
326: #ifdef LATER
327: case WM_LBUTTONDOWN:
328: InitializeBoxes(TRUE, &ThreadWindow);
329: break;
330: #endif
331:
332: case WM_COMMAND:
333:
334: switch (LOWORD(wParam)) {
335: case IDM_TILE:
336: SendMessage(hwndClient, WM_MDITILE, 0L, 0L);
337: return 0L;
338: case IDM_CASCADE:
339: SendMessage(hwndClient, WM_MDICASCADE, 0L, 0L);
340: return 0L;
341: case IDM_ARRANGE:
342: SendMessage(hwndClient, WM_MDIICONARRANGE, 0L, 0L);
343: return 0L;
344: case MM_BOUNCE: {
345: HANDLE hNode, hHead;
346: HANDLE hThrd;
347: PNODE pNode;
348: MDICREATESTRUCT mdicreate;
349:
350: hNode = LocalAlloc(LHND, (WORD) sizeof(NODE));
351: if (hNode) {
352: if ((pNode = (PNODE)LocalLock(hNode))==NULL)
353: MessageBox(ghwndMain, "Failed in LocalLock, hNode!", "Error", MB_OK);
354:
355: wsprintf((LPSTR)&(pNode->ThreadWindow.CaptionBarText), "Thread Window %d", iCount);
356:
357: mdicreate.szClass = "ThreadClass";
358: mdicreate.szTitle = (LPSTR)&(pNode->ThreadWindow.CaptionBarText);
359: mdicreate.hOwner = ghModule;
360: mdicreate.x =
361: mdicreate.y =
362: mdicreate.cx =
363: mdicreate.cy = CW_USEDEFAULT;
364: mdicreate.style = 0l;
365: mdicreate.lParam = 0L;
366:
367: /*Create Child Window*/
368: hwndChildWindow = (HANDLE) SendMessage(hwndClient, WM_MDICREATE,
369: 0L,
370: (LONG)(LPMDICREATESTRUCT)&mdicreate);
371:
372: if (hwndChildWindow == NULL) {
373: MessageBox(ghwndMain, "Failed in Creating Thread Window!", "Error", MB_OK);
374: return 0L;
375: }
376:
377: // This stuff is here for simplicity. Initialization should
378: // be done in StartDemo
379: pNode->ThreadWindow.hwndClient = hwndClient;
380: pNode->ThreadWindow.hwndThreadWindow = hwndChildWindow;
381: hHead = (HANDLE)GetWindowLong(hwnd, 0);
382: pNode->hNext = hHead;
383: SetWindowLong(hwnd, 0, (LONG) hNode);
384:
385: // Create the thread suspended so we can alter its priority
386:
387: // before it begins to run.
388:
389:
390:
391: hThrd = CreateThread(NULL, 0,
392: (LPTHREAD_START_ROUTINE)StartBounce,
393: &pNode->ThreadWindow,
394: CREATE_SUSPENDED | STANDARD_RIGHTS_REQUIRED,
395:
396: (LPDWORD) &pNode->ThreadWindow.lThreadId );
397: if (hThrd) {
398:
399: // I really don't need this info, it won't even be
400: // updated right the way for this thread will be
401: // preempted.
402: pNode->ThreadWindow.hThread = hThrd;
403: iCount++;
404:
405:
406: // This way the primary (input) thread will be higher priority
407:
408: // than the bouncers, thus keeping MLTITHRD responsive to user
409:
410: // input.
411:
412:
413:
414: SetThreadPriority(hThrd, THREAD_PRIORITY_BELOW_NORMAL);
415:
416:
417:
418: // Everything's set, let it go.
419:
420:
421:
422: ResumeThread(hThrd);
423:
424:
425: } else {
426: MessageBox(ghwndMain, "Create Thread Failed!", "Error", MB_OK);
427: }
428: LocalUnlock(hNode);
429:
430: } else {
431: MessageBox(ghwndMain, "Failed to Allocate Node!", "Error", MB_OK);
432: }
433: return 0L;
434: }
435:
436: case MM_ABOUT:
437: if (DialogBox(ghModule, "AboutBox", ghwndMain, About) == -1)
438: MessageBox(ghwndMain, "Mltithrd: About Dialog Creation Error!", "Error", MB_OK);
439: return 0L;
440:
441: default:
442: return DefFrameProc(hwnd, hwndClient, message, wParam, lParam);
443: }
444:
445: default:
446:
447: return DefFrameProc(hwnd, hwndClient, message, wParam, lParam);
448: }
449: }
450:
451: /********************************************************************\
452: * ThreadWndProc
453: *
454: * History:
455: * 04-17-91 ??????? Created.
456:
457: * 09-09-91 PetrusW Rewrote.
458: \***************************************************************************/
459:
460: long ThreadWndProc(
461: HWND hwnd,
462: UINT message,
463: DWORD wParam,
464: LONG lParam)
465: {
466: switch (message) {
467: case WM_SIZE:
468:
469: case WM_CREATE: {
470: PTHREADBLOCKINFO pThreadBlockInfo;
471: PNODE pHead;
472: HANDLE hHead, hTmp;
473:
474:
475:
476: // now find match
477: hHead = (HANDLE) GetWindowLong(ghwndMain, 0);
478: if (hHead) {
479: if ((pHead = (PNODE)LocalLock(hHead))==NULL)
480: MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK);
481:
482: while ((pHead->ThreadWindow.hwndThreadWindow != hwnd) &&
483: (pHead->hNext != NULL)) {
484: hTmp = hHead;
485: hHead = pHead->hNext;
486: LocalUnlock(hTmp);
487:
488: if ((pHead = (PNODE) LocalLock(hHead))==NULL)
489: MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK);
490: }
491: if (pHead->ThreadWindow.hwndThreadWindow == hwnd) {
492: pThreadBlockInfo = &pHead->ThreadWindow;
493: goto Thread_Found;
494: } else {
495: //MessageBox(ghwndMain, "Trouble - Can't find the thread node!", "Error", MB_OK);
496: goto Thread_Out;
497: }
498:
499: Thread_Found:
500: if (!GetClientRect(pThreadBlockInfo->hwndThreadWindow,
501: &pThreadBlockInfo->rcClient))
502: MessageBox(ghwndMain, "Failed in GetClientRect!", "Error", MB_OK);
503: Thread_Out:
504: LocalUnlock(hHead);
505:
506: return DefMDIChildProc(hwnd, message, wParam, lParam);
507: } else {
508: //MessageBox(ghwndMain, "Can't GetWindowLong(ghwndMain,0) !", "Error", MB_OK);
509: } return DefMDIChildProc(hwnd, message, wParam, lParam);
510: }
511:
512: case WM_CLOSE: {
513: PTHREADBLOCKINFO pThreadBlockInfo;
514: PNODE pHead;
515: HANDLE hHead, hTmp;
516:
517:
518:
519: // now find match
520: hHead = (HANDLE) GetWindowLong(ghwndMain, 0);
521: if (hHead) {
522: if ((pHead = (PNODE)LocalLock(hHead))==NULL)
523: MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK);
524:
525: while ((pHead->ThreadWindow.hwndThreadWindow != hwnd) &&
526: (pHead->hNext != NULL)) {
527: hTmp = hHead;
528: hHead = pHead->hNext;
529: LocalUnlock(hTmp);
530:
531: if ((pHead = (PNODE) LocalLock(hHead))==NULL)
532: MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK);
533: }
534: if (pHead->ThreadWindow.hwndThreadWindow == hwnd) {
535: pThreadBlockInfo = &pHead->ThreadWindow;
536: goto Thread_Found1;
537: } else {
538: //MessageBox(ghwndMain, "Trouble - Can't find the thread node!", "Error", MB_OK);
539: goto Thread_Out1;
540: }
541:
542: Thread_Found1:
543: pThreadBlockInfo->bKillThrd = TRUE;
544:
545: Thread_Out1:
546: LocalUnlock(hHead);
547:
548: } else {
549: //MessageBox(ghwndMain, "Can't GetWindowLong(ghwndMain,0) !", "Error", MB_OK);
550: }
551: return DefMDIChildProc(hwnd, message, wParam, lParam);
552: }
553:
554: case WM_DESTROY:
555:
556:
557: return 0L;
558:
559: default:
560: return DefMDIChildProc(hwnd, message, wParam, lParam);
561: }
562:
563: }
564:
565:
566: /***************************************************************************\
567: * About
568: *
569: * About dialog proc.
570: *
571: * History:
572: * 04-13-91 ??????? Created.
573:
574: * 09-09-91 PetrusW Rewrote.
575: \***************************************************************************/
576:
577: long About(
578: HWND hDlg,
579: UINT message,
580: DWORD wParam,
581: LONG lParam)
582: {
583: switch (message) {
584: case WM_INITDIALOG:
585: return TRUE;
586:
587: case WM_COMMAND:
588: if (wParam == IDOK)
589: EndDialog(hDlg, wParam);
590: break;
591: }
592:
593: return FALSE;
594:
595: lParam;
596: hDlg;
597: }
598:
599: long StartBounce(PTHREADBLOCKINFO pThreadBlockInfo)
600: {
601: if (!StartDemo(MM_BOUNCE, pThreadBlockInfo))
602: return(0);
603:
604: cmdDemo = MM_BOUNCE;
605: /* Here everythings been initialized, ThreadBlockINfo, etc*/
606: /* Now loop and call BounceProc to draw and move boxes*/
607:
608: /* NOTE NOTE, each thread MUST have its own message loop!*/
609:
610: while (TRUE) {
611:
612: if (!bKillMe && !pThreadBlockInfo->bKillThrd) {
613: BounceProc(pThreadBlockInfo);
614: } else {
615: break;
616: }
617: }
618:
619:
620: ExitThread(0);
621: if (!CloseHandle(pThreadBlockInfo->hThread))
622: MessageBox(ghwndMain, "Failed in CloseHandle!", "Error", MB_OK);
623: }
624:
625:
626: BOOL StartDemo(
627: int cmd,
628: PTHREADBLOCKINFO pThreadBlockInfo)
629: {
630:
631: // Initializing the rcClient for the bouncing box
632: // Better be initializing here for once CreateThread is called, this
633: // thread got the time slice; parent thread is preempted.
634: if (!GetClientRect(pThreadBlockInfo->hwndThreadWindow,
635: &pThreadBlockInfo->rcClient))
636: MessageBox(ghwndMain, "Failed in GetClientRect!", "Error", MB_OK);
637: pThreadBlockInfo->bKillThrd = FALSE;
638:
639: InitializeBoxes(FALSE, pThreadBlockInfo);
640:
641: return TRUE;
642: UNREFERENCED_PARAMETER(cmd);
643: }
644:
645:
646: void InitializeBoxes(
647: BOOL fVectorsOnly,
648: PTHREADBLOCKINFO pThreadBlockInfo)
649: {
650: int j;
651: int i;
652:
653: /*
654: * Initialize bounce arrays...
655: */
656: for (i = 0; i < COBJS; i++) {
657:
658: if (!fVectorsOnly) {
659: for (j = 0; j < CPOINTS; j++) {
660: pThreadBlockInfo->gab[i].apt[j].x = 0;
661: pThreadBlockInfo->gab[i].apt[j].y = 0;
662: }
663: pThreadBlockInfo->gab[i].iColor = 0;
664: }
665:
666: if (GetRandomVector() <= 3) {
667: if (GetRandomVector() >= 4) {
668: pThreadBlockInfo->gab[i].vx = 4;
669: } else {
670: pThreadBlockInfo->gab[i].vx = 1;
671: }
672:
673: pThreadBlockInfo->gab[i].vy = GetRandomVector();
674: } else {
675: if (GetRandomVector() >= 4) {
676: pThreadBlockInfo->gab[i].vy = 4;
677: } else {
678: pThreadBlockInfo->gab[i].vy = 1;
679: }
680:
681: pThreadBlockInfo->gab[i].vx = GetRandomVector();
682: }
683:
684: pThreadBlockInfo->gab[i].dx = pThreadBlockInfo->gab[i].vx;
685: pThreadBlockInfo->gab[i].dy = pThreadBlockInfo->gab[i].vy;
686:
687: pThreadBlockInfo->gab[i].ax = GetRandomVector() + 3;
688: pThreadBlockInfo->gab[i].ay = GetRandomVector() + 3;
689: }
690: }
691:
692: int GetRandomVector()
693: {
694: /*
695: * Returns a number between 1 and 6.
696: */
697: return (rand() % 6) + 1;
698: }
699:
700: void BounceProc( PTHREADBLOCKINFO pThreadBlockInfo)
701: {
702: int i;
703: LONG lCurrentThreadId;
704:
705: #ifdef LATER
706: // not erasing looks cool
707: /*
708: * Erase...
709: */
710: for (i = 0; i < COBJS; i++)
711: DrawBox(gab[i].apt[0].x, gab[i].apt[0].y, ghbrWhite);
712: #endif
713:
714:
715: /*
716: * Move, and bounce on wall
717: */
718: for (i = 0; i < COBJS; i++)
719: MoveBox((int *)&pThreadBlockInfo->gab[i].apt[0].x, (int *)&pThreadBlockInfo->gab[i].apt[0].y,
720: (int *)&pThreadBlockInfo->gab[i].dx, (int *)&pThreadBlockInfo->gab[i].dy,
721: (int *)&pThreadBlockInfo->gab[i].vx, (int *)&pThreadBlockInfo->gab[i].vy,
722: (int)pThreadBlockInfo->gab[i].ax, (int)pThreadBlockInfo->gab[i].ay, pThreadBlockInfo);
723:
724: /*
725: * Draw new...
726: */
727: for (i = 0; i < COBJS; i++) {
728: DrawBox(pThreadBlockInfo->gab[i].apt[0].x, pThreadBlockInfo->gab[i].apt[0].y,
729: gahbrColor[pThreadBlockInfo->gab[i].iColor++ % CCOLORS], pThreadBlockInfo);
730: }
731:
732: UNREFERENCED_PARAMETER(lCurrentThreadId);
733: }
734:
735: void DrawBox(
736: int x,
737: int y,
738: HBRUSH hbr,
739: PTHREADBLOCKINFO pThreadBlockInfo)
740: {
741: HBRUSH hbrOld;
742:
743: pThreadBlockInfo->hdcThreadWindow =
744: GetDC(pThreadBlockInfo->hwndThreadWindow);
745: if (pThreadBlockInfo->hdcThreadWindow) {
746: if ((hbrOld = SelectObject(pThreadBlockInfo->hdcThreadWindow, hbr))==0)
747: MessageBox(ghwndMain, "Failed in SelectObject!", "Error", MB_OK);
748: if (!BitBlt(pThreadBlockInfo->hdcThreadWindow, x, y, 20, 20, NULL, 0, 0, PATCOPY))
749: MessageBox(ghwndMain, "Failed in BitBlt!", "Error", MB_OK);
750: if (SelectObject(pThreadBlockInfo->hdcThreadWindow, hbrOld)==0)
751: MessageBox(ghwndMain, "Failed in SelectObject!", "Error", MB_OK);
752: if (ReleaseDC(pThreadBlockInfo->hwndThreadWindow, pThreadBlockInfo->hdcThreadWindow)==0)
753: MessageBox(ghwndMain, "Failed in ReleaseDC!", "Error", MB_OK);
754: } else {
755: MessageBox(ghwndMain, "Failed in GetDC!", "Error", MB_OK);
756: }
757: }
758:
759: void MoveBox(
760: int *px,
761: int *py,
762: int *pdx,
763: int *pdy,
764: int *pvx,
765: int *pvy,
766: int ax,
767: int ay,
768: PTHREADBLOCKINFO pThreadBlockInfo)
769: {
770:
771: (*pdx)--;
772: if (*pdx == 0) {
773: *px -= ax;
774: *pdx = *pvx;
775: } else if (*pdx == 3) {
776: *px += ax;
777: *pdx = *pvx;
778: }
779:
780: (*pdy)--;
781: if (*pdy == 0) {
782: *py -= ay;
783: *pdy = *pvy;
784: } else if (*pdy == 3) {
785: *py += ay;
786: *pdy = *pvy;
787: }
788:
789: if (*px < pThreadBlockInfo->rcClient.left) {
790: *px = pThreadBlockInfo->rcClient.left;
791:
792: if (*pvx >= 4)
793: *pvx -= 3;
794: else
795: *pvx += 3;
796:
797: *pdx = *pvx;
798: }
799:
800: if (*px > (pThreadBlockInfo->rcClient.right - 20)) {
801: *px = pThreadBlockInfo->rcClient.right - 20;
802:
803: if (*pvx >= 4)
804: *pvx -= 3;
805: else
806: *pvx += 3;
807:
808: *pdx = *pvx;
809: }
810:
811: if (*py < pThreadBlockInfo->rcClient.top) {
812: *py = pThreadBlockInfo->rcClient.top;
813:
814: if (*pvy >= 4)
815: *pvy -= 3;
816: else
817: *pvy += 3;
818:
819: *pdy = *pvy;
820: }
821:
822: if (*py > (pThreadBlockInfo->rcClient.bottom - 20)) {
823: *py = pThreadBlockInfo->rcClient.bottom - 20;
824:
825: if (*pvy >= 4)
826: *pvy -= 3;
827: else
828: *pvy += 3;
829:
830: *pdy = *pvy;
831: }
832: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.