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

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: }

unix.superglobalmegacorp.com

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