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

1.1.1.3 ! 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:                                                                                                                                          
1.1       root       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);
1.1.1.3 ! root      136: int WINAPI MainWndProc     (HWND, UINT, DWORD, LONG);
        !           137: int WINAPI ThreadWndProc   (HWND, UINT, DWORD, LONG);
        !           138: int WINAPI About                (HWND, UINT, DWORD, LONG);
1.1       root      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: 
1.1.1.3 ! root      157: int WINAPI WinMain(
1.1       root      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;
1.1.1.3 ! root      212:     wc.lpfnWndProc      = (WNDPROC) MainWndProc;
1.1       root      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;
1.1.1.3 ! root      226:     wc.lpfnWndProc      = (WNDPROC) ThreadWndProc;
1.1       root      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: 
1.1.1.3 ! root      269: int WINAPI MainWndProc(
1.1       root      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,
1.1.1.3 ! root      394:                                         CREATE_SUSPENDED,
1.1       root      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:
1.1.1.3 ! root      437:                if (DialogBox(ghModule, "AboutBox", ghwndMain, About) == -1)
1.1       root      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: 
1.1.1.3 ! root      460: int WINAPI ThreadWndProc(
1.1       root      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: 
1.1.1.3 ! root      577: int WINAPI About(
1.1       root      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: }

unix.superglobalmegacorp.com

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