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