2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for GetDCEx
5 * PROGRAMMERS: Timo Kreuzer
12 #define DCX_USESTYLE 0x00010000
14 void Test_GetDCEx_Params()
41 cls
.lpfnWndProc
= pfnWndProc
;
44 cls
.hInstance
= GetModuleHandleA(0);
46 cls
.hCursor
= LoadCursorA(0, IDC_ARROW
);
47 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
48 cls
.lpszMenuName
= NULL
;
49 cls
.lpszClassName
= pszClassName
;
51 return RegisterClassA(&cls
);
60 return CreateWindowA(pszClassName
,
77 static const PSTR pszClassName
= "TestClass_Cached";
83 atomClass
= RegisterClassHelper(pszClassName
, 0, WndProc
);
84 ok(atomClass
!= 0, "Failed to register class\n");
86 hwnd
= CreateWindowHelper(pszClassName
, "Test Window1");
87 ok(hwnd
!= NULL
, "Failed to create hwnd\n");
89 hdc1
= GetDCEx(hwnd
, 0, 0);
90 ok(hdc1
== NULL
, "GetDCEx should fail\n");
91 hrgn
= CreateRectRgn(0, 0, 100, 100);
92 hdc1
= GetDCEx(hwnd
, hrgn
, 0);
93 ok(hdc1
== NULL
, "GetDCEx should fail\n");
95 hdc1
= GetDCEx(hwnd
, 0, DCX_WINDOW
);
96 ok(hdc1
== NULL
, "GetDCEx should fail\n");
97 hdc1
= GetDCEx(hwnd
, hrgn
, DCX_WINDOW
);
98 ok(hdc1
== NULL
, "GetDCEx should fail\n");
100 hdc1
= GetDCEx(hwnd
, hrgn
, DCX_INTERSECTRGN
);
101 ok(hdc1
== NULL
, "GetDCEx should fail\n");
103 hdc1
= GetDCEx(hwnd
, hrgn
, DCX_PARENTCLIP
);
104 ok(hdc1
!= NULL
, "GetDCEx failed\n");
105 ReleaseDC(hwnd
, hdc1
);
107 hdc1
= GetDCEx(hwnd
, hrgn
, DCX_WINDOW
| DCX_INTERSECTRGN
| DCX_PARENTCLIP
);
108 ok(hdc1
!= NULL
, "GetDCEx failed\n");
109 ReleaseDC(hwnd
, hdc1
);
111 hdc1
= GetDCEx(hwnd
, 0, DCX_CACHE
);
112 ok(hdc1
!= NULL
, "GetDCEx failed\n");
113 ReleaseDC(hwnd
, hdc1
);
115 hrgn
= CreateRectRgn(0, 0, 100, 100);
116 hdc2
= GetDCEx(hwnd
, hrgn
, DCX_CACHE
);
117 ok(hdc2
!= NULL
, "GetDCEx failed\n");
118 ReleaseDC(hwnd
, hdc2
);
119 ok(hdc2
== hdc1
, "Expected the same DC\n");
121 hdc1
= GetDCEx(hwnd
, 0, DCX_CACHE
);
122 hdc2
= GetDCEx(hwnd
, hrgn
, DCX_CACHE
);
123 ok(hdc1
!= NULL
, "GetDCEx failed\n");
124 ok(hdc2
!= hdc1
, "Expected a different DC\n");
125 ReleaseDC(hwnd
, hdc1
);
126 ReleaseDC(hwnd
, hdc2
);
128 hdc1
= GetDCEx(NULL
, NULL
, 0);
129 ok(hdc1
!= NULL
, "GetDCEx failed\n");
130 hdc2
= GetDCEx(NULL
, NULL
, 0);
131 ok(hdc2
!= NULL
, "GetDCEx failed\n");
132 ok(hdc2
!= hdc1
, "Expected a different DC\n");
133 ReleaseDC(hwnd
, hdc1
);
134 ReleaseDC(hwnd
, hdc2
);
136 ok(CombineRgn(hrgn
, hrgn
, hrgn
, RGN_OR
) == SIMPLEREGION
, "region is not valid");
139 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
140 "UnregisterClass failed");
145 Test_GetDCEx_CS_OWNDC()
147 static const PSTR pszClassName
= "TestClass_CS_OWNDC";
153 atomClass
= RegisterClassHelper(pszClassName
, CS_OWNDC
, WndProc
);
154 ok(atomClass
!= 0, "Failed to register class\n");
156 hwnd
= CreateWindowHelper(pszClassName
, "Test Window1");
157 ok(hwnd
!= NULL
, "Failed to create hwnd\n");
159 hdc1
= GetDCEx(hwnd
, NULL
, 0);
160 ok(hdc1
!= NULL
, "GetDCEx failed\n");
161 hdc2
= GetDCEx(hwnd
, NULL
, 0);
162 ok(hdc2
!= NULL
, "GetDCEx failed\n");
163 ok(hdc2
== hdc1
, "Expected the same DC\n");
164 ok(ReleaseDC(hwnd
, hdc1
) == TRUE
, "ReleaseDC failed\n");
165 ok(ReleaseDC(hwnd
, hdc2
) == TRUE
, "ReleaseDC failed\n");
167 hdc2
= GetDCEx(hwnd
, NULL
, 0);
168 ok(hdc2
== hdc1
, "Expected the same DC\n");
169 ok(ReleaseDC(hwnd
, hdc2
) == TRUE
, "ReleaseDC failed\n");
171 hdc2
= GetDCEx(hwnd
, NULL
, DCX_CACHE
);
172 ok(hdc2
!= hdc1
, "Expected a different DC\n");
173 ok(ReleaseDC(hwnd
, hdc2
) == TRUE
, "ReleaseDC failed\n");
175 hdc2
= GetDCEx(hwnd
, NULL
, DCX_WINDOW
);
176 ok(hdc2
== hdc1
, "Expected the same DC\n");
177 ok(ReleaseDC(hwnd
, hdc2
) == TRUE
, "ReleaseDC failed\n");
179 /* Try after resetting CS_OWNDC in the class */
180 ok(SetClassLongPtrA(hwnd
, GCL_STYLE
, 0) == CS_OWNDC
, "class style wrong\n");
181 hdc2
= GetDCEx(hwnd
, NULL
, 0);
182 ok(hdc2
== hdc1
, "Expected the same DC, got %p\n", hdc2
);
183 ok(ReleaseDC(hwnd
, hdc2
) == TRUE
, "ReleaseDC failed\n");
185 /* Try after setting CS_CLASSDC in the class */
186 ok(SetClassLongPtrA(hwnd
, GCL_STYLE
, CS_CLASSDC
) == 0, "class style not set\n");
187 hdc2
= GetDCEx(hwnd
, NULL
, 0);
188 ok(hdc2
== hdc1
, "Expected the same DC, got %p\n", hdc2
);
189 ok(ReleaseDC(hwnd
, hdc2
) == TRUE
, "ReleaseDC failed\n");
191 /* CS_OWNDC and CS_CLASSDC? Is that even legal? */
192 ok(SetClassLongPtrA(hwnd
, GCL_STYLE
, (CS_OWNDC
| CS_CLASSDC
)) == CS_CLASSDC
, "class style not set\n");
193 hdc2
= GetDCEx(hwnd
, NULL
, 0);
194 ok(hdc2
== hdc1
, "Expected the same DC, got %p\n", hdc2
);
195 ok(ReleaseDC(hwnd
, hdc2
) == TRUE
, "ReleaseDC failed\n");
197 SetClassLongPtrA(hwnd
, GCL_STYLE
, CS_OWNDC
);
200 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
201 "UnregisterClass failed");
206 Test_GetDCEx_CS_CLASSDC()
208 static const PSTR pszClassName
= "TestClass_CS_CLASSDC";
214 atomClass
= RegisterClassHelper(pszClassName
, CS_CLASSDC
, WndProc
);
215 ok(atomClass
!= 0, "Failed to register class\n");
217 hwnd1
= CreateWindowHelper(pszClassName
, "Test Window1");
218 ok(hwnd1
!= NULL
, "Failed to create hwnd1\n");
220 /* Looks legit, but this is not the DC you are looking for!
221 In fact this is NOT the class dc, but an own DC, doh!
222 When the first Window is created, the DC for that Window is both it's own
223 AND the class DC. But we only get the class DC, when using DCX_USESTYLE */
224 hdc1
= GetDCEx(hwnd1
, NULL
, 0);
225 ok(hdc1
!= NULL
, "GetDCEx failed\n");
226 hdc2
= GetDCEx(hwnd1
, NULL
, 0);
227 ok(hdc2
== hdc1
, "Expected the same DC, got %p\n", hdc2
);
228 ok(ReleaseDC(hwnd1
, hdc1
) == TRUE
, "ReleaseDC failed\n");
229 ok(ReleaseDC(hwnd1
, hdc2
) == TRUE
, "ReleaseDC failed\n");
231 /* Now with DCX_USESTYLE */
232 hdc2
= GetDCEx(hwnd1
, NULL
, DCX_USESTYLE
);
233 ok(hdc2
== hdc1
, "Expected the same DC, got %p\n", hdc2
);
234 ok(ReleaseDC(hwnd1
, hdc2
) == TRUE
, "ReleaseDC failed\n");
236 hwnd2
= CreateWindowHelper(pszClassName
, "Test Window2");
237 ok(hwnd2
!= NULL
, "Failed to create hwnd2\n");
239 /* Yeah, this doesn't work anymore. Once the */
240 hdc2
= GetDCEx(hwnd2
, NULL
, 0);
241 ok(hdc2
== NULL
, "Expected failure\n");
243 /* Now with DCX_USESTYLE ... */
244 hdc2
= GetDCEx(hwnd2
, NULL
, DCX_USESTYLE
);
245 ok(hdc2
== hdc1
, "Expected the same DC, got %p\n", hdc2
);
246 ok(ReleaseDC(hwnd2
, hdc2
) == TRUE
, "ReleaseDC failed\n");
248 SendMessage(hwnd2
, WM_USER
, 0, 0);
250 DestroyWindow(hwnd1
);
251 DestroyWindow(hwnd2
);
252 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
253 "UnregisterClass failed");
258 Test_GetDCEx_CS_Mixed()
260 static const PSTR pszClassName
= "TestClass_CS_Mixed";
262 HWND hwnd1
,hwnd2
, hwnd3
;
263 HDC hdc1
, hdc2
, hdc3
;
265 /* Register a class with CS_OWNDC *and* CS_CLASSDC */
266 atomClass
= RegisterClassHelper(pszClassName
, CS_OWNDC
| CS_CLASSDC
, WndProc
);
267 ok(atomClass
!= 0, "Failed to register class\n");
269 /* Create the first window, this should create a single own and class DC */
270 hwnd1
= CreateWindowHelper(pszClassName
, "Test Window1");
271 ok(hwnd1
!= NULL
, "Failed to create hwnd1\n");
273 /* Verify that we have the right style */
274 ok(GetClassLongPtrA(hwnd1
, GCL_STYLE
) == (CS_OWNDC
| CS_CLASSDC
),
275 "class style not set\n");
277 /* This is now the class DC and the first windows own DC */
278 hdc1
= GetDCEx(hwnd1
, NULL
, 0);
279 ok(hdc1
!= NULL
, "GetDCEx failed\n");
280 ok(ReleaseDC(hwnd1
, hdc1
) == TRUE
, "ReleaseDC failed\n");
282 /* This should get us the own/class DC again */
283 hdc2
= GetDCEx(hwnd1
, NULL
, 0);
284 ok(hdc2
== hdc1
, "Expected the own/class DC, got %p\n", hdc2
);
285 ok(ReleaseDC(hwnd1
, hdc2
) == TRUE
, "ReleaseDC failed\n");
287 /* This should get us the class DC, but it's the same */
288 hdc2
= GetDCEx(hwnd1
, NULL
, DCX_USESTYLE
);
289 ok(hdc2
== hdc1
, "Expected the own/class DC, got %p\n", hdc2
);
290 ok(ReleaseDC(hwnd1
, hdc2
) == TRUE
, "ReleaseDC failed\n");
292 /* Create a second window */
293 hwnd2
= CreateWindowHelper(pszClassName
, "Test Window1");
294 ok(hwnd1
!= NULL
, "Failed to create hwnd1\n");
296 /* This should get us the own DC of the new window */
297 hdc2
= GetDCEx(hwnd2
, NULL
, 0);
298 ok(hdc2
!= NULL
, "GetDCEx failed\n");
299 ok(hdc2
!= hdc1
, "Expected different DC\n");
300 ok(ReleaseDC(hwnd2
, hdc2
) == TRUE
, "ReleaseDC failed\n");
302 /* This gets us the own DC again, CS_OWNDC has priority! */
303 hdc3
= GetDCEx(hwnd2
, NULL
, DCX_USESTYLE
);
304 ok(hdc3
== hdc2
, "Expected the own DC, got %p\n", hdc3
);
305 ok(ReleaseDC(hwnd2
, hdc3
) == TRUE
, "ReleaseDC failed\n");
307 /* Disable CS_OWNDC */
308 ok(SetClassLongPtrA(hwnd1
, GCL_STYLE
, CS_CLASSDC
) == (CS_OWNDC
| CS_CLASSDC
), "unexpected style\n");
309 ok(GetClassLongPtrA(hwnd1
, GCL_STYLE
) == CS_CLASSDC
, "class style not set\n");
311 /* Since the window already has an own DC, we get it again! */
312 hdc3
= GetDCEx(hwnd2
, NULL
, DCX_USESTYLE
);
313 ok(hdc3
== hdc2
, "Expected the own DC, got %p\n", hdc3
);
314 ok(ReleaseDC(hwnd2
, hdc3
) == TRUE
, "ReleaseDC failed\n");
316 /* Disable CS_CLASSDC, too */
317 ok(SetClassLongPtrA(hwnd1
, GCL_STYLE
, 0) == CS_CLASSDC
, "unexpected style\n");
318 ok(GetClassLongPtrA(hwnd1
, GCL_STYLE
) == 0, "class style not set\n");
320 /* With DCX_USESTYLE we only get a cached DC */
321 hdc3
= GetDCEx(hwnd2
, NULL
, DCX_USESTYLE
);
322 ok(hdc3
!= NULL
, "GetDCEx failed\n");
323 ok(hdc3
!= hdc1
, "Expected different DC, got class DC\n");
324 ok(hdc3
!= hdc2
, "Expected different DC, got own DC\n");
325 ok(ReleaseDC(hwnd2
, hdc3
) == TRUE
, "ReleaseDC failed\n");
327 /* Without DCX_USESTYLE we get the own DC */
328 hdc3
= GetDCEx(hwnd2
, NULL
, 0);
329 ok(hdc3
!= NULL
, "GetDCEx failed\n");
330 ok(hdc3
!= hdc1
, "Expected different DC, got class DC\n");
331 ok(hdc3
== hdc2
, "Expected the own DC, got %p\n", hdc3
);
332 ok(ReleaseDC(hwnd2
, hdc3
) == TRUE
, "ReleaseDC failed\n");
334 /* Set only CS_OWNDC */
335 ok(SetClassLongPtrA(hwnd1
, GCL_STYLE
, CS_OWNDC
) == 0, "unexpected style\n");
336 ok(GetClassLongPtrA(hwnd1
, GCL_STYLE
) == CS_OWNDC
, "class style not set\n");
338 hwnd3
= CreateWindowHelper(pszClassName
, "Test Window1");
339 ok(hwnd3
!= NULL
, "Failed to create hwnd1\n");
341 /* This should get a new own DC */
342 hdc2
= GetDCEx(hwnd3
, NULL
, 0);
343 ok(hdc2
!= hdc1
, "Expected different DC\n");
344 ok(ReleaseDC(hwnd3
, hdc2
) == TRUE
, "ReleaseDC failed\n");
346 /* Re-enable CS_CLASSDC */
347 ok(SetClassLongPtrA(hwnd1
, GCL_STYLE
, (CS_OWNDC
| CS_CLASSDC
)) == CS_OWNDC
, "unexpected style\n");
348 ok(GetClassLongPtrA(hwnd1
, GCL_STYLE
) == (CS_OWNDC
| CS_CLASSDC
), "class style not set\n");
350 /* This should get us the own DC */
351 hdc3
= GetDCEx(hwnd3
, NULL
, 0);
352 ok(hdc3
== hdc2
, "Expected the same DC, got %p\n", hdc3
);
353 ok(ReleaseDC(hwnd3
, hdc3
) == TRUE
, "ReleaseDC failed\n");
355 /* This should still get us the new own DC */
356 hdc3
= GetDCEx(hwnd3
, NULL
, DCX_USESTYLE
);
357 ok(hdc3
== hdc2
, "Expected the same DC, got %p\n", hdc3
);
358 ok(ReleaseDC(hwnd3
, hdc3
) == TRUE
, "ReleaseDC failed\n");
360 /* Disable CS_OWNDC */
361 ok(SetClassLongPtrA(hwnd1
, GCL_STYLE
, CS_CLASSDC
) == (CS_OWNDC
| CS_CLASSDC
), "unexpected style\n");
362 ok(GetClassLongPtrA(hwnd1
, GCL_STYLE
) == CS_CLASSDC
, "class style not set\n");
364 /* This should get us the own DC */
365 hdc3
= GetDCEx(hwnd3
, NULL
, 0);
366 ok(hdc3
== hdc2
, "Expected the same DC, got %p\n", hdc3
);
367 ok(ReleaseDC(hwnd3
, hdc3
) == TRUE
, "ReleaseDC failed\n");
369 /* This should still get us the new own DC */
370 hdc3
= GetDCEx(hwnd3
, NULL
, DCX_USESTYLE
);
371 ok(hdc3
== hdc2
, "Expected the same DC, got %p\n", hdc3
);
372 ok(ReleaseDC(hwnd3
, hdc3
) == TRUE
, "ReleaseDC failed\n");
374 /* cleanup for a second run */
375 DestroyWindow(hwnd1
);
376 DestroyWindow(hwnd2
);
377 DestroyWindow(hwnd3
);
378 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
379 "UnregisterClass failed\n");
381 /* Create class again with CS_OWNDC */
382 atomClass
= RegisterClassHelper(pszClassName
, CS_OWNDC
, WndProc
);
383 ok(atomClass
!= 0, "Failed to register class\n");
385 hwnd1
= CreateWindowHelper(pszClassName
, "Test Window1");
386 ok(hwnd1
!= NULL
, "Failed to create hwnd1\n");
388 /* This is the windows own DC, the class does not have a class DC yet */
389 hdc1
= GetDCEx(hwnd1
, NULL
, 0);
390 ok(hdc1
!= NULL
, "GetDCEx failed\n");
391 ok(ReleaseDC(hwnd1
, hdc1
) == TRUE
, "ReleaseDC failed\n");
393 /* Enable only CS_CLASSDC */
394 ok(SetClassLongPtrA(hwnd1
, GCL_STYLE
, CS_CLASSDC
) == CS_OWNDC
, "unexpected style\n");
395 ok(GetClassLongPtrA(hwnd1
, GCL_STYLE
) == CS_CLASSDC
, "class style not set\n");
397 /* Create a second window. Now we should create a class DC! */
398 hwnd2
= CreateWindowHelper(pszClassName
, "Test Window2");
399 ok(hwnd2
!= NULL
, "Failed to create hwnd1\n");
401 /* We expect a new DCE (the class DCE) */
402 hdc2
= GetDCEx(hwnd2
, NULL
, DCX_USESTYLE
);
403 ok(hdc2
!= NULL
, "GetDCEx failed\n");
404 ok(hdc2
!= hdc1
, "Expected different DCs\n");
405 ok(ReleaseDC(hwnd2
, hdc2
) == TRUE
, "ReleaseDC failed\n");
408 DestroyWindow(hwnd1
);
409 DestroyWindow(hwnd2
);
410 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
411 "UnregisterClass failed\n");
416 Test_GetDCEx_CS_SwitchedStyle()
418 static const PSTR pszClassName
= "TestClass_CS_SwitchedStyle";
422 atomClass
= RegisterClassHelper(pszClassName
, CS_OWNDC
, WndProc
);
423 ok(atomClass
!= 0, "Failed to register class\n");
425 hwnd1
= CreateWindowHelper(pszClassName
, "Test Window1");
426 ok(hwnd1
!= NULL
, "Failed to create hwnd1\n");
428 ok(SetClassLongPtrA(hwnd1
, GCL_STYLE
, CS_CLASSDC
) == CS_OWNDC
, "unexpected style\n");
429 ok(GetClassLongPtrA(hwnd1
, GCL_STYLE
) == CS_CLASSDC
, "class style not set\n");
431 hwnd2
= CreateWindowHelper(pszClassName
, "Test Window2");
432 ok(hwnd2
!= NULL
, "Failed to create hwnd2\n");
434 DestroyWindow(hwnd1
);
435 DestroyWindow(hwnd2
);
436 ok(UnregisterClass(pszClassName
, GetModuleHandleA(0)) == TRUE
,
437 "UnregisterClass failed\n");
442 Test_GetDCEx_Params();
443 Test_GetDCEx_Cached();
444 Test_GetDCEx_CS_OWNDC();
445 Test_GetDCEx_CS_CLASSDC();
446 Test_GetDCEx_CS_Mixed();
447 Test_GetDCEx_CS_SwitchedStyle();