--- mstools/samples/mltithrd/mltithrd.c 2018/08/09 18:21:42 1.1.1.3 +++ mstools/samples/mltithrd/mltithrd.c 2018/08/09 18:23:45 1.1.1.4 @@ -1,61 +1,63 @@ + +/******************************************************************************\ +* This is a part of the Microsoft Source Code Samples. +* Copyright (C) 1993 Microsoft Corporation. +* All rights reserved. +* This source code is only intended as a supplement to +* Microsoft Development Tools and/or WinHelp documentation. +* See these sources for detailed information regarding the +* Microsoft samples programs. +\******************************************************************************/ + /****************************** Module Header ******************************\ * Module Name: demo.c -* -* Copyright (c) 1991, Microsoft Corporation -* -* Yet another User test program. -* -* History: -* 04-17-90 ??????? Created. - -* 09-09-91 PetrusW Rewrote. -* create as many threads (windows) as we wish -* change the UI to MDI \***************************************************************************/ -/* ******MULTI-THREADED GUIDE******** +/* ******MULTI-THREADED GUIDE******** - There are aspects to a multi-threaded app, that need be explained, - so that a programmer understand the pitfalls of a multi-threaded app, - and avoid future problems in a multi-threaded application. - - The primary pifalls involve the usage of GDI objects. (DC's, regions, etc). - GDI is the only subsytem in NT win32, that does NOT serialize access - to its objects. This is for speed/throughput reasons. The premise - of GDI objects, is that an object is per process owned, per thread locked. - - This means if you have multiple threads, accessing the same GDI object, - you will have MAJOR headaches, because while one thread deletes an object, - the other may be using it. The model we put forward towards developers, is - the following model. - - Seperate threads for - - > Input - > File IO - > Printing - > Graphics * Note its ok to have graphics/Printing threads, because - The use a different device. - - - Note that you can be single threaded, and have no GDI object serialization - problems. What types of problems occur, is when seperate threads attempt - to delete/use a GDI object, or share an object between multiple threads. - Since an object is per thread locked, means you will get an unexpected - error within the other thread. Many windows programmers, do not expect - certain calls to ever fail, but a poorly constructed multi-threaded app - under win32 (given the above scenerios) may fail, and if not checked, - will cause subsequent GDI calls to fail, ultimately causing the GDI client - side server to die, taking the app with it. +There are aspects to a multi-threaded app, that need be explained, +so that a programmer understand the pitfalls of a multi-threaded app, +and avoid future problems in a multi-threaded application. + +The primary pifalls involve the usage of GDI objects. (DC's, regions, etc). +GDI is the only subsytem in NT win32, that does NOT serialize access +to its objects. This is for speed/throughput reasons. The premise +of GDI objects, is that an object is per process owned, per thread locked. + + This means if you have multiple threads, accessing the same GDI object, +you will have MAJOR headaches, because while one thread deletes an object, +the other may be using it. The model we put forward towards developers, is +the following model. + + Seperate threads for + + > Input + > File IO + > Printing + > Graphics + +* Note its ok to have graphics/Printing threads, because the use a different + device. + + +Note that you can be single threaded, and have no GDI object serialization +problems. What types of problems occur, is when seperate threads attempt +to delete/use a GDI object, or share an object between multiple threads. +Since an object is per thread locked, means you will get an unexpected +error within the other thread. Many windows programmers, do not expect +certain calls to ever fail, but a poorly constructed multi-threaded app +under win32 (given the above scenerios) may fail, and if not checked, +will cause subsequent GDI calls to fail, ultimately causing the GDI client +side server to die, taking the app with it. - Thus its most important to realize that while multi-threaded apps are cool, - they must be programmed with respect to the above guidelines. +Thus its most important to realize that while multi-threaded apps are cool, +they must be programmed with respect to the above guidelines. */ - + #include #include "mltithrd.h" @@ -63,7 +65,7 @@ #define CCOLORS 16 #define CPOINTS 20 -#define COBJS 1 +#define COBJS 1 /* @@ -73,7 +75,7 @@ HANDLE ghModule; HWND ghwndMain = NULL; HBRUSH ghbrWhite, ghbrBlack; HBRUSH gahbrColor[CCOLORS]; -int cmdDemo = 0; +int cmdDemo = 0; BOOL bKillMe = FALSE; HMENU hMenu, hMenuWindow; @@ -111,21 +113,21 @@ typedef struct _b { typedef struct _ThreadBlockInfo { - HANDLE hThread; - BOOL bKillThrd; - HWND hwndClient; - HWND hwndThreadWindow; - LONG lThreadId; - char CaptionBarText[SIZEOFCAPTIONTEXT]; - B gab[COBJS]; - RECT rcClient; - HDC hdcThreadWindow; + HANDLE hThread; + BOOL bKillThrd; + HWND hwndClient; + HWND hwndThreadWindow; + LONG lThreadId; + char CaptionBarText[SIZEOFCAPTIONTEXT]; + B gab[COBJS]; + RECT rcClient; + HDC hdcThreadWindow; } THREADBLOCKINFO, *PTHREADBLOCKINFO; typedef struct _node { THREADBLOCKINFO ThreadWindow; - HANDLE hNext; + HANDLE hNext; } NODE, *PNODE; @@ -135,23 +137,17 @@ typedef struct _node { BOOL InitializeApp (void); int WINAPI MainWndProc (HWND, UINT, DWORD, LONG); int WINAPI ThreadWndProc (HWND, UINT, DWORD, LONG); -int WINAPI About (HWND, UINT, DWORD, LONG); - +int WINAPI About (HWND, UINT, DWORD, LONG); LONG StartBounce (PTHREADBLOCKINFO); -void DrawBox (int, int, HBRUSH, PTHREADBLOCKINFO); -void MoveBox (int *px, int *py, int *pdx, int *pdy, int *pvx, int *pvy, int ax, int ay, PTHREADBLOCKINFO pThreadBlockInfo); +void DrawBox (int, int, HBRUSH, PTHREADBLOCKINFO); +void MoveBox (int *px, int *py, int *pdx, int *pdy, int *pvx, int *pvy, int ax, int ay, PTHREADBLOCKINFO pThreadBlockInfo); void BounceProc (PTHREADBLOCKINFO); -BOOL StartDemo (int, PTHREADBLOCKINFO); +BOOL StartDemo (int, PTHREADBLOCKINFO); int GetRandomVector (); void InitializeBoxes (BOOL, PTHREADBLOCKINFO); /***************************************************************************\ * main -* -* -* History: -* 04-17-91 ??????? Created. - \***************************************************************************/ int WINAPI WinMain( @@ -167,10 +163,20 @@ int WINAPI WinMain( ghModule = GetModuleHandle(NULL); if (!InitializeApp()) { - MessageBox(ghwndMain, "MLTITHRD: InitializeApp failure!", "Error", MB_OK); + MessageBox(ghwndMain, "MLTITHRD: InitializeApp failure!", "Error", MB_OK); return 0; } +/* +** DEMO MODE - These PostMessages are for Demonstration Only +*/ + + PostMessage(ghwndMain, WM_COMMAND, MM_BOUNCE, 0); + PostMessage(ghwndMain, WM_COMMAND, MM_BOUNCE, 0); + PostMessage(ghwndMain, WM_COMMAND, MM_BOUNCE, 0); + PostMessage(ghwndMain, WM_COMMAND, MM_BOUNCE, 0); + PostMessage(ghwndMain, WM_COMMAND, IDM_TILE, 0); + while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -187,11 +193,6 @@ int WINAPI WinMain( /***************************************************************************\ * InitializeApp -* -* History: -* 04-17-91 ??????? Created. - -* 09-09-91 PetrusW Rewrote. \***************************************************************************/ BOOL InitializeApp(void) @@ -211,7 +212,7 @@ BOOL InitializeApp(void) wc.style = CS_OWNDC; wc.lpfnWndProc = (WNDPROC) MainWndProc; wc.cbClsExtra = 0; - wc.cbWndExtra = sizeof(LONG); + wc.cbWndExtra = sizeof(LONG); wc.hInstance = ghModule; wc.hIcon = LoadIcon(ghModule,MAKEINTRESOURCE(APPICON)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); @@ -220,17 +221,17 @@ BOOL InitializeApp(void) wc.lpszClassName = "MltithrdClass"; if (!RegisterClass(&wc)) - return FALSE; + return FALSE; - wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; + wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC) ThreadWndProc; wc.cbClsExtra = 0; - wc.cbWndExtra = 0; + wc.cbWndExtra = 0; wc.hInstance = ghModule; wc.hIcon = LoadIcon(ghModule,MAKEINTRESOURCE(APPICON)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = ghbrWhite; - wc.lpszMenuName = NULL; + wc.lpszMenuName = NULL; wc.lpszClassName = "ThreadClass"; if (!RegisterClass(&wc)) @@ -244,10 +245,10 @@ BOOL InitializeApp(void) WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_VISIBLE | WS_SYSMENU, 80, 70, 400, 300, - NULL, hMenu, ghModule, NULL); + NULL, hMenu, ghModule, NULL); if (ghwndMain == NULL) - return FALSE; + return FALSE; SetWindowLong(ghwndMain, GWL_USERDATA, 0L); @@ -259,11 +260,6 @@ BOOL InitializeApp(void) /***************************************************************************\ * MainWndProc -* -* History: -* 04-17-91 ??????? Created. - -* 09-09-91 PetrusW Rewrote. \***************************************************************************/ int WINAPI MainWndProc( @@ -272,7 +268,7 @@ int WINAPI MainWndProc( DWORD wParam, LONG lParam) { - static int iCount=1; + static int iCount=1; static HWND hwndClient; CLIENTCREATESTRUCT clientcreate; HWND hwndChildWindow; @@ -282,179 +278,160 @@ int WINAPI MainWndProc( case WM_CREATE: - SetWindowLong(hwnd, 0, (LONG)NULL); + SetWindowLong(hwnd, 0, (LONG)NULL); - clientcreate.hWindowMenu = hMenuWindow; - clientcreate.idFirstChild = 1; + clientcreate.hWindowMenu = hMenuWindow; + clientcreate.idFirstChild = 1; - hwndClient = CreateWindow("MDICLIENT", NULL, - WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, - 0,0,0,0, - hwnd, NULL, ghModule, (LPVOID)&clientcreate); - return 0L; + hwndClient = CreateWindow("MDICLIENT", NULL, + WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE, + 0,0,0,0, + hwnd, NULL, ghModule, (LPVOID)&clientcreate); + return 0L; case WM_DESTROY: { - HANDLE hHead, hTmp; - PNODE pHead; + HANDLE hHead, hTmp; + PNODE pHead; + + bKillMe = TRUE; - bKillMe = TRUE; + hHead = (HANDLE) GetWindowLong(hwnd, 0); + if (hHead) { + if ((pHead = (PNODE) LocalLock(hHead))==NULL) + MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK); + while (pHead->hNext != NULL) { + + hTmp = hHead; + hHead = pHead->hNext; + LocalUnlock(hTmp); + + if (LocalFree(hTmp)!=NULL) + MessageBox(ghwndMain, "Failed in LocalFree!", "Error", MB_OK); + if ((pHead = (PNODE) LocalLock(hHead))==NULL) + MessageBox(ghwndMain, "Failed in LocalLock, hHead!", "Error", MB_OK); + } + LocalUnlock(hHead); - hHead = (HANDLE) GetWindowLong(hwnd, 0); - if (hHead) { - if ((pHead = (PNODE) LocalLock(hHead))==NULL) - MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK); - while (pHead->hNext != NULL) { - - hTmp = hHead; - hHead = pHead->hNext; - LocalUnlock(hTmp); - - if (LocalFree(hTmp)!=NULL) - MessageBox(ghwndMain, "Failed in LocalFree!", "Error", MB_OK); - if ((pHead = (PNODE) LocalLock(hHead))==NULL) - MessageBox(ghwndMain, "Failed in LocalLock, hHead!", "Error", MB_OK); - } - LocalUnlock(hHead); - - if (LocalFree(hHead)!=NULL) - MessageBox(ghwndMain, "LocalFree failed to free hHead!", "Error", MB_OK); - } - PostQuitMessage(0); - return 0L; + if (LocalFree(hHead)!=NULL) + MessageBox(ghwndMain, "LocalFree failed to free hHead!", "Error", MB_OK); + } + PostQuitMessage(0); + return 0L; } #ifdef LATER case WM_LBUTTONDOWN: - InitializeBoxes(TRUE, &ThreadWindow); - break; + InitializeBoxes(TRUE, &ThreadWindow); + break; #endif case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDM_TILE: - SendMessage(hwndClient, WM_MDITILE, 0L, 0L); - return 0L; - case IDM_CASCADE: - SendMessage(hwndClient, WM_MDICASCADE, 0L, 0L); - return 0L; - case IDM_ARRANGE: - SendMessage(hwndClient, WM_MDIICONARRANGE, 0L, 0L); - return 0L; - case MM_BOUNCE: { - HANDLE hNode, hHead; - HANDLE hThrd; - PNODE pNode; + switch (LOWORD(wParam)) { + case IDM_TILE: + SendMessage(hwndClient, WM_MDITILE, 0L, 0L); + return 0L; + case IDM_CASCADE: + SendMessage(hwndClient, WM_MDICASCADE, 0L, 0L); + return 0L; + case IDM_ARRANGE: + SendMessage(hwndClient, WM_MDIICONARRANGE, 0L, 0L); + return 0L; + case MM_BOUNCE: { + HANDLE hNode, hHead; + HANDLE hThrd; + PNODE pNode; MDICREATESTRUCT mdicreate; - hNode = LocalAlloc(LHND, (WORD) sizeof(NODE)); - if (hNode) { - if ((pNode = (PNODE)LocalLock(hNode))==NULL) - MessageBox(ghwndMain, "Failed in LocalLock, hNode!", "Error", MB_OK); - - wsprintf((LPSTR)&(pNode->ThreadWindow.CaptionBarText), "Thread Window %d", iCount); - - mdicreate.szClass = "ThreadClass"; - mdicreate.szTitle = (LPSTR)&(pNode->ThreadWindow.CaptionBarText); - mdicreate.hOwner = ghModule; - mdicreate.x = - mdicreate.y = - mdicreate.cx = - mdicreate.cy = CW_USEDEFAULT; - mdicreate.style = 0l; - mdicreate.lParam = 0L; - - /*Create Child Window*/ - hwndChildWindow = (HANDLE) SendMessage(hwndClient, WM_MDICREATE, - 0L, - (LONG)(LPMDICREATESTRUCT)&mdicreate); - - if (hwndChildWindow == NULL) { - MessageBox(ghwndMain, "Failed in Creating Thread Window!", "Error", MB_OK); - return 0L; - } - - // This stuff is here for simplicity. Initialization should - // be done in StartDemo - pNode->ThreadWindow.hwndClient = hwndClient; - pNode->ThreadWindow.hwndThreadWindow = hwndChildWindow; - hHead = (HANDLE)GetWindowLong(hwnd, 0); - pNode->hNext = hHead; - SetWindowLong(hwnd, 0, (LONG) hNode); + hNode = LocalAlloc(LHND, (WORD) sizeof(NODE)); + if (hNode) { + if ((pNode = (PNODE)LocalLock(hNode))==NULL) + MessageBox(ghwndMain, "Failed in LocalLock, hNode!", "Error", MB_OK); + + wsprintf((LPSTR)&(pNode->ThreadWindow.CaptionBarText), "Thread Window %d", iCount); + + mdicreate.szClass = "ThreadClass"; + mdicreate.szTitle = (LPSTR)&(pNode->ThreadWindow.CaptionBarText); + mdicreate.hOwner = ghModule; + mdicreate.x = + mdicreate.y = + mdicreate.cx = + mdicreate.cy = CW_USEDEFAULT; + mdicreate.style = 0l; + mdicreate.lParam = 0L; + + /*Create Child Window*/ + hwndChildWindow = (HANDLE) SendMessage(hwndClient, WM_MDICREATE, + 0L, + (LONG)(LPMDICREATESTRUCT)&mdicreate); + + if (hwndChildWindow == NULL) { + MessageBox(ghwndMain, "Failed in Creating Thread Window!", "Error", MB_OK); + return 0L; + } + + // This stuff is here for simplicity. Initialization should + // be done in StartDemo + pNode->ThreadWindow.hwndClient = hwndClient; + pNode->ThreadWindow.hwndThreadWindow = hwndChildWindow; + hHead = (HANDLE)GetWindowLong(hwnd, 0); + pNode->hNext = hHead; + SetWindowLong(hwnd, 0, (LONG) hNode); // Create the thread suspended so we can alter its priority - // before it begins to run. - - - hThrd = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE)StartBounce, - &pNode->ThreadWindow, - CREATE_SUSPENDED, - - (LPDWORD) &pNode->ThreadWindow.lThreadId ); - if (hThrd) { - - // I really don't need this info, it won't even be - // updated right the way for this thread will be - // preempted. - pNode->ThreadWindow.hThread = hThrd; - iCount++; - + hThrd = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE)StartBounce, + &pNode->ThreadWindow, + CREATE_SUSPENDED, + (LPDWORD) &pNode->ThreadWindow.lThreadId ); + if (hThrd) { + + // I really don't need this info, it won't even be + // updated right the way for this thread will be + // preempted. + pNode->ThreadWindow.hThread = hThrd; + iCount++; // This way the primary (input) thread will be higher priority - // than the bouncers, thus keeping MLTITHRD responsive to user - // input. - - SetThreadPriority(hThrd, THREAD_PRIORITY_BELOW_NORMAL); - - // Everything's set, let it go. - - ResumeThread(hThrd); + } else { + MessageBox(ghwndMain, "Create Thread Failed!", "Error", MB_OK); + } + LocalUnlock(hNode); + + } else { + MessageBox(ghwndMain, "Failed to Allocate Node!", "Error", MB_OK); + } + return 0L; + } - } else { - MessageBox(ghwndMain, "Create Thread Failed!", "Error", MB_OK); - } - LocalUnlock(hNode); - - } else { - MessageBox(ghwndMain, "Failed to Allocate Node!", "Error", MB_OK); - } - return 0L; - } - - case MM_ABOUT: - if (DialogBox(ghModule, "AboutBox", ghwndMain, About) == -1) - MessageBox(ghwndMain, "Mltithrd: About Dialog Creation Error!", "Error", MB_OK); - return 0L; + case MM_ABOUT: + if (DialogBox(ghModule, "AboutBox", ghwndMain, About) == -1) + MessageBox(ghwndMain, "Mltithrd: About Dialog Creation Error!", "Error", MB_OK); + return 0L; - default: - return DefFrameProc(hwnd, hwndClient, message, wParam, lParam); + default: + return DefFrameProc(hwnd, hwndClient, message, wParam, lParam); } default: - return DefFrameProc(hwnd, hwndClient, message, wParam, lParam); + return DefFrameProc(hwnd, hwndClient, message, wParam, lParam); } } /********************************************************************\ * ThreadWndProc -* -* History: -* 04-17-91 ??????? Created. - -* 09-09-91 PetrusW Rewrote. \***************************************************************************/ int WINAPI ThreadWndProc( @@ -464,100 +441,101 @@ int WINAPI ThreadWndProc( LONG lParam) { switch (message) { - case WM_SIZE: + case WM_SIZE: - case WM_CREATE: { - PTHREADBLOCKINFO pThreadBlockInfo; - PNODE pHead; - HANDLE hHead, hTmp; + case WM_CREATE: { + PTHREADBLOCKINFO pThreadBlockInfo; + PNODE pHead; + HANDLE hHead, hTmp; - // now find match - hHead = (HANDLE) GetWindowLong(ghwndMain, 0); - if (hHead) { - if ((pHead = (PNODE)LocalLock(hHead))==NULL) - MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK); - - while ((pHead->ThreadWindow.hwndThreadWindow != hwnd) && - (pHead->hNext != NULL)) { - hTmp = hHead; - hHead = pHead->hNext; - LocalUnlock(hTmp); - - if ((pHead = (PNODE) LocalLock(hHead))==NULL) - MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK); - } - if (pHead->ThreadWindow.hwndThreadWindow == hwnd) { - pThreadBlockInfo = &pHead->ThreadWindow; - goto Thread_Found; - } else { - //MessageBox(ghwndMain, "Trouble - Can't find the thread node!", "Error", MB_OK); - goto Thread_Out; - } + // now find match + hHead = (HANDLE) GetWindowLong(ghwndMain, 0); + if (hHead) { + if ((pHead = (PNODE)LocalLock(hHead))==NULL) + MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK); + + while ((pHead->ThreadWindow.hwndThreadWindow != hwnd) && + (pHead->hNext != NULL)) { + hTmp = hHead; + hHead = pHead->hNext; + LocalUnlock(hTmp); + + if ((pHead = (PNODE) LocalLock(hHead))==NULL) + MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK); + } + if (pHead->ThreadWindow.hwndThreadWindow == hwnd) { + pThreadBlockInfo = &pHead->ThreadWindow; + goto Thread_Found; + } else { + //MessageBox(ghwndMain, "Trouble - Can't find the thread node!", "Error", MB_OK); + goto Thread_Out; + } Thread_Found: - if (!GetClientRect(pThreadBlockInfo->hwndThreadWindow, - &pThreadBlockInfo->rcClient)) - MessageBox(ghwndMain, "Failed in GetClientRect!", "Error", MB_OK); + if (!GetClientRect(pThreadBlockInfo->hwndThreadWindow, + &pThreadBlockInfo->rcClient)) + MessageBox(ghwndMain, "Failed in GetClientRect!", "Error", MB_OK); Thread_Out: - LocalUnlock(hHead); + LocalUnlock(hHead); - return DefMDIChildProc(hwnd, message, wParam, lParam); - } else { - //MessageBox(ghwndMain, "Can't GetWindowLong(ghwndMain,0) !", "Error", MB_OK); - } return DefMDIChildProc(hwnd, message, wParam, lParam); - } - - case WM_CLOSE: { - PTHREADBLOCKINFO pThreadBlockInfo; - PNODE pHead; - HANDLE hHead, hTmp; + return DefMDIChildProc(hwnd, message, wParam, lParam); + } else { + //MessageBox(ghwndMain, "Can't GetWindowLong(ghwndMain,0) !", "Error", MB_OK); + } return DefMDIChildProc(hwnd, message, wParam, lParam); + } + case WM_CLOSE: { + PTHREADBLOCKINFO pThreadBlockInfo; + PNODE pHead; + HANDLE hHead, hTmp; - // now find match - hHead = (HANDLE) GetWindowLong(ghwndMain, 0); - if (hHead) { - if ((pHead = (PNODE)LocalLock(hHead))==NULL) - MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK); - - while ((pHead->ThreadWindow.hwndThreadWindow != hwnd) && - (pHead->hNext != NULL)) { - hTmp = hHead; - hHead = pHead->hNext; - LocalUnlock(hTmp); - - if ((pHead = (PNODE) LocalLock(hHead))==NULL) - MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK); - } - if (pHead->ThreadWindow.hwndThreadWindow == hwnd) { - pThreadBlockInfo = &pHead->ThreadWindow; - goto Thread_Found1; - } else { - //MessageBox(ghwndMain, "Trouble - Can't find the thread node!", "Error", MB_OK); - goto Thread_Out1; - } + + // now find match + hHead = (HANDLE) GetWindowLong(ghwndMain, 0); + if (hHead) { + if ((pHead = (PNODE)LocalLock(hHead))==NULL) + MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK); + + while ((pHead->ThreadWindow.hwndThreadWindow != hwnd) && + (pHead->hNext != NULL)) { + hTmp = hHead; + hHead = pHead->hNext; + LocalUnlock(hTmp); + + if ((pHead = (PNODE) LocalLock(hHead))==NULL) + MessageBox(ghwndMain, "Failed in LocalLock!", "Error", MB_OK); + } + if (pHead->ThreadWindow.hwndThreadWindow == hwnd) { + pThreadBlockInfo = &pHead->ThreadWindow; + goto Thread_Found1; + } else { + //MessageBox(ghwndMain, "Trouble - Can't find the thread node!", "Error", MB_OK); + goto Thread_Out1; + } Thread_Found1: - pThreadBlockInfo->bKillThrd = TRUE; + pThreadBlockInfo->bKillThrd = TRUE; + CloseHandle(pThreadBlockInfo->hThread); Thread_Out1: - LocalUnlock(hHead); + LocalUnlock(hHead); - } else { - //MessageBox(ghwndMain, "Can't GetWindowLong(ghwndMain,0) !", "Error", MB_OK); - } - return DefMDIChildProc(hwnd, message, wParam, lParam); - } + } else { + //MessageBox(ghwndMain, "Can't GetWindowLong(ghwndMain,0) !", "Error", MB_OK); + } + return DefMDIChildProc(hwnd, message, wParam, lParam); + } - case WM_DESTROY: + case WM_DESTROY: - return 0L; + return 0L; - default: - return DefMDIChildProc(hwnd, message, wParam, lParam); + default: + return DefMDIChildProc(hwnd, message, wParam, lParam); } } @@ -565,13 +543,6 @@ Thread_Out1: /***************************************************************************\ * About -* -* About dialog proc. -* -* History: -* 04-13-91 ??????? Created. - -* 09-09-91 PetrusW Rewrote. \***************************************************************************/ int WINAPI About( @@ -602,24 +573,21 @@ long StartBounce(PTHREADBLOCKINFO pThrea return(0); cmdDemo = MM_BOUNCE; - /* Here everythings been initialized, ThreadBlockINfo, etc*/ - /* Now loop and call BounceProc to draw and move boxes*/ + /* Here everythings been initialized, ThreadBlockINfo, etc*/ + /* Now loop and call BounceProc to draw and move boxes*/ - /* NOTE NOTE, each thread MUST have its own message loop!*/ + /* NOTE NOTE, each thread MUST have its own message loop!*/ while (TRUE) { if (!bKillMe && !pThreadBlockInfo->bKillThrd) { - BounceProc(pThreadBlockInfo); + BounceProc(pThreadBlockInfo); } else { - break; + break; } } - - ExitThread(0); - if (!CloseHandle(pThreadBlockInfo->hThread)) - MessageBox(ghwndMain, "Failed in CloseHandle!", "Error", MB_OK); + ExitThread(0); } @@ -630,16 +598,16 @@ BOOL StartDemo( // Initializing the rcClient for the bouncing box // Better be initializing here for once CreateThread is called, this - // thread got the time slice; parent thread is preempted. + // thread got the time slice; parent thread is preempted. if (!GetClientRect(pThreadBlockInfo->hwndThreadWindow, - &pThreadBlockInfo->rcClient)) - MessageBox(ghwndMain, "Failed in GetClientRect!", "Error", MB_OK); + &pThreadBlockInfo->rcClient)) + MessageBox(ghwndMain, "Failed in GetClientRect!", "Error", MB_OK); pThreadBlockInfo->bKillThrd = FALSE; InitializeBoxes(FALSE, pThreadBlockInfo); return TRUE; - UNREFERENCED_PARAMETER(cmd); + UNREFERENCED_PARAMETER(cmd); } @@ -700,7 +668,7 @@ int GetRandomVector() void BounceProc( PTHREADBLOCKINFO pThreadBlockInfo) { int i; - LONG lCurrentThreadId; + LONG lCurrentThreadId; #ifdef LATER // not erasing looks cool @@ -729,7 +697,7 @@ void BounceProc( PTHREADBLOCKINFO pThrea gahbrColor[pThreadBlockInfo->gab[i].iColor++ % CCOLORS], pThreadBlockInfo); } - UNREFERENCED_PARAMETER(lCurrentThreadId); + UNREFERENCED_PARAMETER(lCurrentThreadId); } void DrawBox( @@ -741,18 +709,14 @@ void DrawBox( HBRUSH hbrOld; pThreadBlockInfo->hdcThreadWindow = - GetDC(pThreadBlockInfo->hwndThreadWindow); + GetDC(pThreadBlockInfo->hwndThreadWindow); if (pThreadBlockInfo->hdcThreadWindow) { - if ((hbrOld = SelectObject(pThreadBlockInfo->hdcThreadWindow, hbr))==0) - MessageBox(ghwndMain, "Failed in SelectObject!", "Error", MB_OK); - if (!BitBlt(pThreadBlockInfo->hdcThreadWindow, x, y, 20, 20, NULL, 0, 0, PATCOPY)) - MessageBox(ghwndMain, "Failed in BitBlt!", "Error", MB_OK); - if (SelectObject(pThreadBlockInfo->hdcThreadWindow, hbrOld)==0) - MessageBox(ghwndMain, "Failed in SelectObject!", "Error", MB_OK); - if (ReleaseDC(pThreadBlockInfo->hwndThreadWindow, pThreadBlockInfo->hdcThreadWindow)==0) - MessageBox(ghwndMain, "Failed in ReleaseDC!", "Error", MB_OK); + hbrOld = SelectObject(pThreadBlockInfo->hdcThreadWindow, hbr); + BitBlt(pThreadBlockInfo->hdcThreadWindow, x, y, 20, 20, NULL, 0, 0, PATCOPY); + SelectObject(pThreadBlockInfo->hdcThreadWindow, hbrOld); + ReleaseDC(pThreadBlockInfo->hwndThreadWindow, pThreadBlockInfo->hdcThreadWindow); } else { - MessageBox(ghwndMain, "Failed in GetDC!", "Error", MB_OK); + MessageBox(ghwndMain, "Failed in GetDC!", "Error", MB_OK); } } @@ -765,7 +729,7 @@ void MoveBox( int *pvy, int ax, int ay, - PTHREADBLOCKINFO pThreadBlockInfo) + PTHREADBLOCKINFO pThreadBlockInfo) { (*pdx)--; @@ -787,7 +751,7 @@ void MoveBox( } if (*px < pThreadBlockInfo->rcClient.left) { - *px = pThreadBlockInfo->rcClient.left; + *px = pThreadBlockInfo->rcClient.left; if (*pvx >= 4) *pvx -= 3; @@ -798,7 +762,7 @@ void MoveBox( } if (*px > (pThreadBlockInfo->rcClient.right - 20)) { - *px = pThreadBlockInfo->rcClient.right - 20; + *px = pThreadBlockInfo->rcClient.right - 20; if (*pvx >= 4) *pvx -= 3; @@ -809,7 +773,7 @@ void MoveBox( } if (*py < pThreadBlockInfo->rcClient.top) { - *py = pThreadBlockInfo->rcClient.top; + *py = pThreadBlockInfo->rcClient.top; if (*pvy >= 4) *pvy -= 3; @@ -820,7 +784,7 @@ void MoveBox( } if (*py > (pThreadBlockInfo->rcClient.bottom - 20)) { - *py = pThreadBlockInfo->rcClient.bottom - 20; + *py = pThreadBlockInfo->rcClient.bottom - 20; if (*pvy >= 4) *pvy -= 3;