1 #include <windows.h> 2 #include <stdio.h> 3 4 ULONG DbgPrint(PCH Format,...); 5 6 typedef struct _THRDCREATEWIN 7 { 8 HANDLE hThread; 9 DWORD ThreadId; 10 LPSTR Caption; 11 HWND *Parent; 12 HWND Window; 13 DWORD Style; 14 POINT Position; 15 SIZE Size; 16 } THRDCREATEWIN, *PTHRDCREATEWIN; 17 18 static HINSTANCE hAppInstance; 19 static HANDLE WinCreatedEvent; 20 static THRDCREATEWIN wnds[3]; 21 22 LRESULT WINAPI MultiWndProc(HWND, UINT, WPARAM, LPARAM); 23 24 DWORD WINAPI 25 WindowThreadProc(LPVOID lpParameter) 26 { 27 MSG msg; 28 char caption[64]; 29 PTHRDCREATEWIN cw = (PTHRDCREATEWIN)lpParameter; 30 31 sprintf(caption, cw->Caption, GetCurrentThreadId()); 32 33 cw->Window = CreateWindow("MultiClass", 34 caption, 35 cw->Style | WS_VISIBLE, 36 cw->Position.x, 37 cw->Position.y, 38 cw->Size.cx, 39 cw->Size.cy, 40 (cw->Parent ? *(cw->Parent) : 0), 41 NULL, 42 hAppInstance, 43 NULL); 44 45 SetEvent(WinCreatedEvent); 46 47 if(!cw->Window) 48 { 49 fprintf(stderr, "CreateWindow failed (last error 0x%lX)\n", 50 GetLastError()); 51 return 1; 52 } 53 CreateWindow("BUTTON","Sleep",WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_GROUP|BS_PUSHBUTTON, 10, 10, 70, 23, cw->Window, (PVOID)1, hAppInstance, NULL); 54 CreateWindow("BUTTON","1",WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_GROUP|BS_PUSHBUTTON, 83, 10, 20, 23, cw->Window, (PVOID)2, hAppInstance, NULL); 55 CreateWindow("BUTTON","2",WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_GROUP|BS_PUSHBUTTON, 105, 10, 20, 23, cw->Window, (PVOID)3, hAppInstance, NULL); 56 CreateWindow("BUTTON","3",WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_GROUP|BS_PUSHBUTTON, 127, 10, 20, 23, cw->Window, (PVOID)4, hAppInstance, NULL); 57 while(GetMessage(&msg, NULL, 0, 0)) 58 { 59 TranslateMessage(&msg); 60 DispatchMessage(&msg); 61 } 62 63 return 0; 64 } 65 66 int WINAPI 67 WinMain(HINSTANCE hInstance, 68 HINSTANCE hPrevInstance, 69 LPSTR lpszCmdLine, 70 int nCmdShow) 71 { 72 WNDCLASS wc; 73 int i; 74 HANDLE Threads[3]; 75 76 hAppInstance = hInstance; 77 78 WinCreatedEvent = CreateEvent(NULL, 79 FALSE, 80 FALSE, 81 NULL); 82 83 if(!WinCreatedEvent) 84 { 85 fprintf(stderr, "Failed to create event (last error 0x%lX)\n", 86 GetLastError()); 87 return 1; 88 } 89 90 wc.lpszClassName = "MultiClass"; 91 wc.lpfnWndProc = MultiWndProc; 92 wc.style = CS_VREDRAW | CS_HREDRAW; 93 wc.hInstance = hInstance; 94 wc.hIcon = LoadIcon(NULL, (LPCTSTR) IDI_APPLICATION); 95 wc.hCursor = LoadCursor(NULL, (LPCTSTR) IDC_ARROW); 96 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); 97 wc.lpszMenuName = NULL; 98 wc.cbClsExtra = 0; 99 wc.cbWndExtra = 0; 100 if (RegisterClass(&wc) == 0) 101 { 102 fprintf(stderr, "RegisterClass failed (last error 0x%lX)\n", 103 GetLastError()); 104 return(1); 105 } 106 107 wnds[0].Caption = "TopLevel1 (ThreadID: %d)"; 108 wnds[0].Parent = NULL; 109 wnds[0].Style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; 110 wnds[0].Position.x = wnds[0].Position.y = 0; 111 wnds[0].Size.cx = 320; 112 wnds[0].Size.cy = 240; 113 114 wnds[1].Caption = "Child1 of TopLevel1 (ThreadID: %d)"; 115 wnds[1].Parent = &wnds[0].Window; 116 wnds[1].Style = WS_CHILD | WS_BORDER | WS_CAPTION | WS_VISIBLE | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; 117 wnds[1].Position.x = 20; 118 wnds[1].Position.y = 120; 119 wnds[1].Size.cx = wnds[1].Size.cy = 240; 120 121 wnds[2].Caption = "TopLevel2 (ThreadID: %d)"; 122 wnds[2].Parent = NULL; 123 wnds[2].Style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; 124 wnds[2].Position.x = 400; 125 wnds[2].Position.y = 0; 126 wnds[2].Size.cx = 160; 127 wnds[2].Size.cy = 490; 128 129 for(i = 0; i < (sizeof(wnds) / sizeof(THRDCREATEWIN)); i++) 130 { 131 wnds[i].hThread = CreateThread(NULL, 132 0, 133 WindowThreadProc, 134 &wnds[i], 135 0, 136 &wnds[i].ThreadId); 137 Threads[i] = wnds[i].hThread; 138 if(!wnds[i].hThread) 139 { 140 fprintf(stderr, "CreateThread #%i failed (last error 0x%lX)\n", 141 i, GetLastError()); 142 return 1; 143 } 144 WaitForSingleObject(WinCreatedEvent, INFINITE); 145 } 146 147 WaitForMultipleObjects(sizeof(Threads) / sizeof(HANDLE), &Threads[0], TRUE, INFINITE); 148 149 UnregisterClass("MultiClass", hInstance); 150 151 return 0; 152 } 153 154 LRESULT CALLBACK MultiWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 155 { 156 PAINTSTRUCT ps; 157 HDC hDC; 158 RECT Client; 159 HBRUSH Brush; 160 DWORD_PTR Ret; 161 162 static COLORREF Colors[] = 163 { 164 RGB(0x00, 0x00, 0x00), 165 RGB(0x80, 0x00, 0x00), 166 RGB(0x00, 0x80, 0x00), 167 RGB(0x00, 0x00, 0x80), 168 RGB(0x80, 0x80, 0x00), 169 RGB(0x80, 0x00, 0x80), 170 RGB(0x00, 0x80, 0x80), 171 RGB(0x80, 0x80, 0x80), 172 RGB(0xff, 0x00, 0x00), 173 RGB(0x00, 0xff, 0x00), 174 RGB(0x00, 0x00, 0xff), 175 RGB(0xff, 0xff, 0x00), 176 RGB(0xff, 0x00, 0xff), 177 RGB(0x00, 0xff, 0xff), 178 RGB(0xff, 0xff, 0xff) 179 }; 180 static unsigned CurrentColor = 0; 181 182 switch(msg) 183 { 184 case WM_PAINT: 185 hDC = BeginPaint(hWnd, &ps); 186 GetClientRect(hWnd, &Client); 187 Brush = CreateSolidBrush(Colors[CurrentColor]); 188 FillRect(hDC, &Client, Brush); 189 DeleteObject(Brush); 190 CurrentColor++; 191 if (sizeof(Colors) / sizeof(Colors[0]) <= CurrentColor) 192 { 193 CurrentColor = 0; 194 } 195 EndPaint(hWnd, &ps); 196 break; 197 198 case WM_COMMAND: 199 switch(LOWORD(wParam)) 200 { 201 case 1: 202 Sleep(20000); 203 break; 204 case 2: 205 case 3: 206 case 4: 207 if(SendMessageTimeout(wnds[LOWORD(wParam) - 2].Window, WM_NULL, 0, 0, SMTO_ABORTIFHUNG, 1000, &Ret)) 208 { 209 DbgPrint("SendMessageTimeout() OK"); 210 MessageBox(hWnd, "SendMessageTimeout() OK", NULL, 0); 211 } 212 else 213 { 214 if(GetLastError() == ERROR_TIMEOUT) 215 { 216 DbgPrint("SendMessageTimeout() Timeout"); 217 MessageBox(hWnd, "SendMessageTimeout() Timeout", NULL, 0); 218 } 219 else 220 { 221 DbgPrint("SendMessageTimeout() Failed"); 222 MessageBox(hWnd, "SendMessageTimeout() Failed", NULL, 0); 223 } 224 } 225 break; 226 } 227 break; 228 229 case WM_DESTROY: 230 PostQuitMessage(0); 231 break; 232 233 default: 234 return DefWindowProc(hWnd, msg, wParam, lParam); 235 } 236 237 return 0; 238 } 239