2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for GetDCEx
5 * PROGRAMMERS: Timo Kreuzer
13 #define DCX_USESTYLE 0x00010000
15 void Test_GetDCEx_Params()
42 cls
.lpfnWndProc
= pfnWndProc
;
45 cls
.hInstance
= GetModuleHandleA(0);
47 cls
.hCursor
= LoadCursorA(0, IDC_ARROW
);
48 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
49 cls
.lpszMenuName
= NULL
;
50 cls
.lpszClassName
= pszClassName
;
52 return RegisterClassA(&cls
);
61 return CreateWindowA(pszClassName
,
78 static const PSTR pszClassName
= "TestClass_Cached";
84 atomClass
= RegisterClassHelper(pszClassName
, 0, WndProc
);
85 ok(atomClass
!= 0, "Failed to register class\n");
87 hwnd
= CreateWindowHelper(pszClassName
, "Test Window1");
88 ok(hwnd
!= NULL
, "Failed to create hwnd\n");
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");
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");
101 hdc1
= GetDCEx(hwnd
, hrgn
, DCX_INTERSECTRGN
);
102 ok(hdc1
== NULL
, "GetDCEx should fail\n");
104 hdc1
= GetDCEx(hwnd
, hrgn
, DCX_PARENTCLIP
);
105 ok(hdc1
!= NULL
, "GetDCEx failed\n");
106 ReleaseDC(hwnd
, hdc1
);
108 hdc1
= GetDCEx(hwnd
, hrgn
, DCX_WINDOW
| DCX_INTERSECTRGN
| DCX_PARENTCLIP
);
109 ok(hdc1
!= NULL
, "GetDCEx failed\n");
110 ReleaseDC(hwnd
, hdc1
);
112 hdc1
= GetDCEx(hwnd
, 0, DCX_CACHE
);
113 ok(hdc1
!= NULL
, "GetDCEx failed\n");
114 ReleaseDC(hwnd
, hdc1
);
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");
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
);
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
);
137 ok(CombineRgn(hrgn
, hrgn
, hrgn
, RGN_OR
) == SIMPLEREGION
, "region is not valid");
140 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
141 "UnregisterClass failed");
146 Test_GetDCEx_CS_OWNDC()
148 static const PSTR pszClassName
= "TestClass_CS_OWNDC";
154 atomClass
= RegisterClassHelper(pszClassName
, CS_OWNDC
, WndProc
);
155 ok(atomClass
!= 0, "Failed to register class\n");
157 hwnd
= CreateWindowHelper(pszClassName
, "Test Window1");
158 ok(hwnd
!= NULL
, "Failed to create hwnd\n");
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");
168 hdc2
= GetDCEx(hwnd
, NULL
, 0);
169 ok(hdc2
== hdc1
, "Expected the same DC\n");
170 ok(ReleaseDC(hwnd
, hdc2
) == TRUE
, "ReleaseDC failed\n");
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");
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");
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");
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");
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");
198 SetClassLongPtrA(hwnd
, GCL_STYLE
, CS_OWNDC
);
201 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
202 "UnregisterClass failed");
207 Test_GetDCEx_CS_CLASSDC()
209 static const PSTR pszClassName
= "TestClass_CS_CLASSDC";
215 atomClass
= RegisterClassHelper(pszClassName
, CS_CLASSDC
, WndProc
);
216 ok(atomClass
!= 0, "Failed to register class\n");
218 hwnd1
= CreateWindowHelper(pszClassName
, "Test Window1");
219 ok(hwnd1
!= NULL
, "Failed to create hwnd1\n");
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");
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");
237 hwnd2
= CreateWindowHelper(pszClassName
, "Test Window2");
238 ok(hwnd2
!= NULL
, "Failed to create hwnd2\n");
240 /* Yeah, this doesn't work anymore. Once the */
241 hdc2
= GetDCEx(hwnd2
, NULL
, 0);
242 ok(hdc2
== NULL
, "Expected failure\n");
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");
249 SendMessage(hwnd2
, WM_USER
, 0, 0);
251 DestroyWindow(hwnd1
);
252 DestroyWindow(hwnd2
);
253 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
254 "UnregisterClass failed");
259 Test_GetDCEx_CS_Mixed()
261 static const PSTR pszClassName
= "TestClass_CS_Mixed";
263 HWND hwnd1
,hwnd2
, hwnd3
;
264 HDC hdc1
, hdc2
, hdc3
;
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");
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");
274 /* Verify that we have the right style */
275 ok(GetClassLongPtrA(hwnd1
, GCL_STYLE
) == (CS_OWNDC
| CS_CLASSDC
),
276 "class style not set\n");
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");
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");
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");
293 /* Create a second window */
294 hwnd2
= CreateWindowHelper(pszClassName
, "Test Window1");
295 ok(hwnd1
!= NULL
, "Failed to create hwnd1\n");
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");
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");
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");
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");
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");
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");
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");
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");
339 hwnd3
= CreateWindowHelper(pszClassName
, "Test Window1");
340 ok(hwnd3
!= NULL
, "Failed to create hwnd1\n");
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");
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");
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");
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");
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");
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");
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");
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");
382 /* Create class again with CS_OWNDC */
383 atomClass
= RegisterClassHelper(pszClassName
, CS_OWNDC
, WndProc
);
384 ok(atomClass
!= 0, "Failed to register class\n");
386 hwnd1
= CreateWindowHelper(pszClassName
, "Test Window1");
387 ok(hwnd1
!= NULL
, "Failed to create hwnd1\n");
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");
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");
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");
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");
409 DestroyWindow(hwnd1
);
410 DestroyWindow(hwnd2
);
411 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
412 "UnregisterClass failed\n");
417 Test_GetDCEx_CS_SwitchedStyle()
419 static const PSTR pszClassName
= "TestClass_CS_SwitchedStyle";
423 atomClass
= RegisterClassHelper(pszClassName
, CS_OWNDC
, WndProc
);
424 ok(atomClass
!= 0, "Failed to register class\n");
426 hwnd1
= CreateWindowHelper(pszClassName
, "Test Window1");
427 ok(hwnd1
!= NULL
, "Failed to create hwnd1\n");
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");
432 hwnd2
= CreateWindowHelper(pszClassName
, "Test Window2");
433 ok(hwnd2
!= NULL
, "Failed to create hwnd2\n");
435 DestroyWindow(hwnd1
);
436 DestroyWindow(hwnd2
);
437 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
438 "UnregisterClass failed\n");
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();