Time to commit some Work-In-Progress stuff before my diff gets too large..
[reactos.git] / rostests / apitests / user32 / GetDCEx.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for GetDCEx
5 * PROGRAMMERS: Timo Kreuzer
6 */
7
8 #include <stdio.h>
9 #include <wine/test.h>
10 #include <windows.h>
11 #include "helper.h"
12
13 #define DCX_USESTYLE 0x00010000
14
15 void Test_GetDCEx_Params()
16 {
17
18 }
19
20 static
21 LRESULT
22 CALLBACK
23 WndProc(
24 _In_ HWND hwnd,
25 _In_ UINT uMsg,
26 _In_ WPARAM wParam,
27 _In_ LPARAM lParam)
28 {
29 return TRUE;
30 }
31
32 static
33 ATOM
34 RegisterClassHelper(
35 PSTR pszClassName,
36 UINT style,
37 WNDPROC pfnWndProc)
38 {
39 WNDCLASSA cls;
40
41 cls.style = style;
42 cls.lpfnWndProc = pfnWndProc;
43 cls.cbClsExtra = 0;
44 cls.cbWndExtra = 0;
45 cls.hInstance = GetModuleHandleA(0);
46 cls.hIcon = 0;
47 cls.hCursor = LoadCursorA(0, IDC_ARROW);
48 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
49 cls.lpszMenuName = NULL;
50 cls.lpszClassName = pszClassName;
51
52 return RegisterClassA(&cls);
53 }
54
55 static
56 HWND
57 CreateWindowHelper(
58 PSZ pszClassName,
59 PSZ pszTitle)
60 {
61 return CreateWindowA(pszClassName,
62 pszTitle,
63 WS_OVERLAPPEDWINDOW,
64 CW_USEDEFAULT,
65 CW_USEDEFAULT,
66 100,
67 100,
68 NULL,
69 NULL,
70 0,
71 NULL);
72 }
73
74 static
75 void
76 Test_GetDCEx_Cached()
77 {
78 static const PSTR pszClassName = "TestClass_Cached";
79 ATOM atomClass;
80 HWND hwnd;
81 HDC hdc1, hdc2;
82 HRGN hrgn;
83
84 atomClass = RegisterClassHelper(pszClassName, 0, WndProc);
85 ok(atomClass != 0, "Failed to register class\n");
86
87 hwnd = CreateWindowHelper(pszClassName, "Test Window1");
88 ok(hwnd != NULL, "Failed to create hwnd\n");
89
90 hdc1 = GetDCEx(hwnd, 0, 0);
91 ok(hdc1 == NULL, "GetDCEx should fail\n");
92 hrgn = CreateRectRgn(0, 0, 100, 100);
93 hdc1 = GetDCEx(hwnd, hrgn, 0);
94 ok(hdc1 == NULL, "GetDCEx should fail\n");
95
96 hdc1 = GetDCEx(hwnd, 0, DCX_WINDOW);
97 ok(hdc1 == NULL, "GetDCEx should fail\n");
98 hdc1 = GetDCEx(hwnd, hrgn, DCX_WINDOW);
99 ok(hdc1 == NULL, "GetDCEx should fail\n");
100
101 hdc1 = GetDCEx(hwnd, hrgn, DCX_INTERSECTRGN);
102 ok(hdc1 == NULL, "GetDCEx should fail\n");
103
104 hdc1 = GetDCEx(hwnd, hrgn, DCX_PARENTCLIP);
105 ok(hdc1 != NULL, "GetDCEx failed\n");
106 ReleaseDC(hwnd, hdc1);
107
108 hdc1 = GetDCEx(hwnd, hrgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_PARENTCLIP);
109 ok(hdc1 != NULL, "GetDCEx failed\n");
110 ReleaseDC(hwnd, hdc1);
111
112 hdc1 = GetDCEx(hwnd, 0, DCX_CACHE);
113 ok(hdc1 != NULL, "GetDCEx failed\n");
114 ReleaseDC(hwnd, hdc1);
115
116 hrgn = CreateRectRgn(0, 0, 100, 100);
117 hdc2 = GetDCEx(hwnd, hrgn, DCX_CACHE);
118 ok(hdc2 != NULL, "GetDCEx failed\n");
119 ReleaseDC(hwnd, hdc2);
120 ok(hdc2 == hdc1, "Expected the same DC\n");
121
122 hdc1 = GetDCEx(hwnd, 0, DCX_CACHE);
123 hdc2 = GetDCEx(hwnd, hrgn, DCX_CACHE);
124 ok(hdc1 != NULL, "GetDCEx failed\n");
125 ok(hdc2 != hdc1, "Expected a different DC\n");
126 ReleaseDC(hwnd, hdc1);
127 ReleaseDC(hwnd, hdc2);
128
129 hdc1 = GetDCEx(NULL, NULL, 0);
130 ok(hdc1 != NULL, "GetDCEx failed\n");
131 hdc2 = GetDCEx(NULL, NULL, 0);
132 ok(hdc2 != NULL, "GetDCEx failed\n");
133 ok(hdc2 != hdc1, "Expected a different DC\n");
134 ReleaseDC(hwnd, hdc1);
135 ReleaseDC(hwnd, hdc2);
136
137 ok(CombineRgn(hrgn, hrgn, hrgn, RGN_OR) == SIMPLEREGION, "region is not valid");
138
139 DestroyWindow(hwnd);
140 ok(UnregisterClass(pszClassName, GetModuleHandleA(0)) == TRUE,
141 "UnregisterClass failed");
142 }
143
144 static
145 void
146 Test_GetDCEx_CS_OWNDC()
147 {
148 static const PSTR pszClassName = "TestClass_CS_OWNDC";
149 ATOM atomClass;
150 HWND hwnd;
151 HDC hdc1, hdc2;
152 //HRGN hrgn;
153
154 atomClass = RegisterClassHelper(pszClassName, CS_OWNDC, WndProc);
155 ok(atomClass != 0, "Failed to register class\n");
156
157 hwnd = CreateWindowHelper(pszClassName, "Test Window1");
158 ok(hwnd != NULL, "Failed to create hwnd\n");
159
160 hdc1 = GetDCEx(hwnd, NULL, 0);
161 ok(hdc1 != NULL, "GetDCEx failed\n");
162 hdc2 = GetDCEx(hwnd, NULL, 0);
163 ok(hdc2 != NULL, "GetDCEx failed\n");
164 ok(hdc2 == hdc1, "Expected the same DC\n");
165 ok(ReleaseDC(hwnd, hdc1) == TRUE, "ReleaseDC failed\n");
166 ok(ReleaseDC(hwnd, hdc2) == TRUE, "ReleaseDC failed\n");
167
168 hdc2 = GetDCEx(hwnd, NULL, 0);
169 ok(hdc2 == hdc1, "Expected the same DC\n");
170 ok(ReleaseDC(hwnd, hdc2) == TRUE, "ReleaseDC failed\n");
171
172 hdc2 = GetDCEx(hwnd, NULL, DCX_CACHE);
173 ok(hdc2 != hdc1, "Expected a different DC\n");
174 ok(ReleaseDC(hwnd, hdc2) == TRUE, "ReleaseDC failed\n");
175
176 hdc2 = GetDCEx(hwnd, NULL, DCX_WINDOW);
177 ok(hdc2 == hdc1, "Expected the same DC\n");
178 ok(ReleaseDC(hwnd, hdc2) == TRUE, "ReleaseDC failed\n");
179
180 /* Try after resetting CS_OWNDC in the class */
181 ok(SetClassLongPtrA(hwnd, GCL_STYLE, 0) == CS_OWNDC, "class style wrong\n");
182 hdc2 = GetDCEx(hwnd, NULL, 0);
183 ok(hdc2 == hdc1, "Expected the same DC, got %p\n", hdc2);
184 ok(ReleaseDC(hwnd, hdc2) == TRUE, "ReleaseDC failed\n");
185
186 /* Try after setting CS_CLASSDC in the class */
187 ok(SetClassLongPtrA(hwnd, GCL_STYLE, CS_CLASSDC) == 0, "class style not set\n");
188 hdc2 = GetDCEx(hwnd, NULL, 0);
189 ok(hdc2 == hdc1, "Expected the same DC, got %p\n", hdc2);
190 ok(ReleaseDC(hwnd, hdc2) == TRUE, "ReleaseDC failed\n");
191
192 /* CS_OWNDC and CS_CLASSDC? Is that even legal? */
193 ok(SetClassLongPtrA(hwnd, GCL_STYLE, (CS_OWNDC | CS_CLASSDC)) == CS_CLASSDC, "class style not set\n");
194 hdc2 = GetDCEx(hwnd, NULL, 0);
195 ok(hdc2 == hdc1, "Expected the same DC, got %p\n", hdc2);
196 ok(ReleaseDC(hwnd, hdc2) == TRUE, "ReleaseDC failed\n");
197
198 SetClassLongPtrA(hwnd, GCL_STYLE, CS_OWNDC);
199
200 DestroyWindow(hwnd);
201 ok(UnregisterClass(pszClassName, GetModuleHandleA(0)) == TRUE,
202 "UnregisterClass failed");
203 }
204
205 static
206 void
207 Test_GetDCEx_CS_CLASSDC()
208 {
209 static const PSTR pszClassName = "TestClass_CS_CLASSDC";
210 ATOM atomClass;
211 HWND hwnd1, hwnd2;
212 HDC hdc1, hdc2;
213 //HRGN hrgn;
214
215 atomClass = RegisterClassHelper(pszClassName, CS_CLASSDC, WndProc);
216 ok(atomClass != 0, "Failed to register class\n");
217
218 hwnd1 = CreateWindowHelper(pszClassName, "Test Window1");
219 ok(hwnd1 != NULL, "Failed to create hwnd1\n");
220
221 /* Looks legit, but this is not the DC you are looking for!
222 In fact this is NOT the class dc, but an own DC, doh!
223 When the first Window is created, the DC for that Window is both it's own
224 AND the class DC. But we only get the class DC, when using DCX_USESTYLE */
225 hdc1 = GetDCEx(hwnd1, NULL, 0);
226 ok(hdc1 != NULL, "GetDCEx failed\n");
227 hdc2 = GetDCEx(hwnd1, NULL, 0);
228 ok(hdc2 == hdc1, "Expected the same DC, got %p\n", hdc2);
229 ok(ReleaseDC(hwnd1, hdc1) == TRUE, "ReleaseDC failed\n");
230 ok(ReleaseDC(hwnd1, hdc2) == TRUE, "ReleaseDC failed\n");
231
232 /* Now with DCX_USESTYLE */
233 hdc2 = GetDCEx(hwnd1, NULL, DCX_USESTYLE);
234 ok(hdc2 == hdc1, "Expected the same DC, got %p\n", hdc2);
235 ok(ReleaseDC(hwnd1, hdc2) == TRUE, "ReleaseDC failed\n");
236
237 hwnd2 = CreateWindowHelper(pszClassName, "Test Window2");
238 ok(hwnd2 != NULL, "Failed to create hwnd2\n");
239
240 /* Yeah, this doesn't work anymore. Once the */
241 hdc2 = GetDCEx(hwnd2, NULL, 0);
242 ok(hdc2 == NULL, "Expected failure\n");
243
244 /* Now with DCX_USESTYLE ... */
245 hdc2 = GetDCEx(hwnd2, NULL, DCX_USESTYLE);
246 ok(hdc2 == hdc1, "Expected the same DC, got %p\n", hdc2);
247 ok(ReleaseDC(hwnd2, hdc2) == TRUE, "ReleaseDC failed\n");
248
249 SendMessage(hwnd2, WM_USER, 0, 0);
250
251 DestroyWindow(hwnd1);
252 DestroyWindow(hwnd2);
253 ok(UnregisterClass(pszClassName, GetModuleHandleA(0)) == TRUE,
254 "UnregisterClass failed");
255 }
256
257 static
258 void
259 Test_GetDCEx_CS_Mixed()
260 {
261 static const PSTR pszClassName = "TestClass_CS_Mixed";
262 ATOM atomClass;
263 HWND hwnd1,hwnd2, hwnd3;
264 HDC hdc1, hdc2, hdc3;
265
266 /* Register a class with CS_OWNDC *and* CS_CLASSDC */
267 atomClass = RegisterClassHelper(pszClassName, CS_OWNDC | CS_CLASSDC, WndProc);
268 ok(atomClass != 0, "Failed to register class\n");
269
270 /* Create the first window, this should create a single own and class DC */
271 hwnd1 = CreateWindowHelper(pszClassName, "Test Window1");
272 ok(hwnd1 != NULL, "Failed to create hwnd1\n");
273
274 /* Verify that we have the right style */
275 ok(GetClassLongPtrA(hwnd1, GCL_STYLE) == (CS_OWNDC | CS_CLASSDC),
276 "class style not set\n");
277
278 /* This is now the class DC and the first windows own DC */
279 hdc1 = GetDCEx(hwnd1, NULL, 0);
280 ok(hdc1 != NULL, "GetDCEx failed\n");
281 ok(ReleaseDC(hwnd1, hdc1) == TRUE, "ReleaseDC failed\n");
282
283 /* This should get us the own/class DC again */
284 hdc2 = GetDCEx(hwnd1, NULL, 0);
285 ok(hdc2 == hdc1, "Expected the own/class DC, got %p\n", hdc2);
286 ok(ReleaseDC(hwnd1, hdc2) == TRUE, "ReleaseDC failed\n");
287
288 /* This should get us the class DC, but it's the same */
289 hdc2 = GetDCEx(hwnd1, NULL, DCX_USESTYLE);
290 ok(hdc2 == hdc1, "Expected the own/class DC, got %p\n", hdc2);
291 ok(ReleaseDC(hwnd1, hdc2) == TRUE, "ReleaseDC failed\n");
292
293 /* Create a second window */
294 hwnd2 = CreateWindowHelper(pszClassName, "Test Window1");
295 ok(hwnd1 != NULL, "Failed to create hwnd1\n");
296
297 /* This should get us the own DC of the new window */
298 hdc2 = GetDCEx(hwnd2, NULL, 0);
299 ok(hdc2 != NULL, "GetDCEx failed\n");
300 ok(hdc2 != hdc1, "Expected different DC\n");
301 ok(ReleaseDC(hwnd2, hdc2) == TRUE, "ReleaseDC failed\n");
302
303 /* This gets us the own DC again, CS_OWNDC has priority! */
304 hdc3 = GetDCEx(hwnd2, NULL, DCX_USESTYLE);
305 ok(hdc3 == hdc2, "Expected the own DC, got %p\n", hdc3);
306 ok(ReleaseDC(hwnd2, hdc3) == TRUE, "ReleaseDC failed\n");
307
308 /* Disable CS_OWNDC */
309 ok(SetClassLongPtrA(hwnd1, GCL_STYLE, CS_CLASSDC) == (CS_OWNDC | CS_CLASSDC), "unexpected style\n");
310 ok(GetClassLongPtrA(hwnd1, GCL_STYLE) == CS_CLASSDC, "class style not set\n");
311
312 /* Since the window already has an own DC, we get it again! */
313 hdc3 = GetDCEx(hwnd2, NULL, DCX_USESTYLE);
314 ok(hdc3 == hdc2, "Expected the own DC, got %p\n", hdc3);
315 ok(ReleaseDC(hwnd2, hdc3) == TRUE, "ReleaseDC failed\n");
316
317 /* Disable CS_CLASSDC, too */
318 ok(SetClassLongPtrA(hwnd1, GCL_STYLE, 0) == CS_CLASSDC, "unexpected style\n");
319 ok(GetClassLongPtrA(hwnd1, GCL_STYLE) == 0, "class style not set\n");
320
321 /* With DCX_USESTYLE we only get a cached DC */
322 hdc3 = GetDCEx(hwnd2, NULL, DCX_USESTYLE);
323 ok(hdc3 != NULL, "GetDCEx failed\n");
324 ok(hdc3 != hdc1, "Expected different DC, got class DC\n");
325 ok(hdc3 != hdc2, "Expected different DC, got own DC\n");
326 ok(ReleaseDC(hwnd2, hdc3) == TRUE, "ReleaseDC failed\n");
327
328 /* Without DCX_USESTYLE we get the own DC */
329 hdc3 = GetDCEx(hwnd2, NULL, 0);
330 ok(hdc3 != NULL, "GetDCEx failed\n");
331 ok(hdc3 != hdc1, "Expected different DC, got class DC\n");
332 ok(hdc3 == hdc2, "Expected the own DC, got %p\n", hdc3);
333 ok(ReleaseDC(hwnd2, hdc3) == TRUE, "ReleaseDC failed\n");
334
335 /* Set only CS_OWNDC */
336 ok(SetClassLongPtrA(hwnd1, GCL_STYLE, CS_OWNDC) == 0, "unexpected style\n");
337 ok(GetClassLongPtrA(hwnd1, GCL_STYLE) == CS_OWNDC, "class style not set\n");
338
339 hwnd3 = CreateWindowHelper(pszClassName, "Test Window1");
340 ok(hwnd3 != NULL, "Failed to create hwnd1\n");
341
342 /* This should get a new own DC */
343 hdc2 = GetDCEx(hwnd3, NULL, 0);
344 ok(hdc2 != hdc1, "Expected different DC\n");
345 ok(ReleaseDC(hwnd3, hdc2) == TRUE, "ReleaseDC failed\n");
346
347 /* Re-enable CS_CLASSDC */
348 ok(SetClassLongPtrA(hwnd1, GCL_STYLE, (CS_OWNDC | CS_CLASSDC)) == CS_OWNDC, "unexpected style\n");
349 ok(GetClassLongPtrA(hwnd1, GCL_STYLE) == (CS_OWNDC | CS_CLASSDC), "class style not set\n");
350
351 /* This should get us the own DC */
352 hdc3 = GetDCEx(hwnd3, NULL, 0);
353 ok(hdc3 == hdc2, "Expected the same DC, got %p\n", hdc3);
354 ok(ReleaseDC(hwnd3, hdc3) == TRUE, "ReleaseDC failed\n");
355
356 /* This should still get us the new own DC */
357 hdc3 = GetDCEx(hwnd3, NULL, DCX_USESTYLE);
358 ok(hdc3 == hdc2, "Expected the same DC, got %p\n", hdc3);
359 ok(ReleaseDC(hwnd3, hdc3) == TRUE, "ReleaseDC failed\n");
360
361 /* Disable CS_OWNDC */
362 ok(SetClassLongPtrA(hwnd1, GCL_STYLE, CS_CLASSDC) == (CS_OWNDC | CS_CLASSDC), "unexpected style\n");
363 ok(GetClassLongPtrA(hwnd1, GCL_STYLE) == CS_CLASSDC, "class style not set\n");
364
365 /* This should get us the own DC */
366 hdc3 = GetDCEx(hwnd3, NULL, 0);
367 ok(hdc3 == hdc2, "Expected the same DC, got %p\n", hdc3);
368 ok(ReleaseDC(hwnd3, hdc3) == TRUE, "ReleaseDC failed\n");
369
370 /* This should still get us the new own DC */
371 hdc3 = GetDCEx(hwnd3, NULL, DCX_USESTYLE);
372 ok(hdc3 == hdc2, "Expected the same DC, got %p\n", hdc3);
373 ok(ReleaseDC(hwnd3, hdc3) == TRUE, "ReleaseDC failed\n");
374
375 /* cleanup for a second run */
376 DestroyWindow(hwnd1);
377 DestroyWindow(hwnd2);
378 DestroyWindow(hwnd3);
379 ok(UnregisterClass(pszClassName, GetModuleHandleA(0)) == TRUE,
380 "UnregisterClass failed\n");
381
382 /* Create class again with CS_OWNDC */
383 atomClass = RegisterClassHelper(pszClassName, CS_OWNDC, WndProc);
384 ok(atomClass != 0, "Failed to register class\n");
385
386 hwnd1 = CreateWindowHelper(pszClassName, "Test Window1");
387 ok(hwnd1 != NULL, "Failed to create hwnd1\n");
388
389 /* This is the windows own DC, the class does not have a class DC yet */
390 hdc1 = GetDCEx(hwnd1, NULL, 0);
391 ok(hdc1 != NULL, "GetDCEx failed\n");
392 ok(ReleaseDC(hwnd1, hdc1) == TRUE, "ReleaseDC failed\n");
393
394 /* Enable only CS_CLASSDC */
395 ok(SetClassLongPtrA(hwnd1, GCL_STYLE, CS_CLASSDC) == CS_OWNDC, "unexpected style\n");
396 ok(GetClassLongPtrA(hwnd1, GCL_STYLE) == CS_CLASSDC, "class style not set\n");
397
398 /* Create a second window. Now we should create a class DC! */
399 hwnd2 = CreateWindowHelper(pszClassName, "Test Window2");
400 ok(hwnd2 != NULL, "Failed to create hwnd1\n");
401
402 /* We expect a new DCE (the class DCE) */
403 hdc2 = GetDCEx(hwnd2, NULL, DCX_USESTYLE);
404 ok(hdc2 != NULL, "GetDCEx failed\n");
405 ok(hdc2 != hdc1, "Expected different DCs\n");
406 ok(ReleaseDC(hwnd2, hdc2) == TRUE, "ReleaseDC failed\n");
407
408 /* cleanup */
409 DestroyWindow(hwnd1);
410 DestroyWindow(hwnd2);
411 ok(UnregisterClass(pszClassName, GetModuleHandleA(0)) == TRUE,
412 "UnregisterClass failed\n");
413 }
414
415 static
416 void
417 Test_GetDCEx_CS_SwitchedStyle()
418 {
419 static const PSTR pszClassName = "TestClass_CS_SwitchedStyle";
420 ATOM atomClass;
421 HWND hwnd1, hwnd2;
422
423 atomClass = RegisterClassHelper(pszClassName, CS_OWNDC, WndProc);
424 ok(atomClass != 0, "Failed to register class\n");
425
426 hwnd1 = CreateWindowHelper(pszClassName, "Test Window1");
427 ok(hwnd1 != NULL, "Failed to create hwnd1\n");
428
429 ok(SetClassLongPtrA(hwnd1, GCL_STYLE, CS_CLASSDC) == CS_OWNDC, "unexpected style\n");
430 ok(GetClassLongPtrA(hwnd1, GCL_STYLE) == CS_CLASSDC, "class style not set\n");
431
432 hwnd2 = CreateWindowHelper(pszClassName, "Test Window2");
433 ok(hwnd2 != NULL, "Failed to create hwnd2\n");
434
435 DestroyWindow(hwnd1);
436 DestroyWindow(hwnd2);
437 ok(UnregisterClass(pszClassName, GetModuleHandleA(0)) == TRUE,
438 "UnregisterClass failed\n");
439 }
440
441 START_TEST(GetDCEx)
442 {
443 Test_GetDCEx_Params();
444 Test_GetDCEx_Cached();
445 Test_GetDCEx_CS_OWNDC();
446 Test_GetDCEx_CS_CLASSDC();
447 Test_GetDCEx_CS_Mixed();
448 Test_GetDCEx_CS_SwitchedStyle();
449 }
450