Annotation of mstools/samples/mltithrd/mltithrd.c, revision 1.1.1.4

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.