mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / user32 / tests / dce.c
blob861150f9a88d43e1e3c622494226bd41489c9814
1 /*
2 * Unit tests for DCE support
4 * Copyright 2005 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdio.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
30 #include "wine/test.h"
32 #ifndef DCX_USESTYLE
33 #define DCX_USESTYLE 0x00010000
34 #endif
36 static HWND hwnd_cache, hwnd_owndc, hwnd_classdc, hwnd_classdc2, hwnd_parent, hwnd_parentdc;
38 /* test behavior of DC attributes with various GetDC/ReleaseDC combinations */
39 static void test_dc_attributes(void)
41 HDC hdc, old_hdc;
42 HDC hdcs[20];
43 INT i, rop, def_rop, caps;
44 BOOL found_dc;
46 /* test cache DC */
48 hdc = GetDC( hwnd_cache );
49 def_rop = GetROP2( hdc );
51 SetROP2( hdc, R2_WHITE );
52 rop = GetROP2( hdc );
53 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
55 ok( WindowFromDC( hdc ) == hwnd_cache, "wrong window\n" );
56 ReleaseDC( hwnd_cache, hdc );
57 ok( WindowFromDC( hdc ) != hwnd_cache, "wrong window\n" );
58 hdc = GetDC( hwnd_cache );
59 rop = GetROP2( hdc );
60 ok( rop == def_rop, "wrong ROP2 %d after release\n", rop );
61 SetROP2( hdc, R2_WHITE );
62 ok( WindowFromDC( hdc ) == hwnd_cache, "wrong window\n" );
63 ReleaseDC( hwnd_cache, hdc );
64 old_hdc = hdc;
66 found_dc = FALSE;
67 for (i = 0; i < 20; i++)
69 hdc = hdcs[i] = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
70 if (!hdc) break;
71 rop = GetROP2( hdc );
72 ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
73 if (hdc == old_hdc)
75 found_dc = TRUE;
76 SetROP2( hdc, R2_WHITE );
79 if (!found_dc)
81 trace( "hdc %p not found in cache using %p\n", old_hdc, hdcs[0] );
82 old_hdc = hdcs[0];
83 SetROP2( old_hdc, R2_WHITE );
85 while (i > 0) ReleaseDC( hwnd_cache, hdcs[--i] );
87 for (i = 0; i < 20; i++)
89 hdc = hdcs[i] = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
90 if (!hdc) break;
91 rop = GetROP2( hdc );
92 if (hdc == old_hdc)
93 ok( rop == R2_WHITE || broken( rop == def_rop), /* win9x doesn't support DCX_NORESETATTRS */
94 "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
95 else
96 ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
98 while (i > 0) ReleaseDC( hwnd_cache, hdcs[--i] );
100 for (i = 0; i < 20; i++)
102 hdc = hdcs[i] = GetDCEx( hwnd_cache, 0, DCX_USESTYLE );
103 if (!hdc) break;
104 rop = GetROP2( hdc );
105 if (hdc == old_hdc)
107 ok( rop == R2_WHITE || broken( rop == def_rop),
108 "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
109 SetROP2( old_hdc, def_rop );
111 else
112 ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
114 while (i > 0) ReleaseDC( hwnd_cache, hdcs[--i] );
116 /* Released cache DCs are 'disabled' */
117 rop = SetROP2( old_hdc, R2_BLACK );
118 ok( rop == 0, "got %d\n", rop );
119 rop = GetROP2( old_hdc );
120 ok( rop == 0, "got %d\n", rop );
121 caps = GetDeviceCaps( old_hdc, HORZRES );
122 ok( caps == 0, "got %d\n", caps );
123 caps = GetDeviceCaps( old_hdc, VERTRES );
124 ok( caps == 0, "got %d\n", caps );
125 caps = GetDeviceCaps( old_hdc, NUMCOLORS );
126 ok( caps == 0, "got %d\n", caps );
127 ok( WindowFromDC( old_hdc ) != hwnd_cache, "wrong window\n" );
129 hdc = GetDC(0);
130 caps = GetDeviceCaps( hdc, HORZRES );
131 ok( caps != 0, "got %d\n", caps );
132 caps = GetDeviceCaps( hdc, VERTRES );
133 ok( caps != 0, "got %d\n", caps );
134 caps = GetDeviceCaps( hdc, NUMCOLORS );
135 ok( caps != 0, "got %d\n", caps );
136 ReleaseDC( 0, hdc );
137 caps = GetDeviceCaps( hdc, HORZRES );
138 ok( caps == 0, "got %d\n", caps );
139 caps = GetDeviceCaps( hdc, VERTRES );
140 ok( caps == 0, "got %d\n", caps );
141 caps = GetDeviceCaps( hdc, NUMCOLORS );
142 ok( caps == 0, "got %d\n", caps );
144 /* test own DC */
146 hdc = GetDC( hwnd_owndc );
147 SetROP2( hdc, R2_WHITE );
148 rop = GetROP2( hdc );
149 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
151 old_hdc = hdc;
152 ok( WindowFromDC( hdc ) == hwnd_owndc, "wrong window\n" );
153 ReleaseDC( hwnd_owndc, hdc );
154 ok( WindowFromDC( hdc ) == hwnd_owndc, "wrong window\n" );
155 hdc = GetDC( hwnd_owndc );
156 ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
157 rop = GetROP2( hdc );
158 ok( rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
159 ok( WindowFromDC( hdc ) == hwnd_owndc, "wrong window\n" );
160 ReleaseDC( hwnd_owndc, hdc );
161 rop = GetROP2( hdc );
162 ok( rop == R2_WHITE, "wrong ROP2 %d after second release\n", rop );
164 /* test class DC */
166 hdc = GetDC( hwnd_classdc );
167 SetROP2( hdc, R2_WHITE );
168 rop = GetROP2( hdc );
169 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
171 old_hdc = hdc;
172 ok( WindowFromDC( hdc ) == hwnd_classdc, "wrong window\n" );
173 ReleaseDC( hwnd_classdc, hdc );
174 ok( WindowFromDC( hdc ) == hwnd_classdc, "wrong window\n" );
175 hdc = GetDC( hwnd_classdc );
176 ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
177 rop = GetROP2( hdc );
178 ok( rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
179 ok( WindowFromDC( hdc ) == hwnd_classdc, "wrong window\n" );
180 ReleaseDC( hwnd_classdc, hdc );
181 rop = GetROP2( hdc );
182 ok( rop == R2_WHITE, "wrong ROP2 %d after second release\n", rop );
184 /* test class DC with 2 windows */
186 old_hdc = GetDC( hwnd_classdc );
187 SetROP2( old_hdc, R2_BLACK );
188 ok( WindowFromDC( old_hdc ) == hwnd_classdc, "wrong window\n" );
189 hdc = GetDC( hwnd_classdc2 );
190 ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
191 rop = GetROP2( hdc );
192 ok( rop == R2_BLACK, "wrong ROP2 %d for other window\n", rop );
193 ok( WindowFromDC( hdc ) == hwnd_classdc2, "wrong window\n" );
194 ReleaseDC( hwnd_classdc, old_hdc );
195 ReleaseDC( hwnd_classdc, hdc );
196 ok( WindowFromDC( hdc ) == hwnd_classdc2, "wrong window\n" );
197 rop = GetROP2( hdc );
198 ok( rop == R2_BLACK, "wrong ROP2 %d after release\n", rop );
202 /* test behavior with various invalid parameters */
203 static void test_parameters(void)
205 HDC hdc;
207 hdc = GetDC( hwnd_cache );
208 ok( ReleaseDC( hwnd_owndc, hdc ), "ReleaseDC with wrong window should succeed\n" );
210 hdc = GetDC( hwnd_cache );
211 ok( !ReleaseDC( hwnd_cache, 0 ), "ReleaseDC with wrong HDC should fail\n" );
212 ok( ReleaseDC( hwnd_cache, hdc ), "correct ReleaseDC should succeed\n" );
213 ok( !ReleaseDC( hwnd_cache, hdc ), "second ReleaseDC should fail\n" );
215 hdc = GetDC( hwnd_owndc );
216 ok( ReleaseDC( hwnd_cache, hdc ), "ReleaseDC with wrong window should succeed\n" );
217 hdc = GetDC( hwnd_owndc );
218 ok( ReleaseDC( hwnd_owndc, hdc ), "correct ReleaseDC should succeed\n" );
219 ok( ReleaseDC( hwnd_owndc, hdc ), "second ReleaseDC should succeed\n" );
221 hdc = GetDC( hwnd_classdc );
222 ok( ReleaseDC( hwnd_cache, hdc ), "ReleaseDC with wrong window should succeed\n" );
223 hdc = GetDC( hwnd_classdc );
224 ok( ReleaseDC( hwnd_classdc, hdc ), "correct ReleaseDC should succeed\n" );
225 ok( ReleaseDC( hwnd_classdc, hdc ), "second ReleaseDC should succeed\n" );
229 static void test_dc_visrgn(void)
231 HDC old_hdc, hdc;
232 HRGN hrgn, hrgn2;
233 RECT rect, parent_rect;
235 /* cache DC */
237 SetRect( &rect, 10, 10, 20, 20 );
238 MapWindowPoints( hwnd_cache, 0, (POINT *)&rect, 2 );
239 hrgn = CreateRectRgnIndirect( &rect );
240 hdc = GetDCEx( hwnd_cache, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
241 SetRectEmpty( &rect );
242 GetClipBox( hdc, &rect );
243 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
244 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
245 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
246 ReleaseDC( hwnd_cache, hdc );
247 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
249 /* cache DC with NORESETATTRS */
251 SetRect( &rect, 10, 10, 20, 20 );
252 MapWindowPoints( hwnd_cache, 0, (POINT *)&rect, 2 );
253 hrgn = CreateRectRgnIndirect( &rect );
254 hdc = GetDCEx( hwnd_cache, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE | DCX_NORESETATTRS );
255 SetRectEmpty( &rect );
256 GetClipBox( hdc, &rect );
257 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
258 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
259 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
260 ReleaseDC( hwnd_cache, hdc );
261 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
262 hdc = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
263 SetRectEmpty( &rect );
264 GetClipBox( hdc, &rect );
265 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
266 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect ));
267 ReleaseDC( hwnd_cache, hdc );
269 /* window DC */
271 SetRect( &rect, 10, 10, 20, 20 );
272 MapWindowPoints( hwnd_owndc, 0, (POINT *)&rect, 2 );
273 hrgn = CreateRectRgnIndirect( &rect );
274 hdc = GetDCEx( hwnd_owndc, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
275 SetRectEmpty( &rect );
276 GetClipBox( hdc, &rect );
277 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
278 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
279 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
280 ReleaseDC( hwnd_owndc, hdc );
281 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
282 SetRectEmpty( &rect );
283 GetClipBox( hdc, &rect );
284 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
285 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
286 hdc = GetDCEx( hwnd_owndc, 0, DCX_USESTYLE );
287 SetRectEmpty( &rect );
288 GetClipBox( hdc, &rect );
289 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
290 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
291 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
292 ReleaseDC( hwnd_owndc, hdc );
293 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
295 SetRect( &rect, 20, 20, 30, 30 );
296 MapWindowPoints( hwnd_owndc, 0, (POINT *)&rect, 2 );
297 hrgn2 = CreateRectRgnIndirect( &rect );
298 hdc = GetDCEx( hwnd_owndc, hrgn2, DCX_INTERSECTRGN | DCX_USESTYLE );
299 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
300 SetRectEmpty( &rect );
301 GetClipBox( hdc, &rect );
302 ok( rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30,
303 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
304 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
305 ReleaseDC( hwnd_owndc, hdc );
306 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
307 hdc = GetDCEx( hwnd_owndc, 0, DCX_EXCLUDERGN | DCX_USESTYLE );
308 ok( GetRgnBox( hrgn2, &rect ) == ERROR, "region must no longer be valid\n" );
309 SetRectEmpty( &rect );
310 GetClipBox( hdc, &rect );
311 ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
312 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect ));
313 ReleaseDC( hwnd_owndc, hdc );
315 /* class DC */
317 SetRect( &rect, 10, 10, 20, 20 );
318 MapWindowPoints( hwnd_classdc, 0, (POINT *)&rect, 2 );
319 hrgn = CreateRectRgnIndirect( &rect );
320 hdc = GetDCEx( hwnd_classdc, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
321 SetRectEmpty( &rect );
322 GetClipBox( hdc, &rect );
323 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
324 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
325 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
326 ReleaseDC( hwnd_classdc, hdc );
327 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
328 SetRectEmpty( &rect );
329 GetClipBox( hdc, &rect );
330 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
331 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
333 hdc = GetDCEx( hwnd_classdc, 0, DCX_USESTYLE );
334 SetRectEmpty( &rect );
335 GetClipBox( hdc, &rect );
336 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
337 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
338 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
339 ReleaseDC( hwnd_classdc, hdc );
340 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
342 SetRect( &rect, 20, 20, 30, 30 );
343 MapWindowPoints( hwnd_classdc, 0, (POINT *)&rect, 2 );
344 hrgn2 = CreateRectRgnIndirect( &rect );
345 hdc = GetDCEx( hwnd_classdc, hrgn2, DCX_INTERSECTRGN | DCX_USESTYLE );
346 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
347 SetRectEmpty( &rect );
348 GetClipBox( hdc, &rect );
349 ok( rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30,
350 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
351 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
353 old_hdc = hdc;
354 hdc = GetDCEx( hwnd_classdc2, 0, DCX_USESTYLE );
355 ok( old_hdc == hdc, "did not get the same hdc %p/%p\n", old_hdc, hdc );
356 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
357 SetRectEmpty( &rect );
358 GetClipBox( hdc, &rect );
359 ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
360 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect ));
361 ReleaseDC( hwnd_classdc2, hdc );
362 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
363 hdc = GetDCEx( hwnd_classdc2, 0, DCX_EXCLUDERGN | DCX_USESTYLE );
364 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
365 ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
366 "clip box must have been reset %s\n", wine_dbgstr_rect( &rect ));
367 ReleaseDC( hwnd_classdc2, hdc );
369 /* parent DC */
370 hdc = GetDC( hwnd_parentdc );
371 GetClipBox( hdc, &rect );
372 ReleaseDC( hwnd_parentdc, hdc );
374 hdc = GetDC( hwnd_parent );
375 GetClipBox( hdc, &parent_rect );
376 ReleaseDC( hwnd_parent, hdc );
378 ok( EqualRect( &rect, &parent_rect ), "rect = %s, expected %s\n", wine_dbgstr_rect( &rect ),
379 wine_dbgstr_rect( &parent_rect ));
383 /* test various BeginPaint/EndPaint behaviors */
384 static void test_begin_paint(void)
386 HDC old_hdc, hdc;
387 RECT rect, parent_rect, client_rect;
388 PAINTSTRUCT ps;
389 COLORREF cr;
391 /* cache DC */
393 /* clear update region */
394 RedrawWindow( hwnd_cache, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
395 SetRect( &rect, 10, 10, 20, 20 );
396 RedrawWindow( hwnd_cache, &rect, 0, RDW_INVALIDATE );
397 hdc = BeginPaint( hwnd_cache, &ps );
398 SetRectEmpty( &rect );
399 GetClipBox( hdc, &rect );
400 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
401 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
402 EndPaint( hwnd_cache, &ps );
404 SetWindowPos( hwnd_cache, 0, 0, 0, 100, 100, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE );
405 RedrawWindow( hwnd_cache, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
406 SetRect( &rect, 0, 0, 150, 150 );
407 RedrawWindow( hwnd_cache, &rect, 0, RDW_INVALIDATE|RDW_NOFRAME|RDW_NOERASE );
408 hdc = BeginPaint( hwnd_cache, &ps );
409 GetClipBox( hdc, &rect );
410 GetClientRect( hwnd_cache, &client_rect );
411 ok( EqualRect( &rect, &client_rect ), "clip box = %s, expected %s\n",
412 wine_dbgstr_rect( &rect ), wine_dbgstr_rect( &client_rect ));
413 SetWindowPos( hwnd_cache, 0, 0, 0, 200, 200, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE );
414 GetClipBox( hdc, &rect );
415 GetClientRect( hwnd_cache, &client_rect );
416 todo_wine ok( (!rect.left && !rect.top && rect.right == 150 && rect.bottom == 150) ||
417 broken( EqualRect( &rect, &client_rect )),
418 "clip box = %s\n", wine_dbgstr_rect( &rect ));
419 EndPaint( hwnd_cache, &ps );
421 SetWindowPos( hwnd_cache, 0, 0, 0, 100, 100, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE );
422 RedrawWindow( hwnd_cache, NULL, 0, RDW_INVALIDATE|RDW_NOFRAME|RDW_NOERASE );
423 hdc = BeginPaint( hwnd_cache, &ps );
424 SetWindowPos( hwnd_cache, 0, 0, 0, 200, 200, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE );
425 GetClipBox( hdc, &rect );
426 GetClientRect( hwnd_cache, &client_rect );
427 todo_wine ok( EqualRect( &rect, &client_rect ), "clip box = %s, expected %s\n",
428 wine_dbgstr_rect( &rect ), wine_dbgstr_rect( &client_rect ));
429 EndPaint( hwnd_cache, &ps );
431 /* window DC */
433 RedrawWindow( hwnd_owndc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
434 SetRect( &rect, 10, 10, 20, 20 );
435 RedrawWindow( hwnd_owndc, &rect, 0, RDW_INVALIDATE );
436 hdc = BeginPaint( hwnd_owndc, &ps );
437 SetRectEmpty( &rect );
438 GetClipBox( hdc, &rect );
439 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
440 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
441 ReleaseDC( hwnd_owndc, hdc );
442 SetRectEmpty( &rect );
443 GetClipBox( hdc, &rect );
444 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
445 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
446 ok( GetDC( hwnd_owndc ) == hdc, "got different hdc\n" );
447 SetRectEmpty( &rect );
448 GetClipBox( hdc, &rect );
449 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
450 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
451 EndPaint( hwnd_owndc, &ps );
452 SetRectEmpty( &rect );
453 GetClipBox( hdc, &rect );
454 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
455 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect ));
456 RedrawWindow( hwnd_owndc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
457 SetRect( &rect, 10, 10, 20, 20 );
458 RedrawWindow( hwnd_owndc, &rect, 0, RDW_INVALIDATE|RDW_ERASE );
459 ok( GetDC( hwnd_owndc ) == hdc, "got different hdc\n" );
460 SetRectEmpty( &rect );
461 GetClipBox( hdc, &rect );
462 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
463 "clip box should be the whole window %s\n", wine_dbgstr_rect( &rect ));
464 RedrawWindow( hwnd_owndc, NULL, 0, RDW_ERASENOW );
465 SetRectEmpty( &rect );
466 GetClipBox( hdc, &rect );
467 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
468 "clip box should still be the whole window %s\n", wine_dbgstr_rect( &rect ));
470 SetWindowPos( hwnd_owndc, 0, 0, 0, 100, 100, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE );
471 RedrawWindow( hwnd_owndc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
472 SetRect( &rect, 0, 0, 50, 50 );
473 RedrawWindow( hwnd_owndc, &rect, 0, RDW_INVALIDATE|RDW_ERASE );
474 hdc = BeginPaint( hwnd_owndc, &ps );
475 GetClipBox( hdc, &rect );
476 ok( !rect.left && !rect.top && rect.right == 50 && rect.bottom == 50,
477 "clip box = %s\n", wine_dbgstr_rect( &rect ));
478 SetWindowPos( hwnd_owndc, 0, 0, 0, 200, 200, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE );
479 GetClipBox( hdc, &rect );
480 GetClientRect( hwnd_owndc, &client_rect );
481 ok( EqualRect( &rect, &client_rect ), "clip box = %s, expected %s\n",
482 wine_dbgstr_rect( &rect ), wine_dbgstr_rect( &client_rect ));
483 EndPaint( hwnd_owndc, &ps );
485 /* class DC */
487 RedrawWindow( hwnd_classdc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
488 SetRect( &rect, 10, 10, 20, 20 );
489 RedrawWindow( hwnd_classdc, &rect, 0, RDW_INVALIDATE );
490 hdc = BeginPaint( hwnd_classdc, &ps );
491 SetRectEmpty( &rect );
492 GetClipBox( hdc, &rect );
493 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
494 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
496 old_hdc = hdc;
497 hdc = GetDC( hwnd_classdc2 );
498 ok( old_hdc == hdc, "did not get the same hdc %p/%p\n", old_hdc, hdc );
499 SetRectEmpty( &rect );
500 GetClipBox( hdc, &rect );
501 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
502 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect ));
503 ReleaseDC( hwnd_classdc2, hdc );
504 EndPaint( hwnd_classdc, &ps );
506 /* parent DC */
507 RedrawWindow( hwnd_parent, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
508 RedrawWindow( hwnd_parentdc, NULL, 0, RDW_INVALIDATE );
509 hdc = BeginPaint( hwnd_parentdc, &ps );
510 GetClipBox( hdc, &rect );
511 cr = SetPixel( hdc, 10, 10, RGB(255, 0, 0) );
512 ok( cr != -1, "error drawing outside of window client area\n" );
513 EndPaint( hwnd_parentdc, &ps );
514 GetClientRect( hwnd_parent, &parent_rect );
516 ok( rect.left == parent_rect.left, "rect.left = %d, expected %d\n", rect.left, parent_rect.left );
517 ok( rect.top == parent_rect.top, "rect.top = %d, expected %d\n", rect.top, parent_rect.top );
518 todo_wine ok( rect.right == parent_rect.right, "rect.right = %d, expected %d\n", rect.right, parent_rect.right );
519 todo_wine ok( rect.bottom == parent_rect.bottom, "rect.bottom = %d, expected %d\n", rect.bottom, parent_rect.bottom );
521 hdc = GetDC( hwnd_parent );
522 todo_wine ok( GetPixel( hdc, 10, 10 ) == cr, "error drawing outside of window client area\n" );
523 ReleaseDC( hwnd_parent, hdc );
526 /* test ScrollWindow with window DCs */
527 static void test_scroll_window(void)
529 PAINTSTRUCT ps;
530 HDC hdc;
531 RECT clip, rect;
533 /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
535 UpdateWindow( hwnd_owndc );
536 SetRect( &clip, 25, 25, 50, 50 );
537 ScrollWindow( hwnd_owndc, -5, -10, NULL, &clip );
538 hdc = BeginPaint( hwnd_owndc, &ps );
539 SetRectEmpty( &rect );
540 GetClipBox( hdc, &rect );
541 ok( rect.left >= 25 && rect.top >= 25 && rect.right <= 50 && rect.bottom <= 50,
542 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
543 EndPaint( hwnd_owndc, &ps );
545 SetViewportExtEx( hdc, 2, 3, NULL );
546 SetViewportOrgEx( hdc, 30, 20, NULL );
548 ScrollWindow( hwnd_owndc, -5, -10, NULL, &clip );
549 hdc = BeginPaint( hwnd_owndc, &ps );
550 SetRectEmpty( &rect );
551 GetClipBox( hdc, &rect );
552 ok( rect.left >= 25 && rect.top >= 25 && rect.right <= 50 && rect.bottom <= 50,
553 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
554 EndPaint( hwnd_owndc, &ps );
556 ScrollWindowEx( hwnd_owndc, -5, -10, NULL, &clip, 0, NULL, SW_INVALIDATE | SW_ERASE );
557 hdc = BeginPaint( hwnd_owndc, &ps );
558 SetRectEmpty( &rect );
559 GetClipBox( hdc, &rect );
560 ok( rect.left >= -5 && rect.top >= 5 && rect.right <= 20 && rect.bottom <= 30,
561 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
562 EndPaint( hwnd_owndc, &ps );
564 SetViewportExtEx( hdc, 1, 1, NULL );
565 SetViewportOrgEx( hdc, 0, 0, NULL );
567 ScrollWindowEx( hwnd_owndc, -5, -10, NULL, &clip, 0, NULL, SW_INVALIDATE | SW_ERASE );
568 hdc = BeginPaint( hwnd_owndc, &ps );
569 SetRectEmpty( &rect );
570 GetClipBox( hdc, &rect );
571 ok( rect.left >= 25 && rect.top >= 25 && rect.right <= 50 && rect.bottom <= 50,
572 "invalid clip box %s\n", wine_dbgstr_rect( &rect ));
573 EndPaint( hwnd_owndc, &ps );
576 static void test_invisible_create(void)
578 HWND hwnd_owndc = CreateWindowA("owndc_class", NULL, WS_OVERLAPPED,
579 0, 200, 100, 100,
580 0, 0, GetModuleHandleA(0), NULL );
581 HDC dc1, dc2;
583 dc1 = GetDC(hwnd_owndc);
584 dc2 = GetDC(hwnd_owndc);
586 ok(dc1 == dc2, "expected owndc dcs to match\n");
588 ReleaseDC(hwnd_owndc, dc2);
589 ReleaseDC(hwnd_owndc, dc1);
590 DestroyWindow(hwnd_owndc);
593 static void test_dc_layout(void)
595 HWND hwnd_cache_rtl, hwnd_owndc_rtl, hwnd_classdc_rtl, hwnd_classdc2_rtl;
596 HDC hdc;
597 DWORD layout;
599 hdc = GetDC( hwnd_cache );
600 SetLayout( hdc, LAYOUT_RTL );
601 layout = GetLayout( hdc );
602 ReleaseDC( hwnd_cache, hdc );
603 if (!layout)
605 win_skip( "SetLayout not supported\n" );
606 return;
609 hwnd_cache_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "cache_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
610 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
611 hwnd_owndc_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "owndc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
612 0, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
613 hwnd_classdc_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
614 200, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
615 hwnd_classdc2_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
616 200, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
617 hdc = GetDC( hwnd_cache_rtl );
618 layout = GetLayout( hdc );
620 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
621 SetLayout( hdc, 0 );
622 ReleaseDC( hwnd_cache_rtl, hdc );
623 hdc = GetDC( hwnd_owndc_rtl );
624 layout = GetLayout( hdc );
625 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
626 ReleaseDC( hwnd_cache_rtl, hdc );
628 hdc = GetDC( hwnd_cache );
629 layout = GetLayout( hdc );
630 ok( layout == 0, "wrong layout %x\n", layout );
631 ReleaseDC( hwnd_cache, hdc );
633 hdc = GetDC( hwnd_owndc_rtl );
634 layout = GetLayout( hdc );
635 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
636 SetLayout( hdc, 0 );
637 ReleaseDC( hwnd_owndc_rtl, hdc );
638 hdc = GetDC( hwnd_owndc_rtl );
639 layout = GetLayout( hdc );
640 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
641 ReleaseDC( hwnd_owndc_rtl, hdc );
643 hdc = GetDC( hwnd_classdc_rtl );
644 layout = GetLayout( hdc );
645 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
646 SetLayout( hdc, 0 );
647 ReleaseDC( hwnd_classdc_rtl, hdc );
648 hdc = GetDC( hwnd_classdc2_rtl );
649 layout = GetLayout( hdc );
650 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
651 ReleaseDC( hwnd_classdc2_rtl, hdc );
652 hdc = GetDC( hwnd_classdc );
653 layout = GetLayout( hdc );
654 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
655 ReleaseDC( hwnd_classdc_rtl, hdc );
657 DestroyWindow(hwnd_classdc2_rtl);
658 DestroyWindow(hwnd_classdc_rtl);
659 DestroyWindow(hwnd_owndc_rtl);
660 DestroyWindow(hwnd_cache_rtl);
663 static void test_destroyed_window(void)
665 HDC dc, old_dc;
666 int rop;
668 dc = GetDC( hwnd_cache );
669 SetROP2( dc, R2_WHITE );
670 rop = GetROP2( dc );
671 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
672 ok( WindowFromDC( dc ) == hwnd_cache, "wrong window\n" );
673 old_dc = dc;
675 DestroyWindow( hwnd_cache );
676 rop = GetROP2( dc );
677 ok( rop == 0, "wrong ROP2 %d\n", rop );
678 ok( WindowFromDC( dc ) != hwnd_cache, "wrong window\n" );
679 ok( !ReleaseDC( hwnd_cache, dc ), "ReleaseDC succeeded\n" );
680 dc = GetDC( hwnd_cache );
681 ok( !dc, "Got a non-NULL DC (%p) for a destroyed window\n", dc );
683 dc = GetDC( hwnd_classdc );
684 SetROP2( dc, R2_WHITE );
685 rop = GetROP2( dc );
686 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
687 ok( WindowFromDC( dc ) == hwnd_classdc, "wrong window\n" );
688 old_dc = dc;
690 dc = GetDC( hwnd_classdc2 );
691 ok( old_dc == dc, "wrong DC\n" );
692 rop = GetROP2( dc );
693 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
694 ok( WindowFromDC( dc ) == hwnd_classdc2, "wrong window\n" );
695 DestroyWindow( hwnd_classdc2 );
697 rop = GetROP2( dc );
698 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
699 ok( WindowFromDC( dc ) != hwnd_classdc2, "wrong window\n" );
700 ok( !ReleaseDC( hwnd_classdc2, dc ), "ReleaseDC succeeded\n" );
701 dc = GetDC( hwnd_classdc2 );
702 ok( !dc, "Got a non-NULL DC (%p) for a destroyed window\n", dc );
704 dc = GetDC( hwnd_classdc );
705 ok( dc != 0, "Got NULL DC\n" );
706 rop = GetROP2( dc );
707 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
708 ok( WindowFromDC( dc ) == hwnd_classdc, "wrong window\n" );
709 DestroyWindow( hwnd_classdc );
711 rop = GetROP2( dc );
712 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
713 ok( WindowFromDC( dc ) != hwnd_classdc, "wrong window\n" );
714 ok( !ReleaseDC( hwnd_classdc, dc ), "ReleaseDC succeeded\n" );
715 dc = GetDC( hwnd_classdc );
716 ok( !dc, "Got a non-NULL DC (%p) for a destroyed window\n", dc );
718 dc = GetDC( hwnd_owndc );
719 ok( dc != 0, "Got NULL DC\n" );
720 rop = GetROP2( dc );
721 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
722 ok( WindowFromDC( dc ) == hwnd_owndc, "wrong window\n" );
723 DestroyWindow( hwnd_owndc );
725 rop = GetROP2( dc );
726 ok( rop == 0, "wrong ROP2 %d\n", rop );
727 ok( WindowFromDC( dc ) != hwnd_owndc, "wrong window\n" );
728 ok( !ReleaseDC( hwnd_owndc, dc ), "ReleaseDC succeeded\n" );
729 dc = GetDC( hwnd_owndc );
730 ok( !dc, "Got a non-NULL DC (%p) for a destroyed window\n", dc );
732 DestroyWindow( hwnd_parent );
735 START_TEST(dce)
737 WNDCLASSA cls;
739 cls.style = CS_DBLCLKS;
740 cls.lpfnWndProc = DefWindowProcA;
741 cls.cbClsExtra = 0;
742 cls.cbWndExtra = 0;
743 cls.hInstance = GetModuleHandleA(0);
744 cls.hIcon = 0;
745 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
746 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
747 cls.lpszMenuName = NULL;
748 cls.lpszClassName = "cache_class";
749 RegisterClassA(&cls);
750 cls.style = CS_DBLCLKS | CS_OWNDC;
751 cls.lpszClassName = "owndc_class";
752 RegisterClassA(&cls);
753 cls.style = CS_DBLCLKS | CS_CLASSDC;
754 cls.lpszClassName = "classdc_class";
755 RegisterClassA(&cls);
756 cls.style = CS_PARENTDC;
757 cls.lpszClassName = "parentdc_class";
758 RegisterClassA(&cls);
760 hwnd_cache = CreateWindowA("cache_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
761 0, 0, 100, 100,
762 0, 0, GetModuleHandleA(0), NULL );
763 hwnd_owndc = CreateWindowA("owndc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
764 0, 200, 100, 100,
765 0, 0, GetModuleHandleA(0), NULL );
766 hwnd_classdc = CreateWindowA("classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
767 200, 0, 100, 100,
768 0, 0, GetModuleHandleA(0), NULL );
769 hwnd_classdc2 = CreateWindowA("classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
770 200, 200, 100, 100,
771 0, 0, GetModuleHandleA(0), NULL );
772 hwnd_parent = CreateWindowA("static", NULL, WS_OVERLAPPED | WS_VISIBLE,
773 400, 0, 100, 100, 0, 0, 0, NULL );
774 hwnd_parentdc = CreateWindowA("parentdc_class", NULL, WS_CHILD | WS_VISIBLE,
775 0, 0, 1, 1, hwnd_parent, 0, 0, NULL );
777 test_dc_attributes();
778 test_parameters();
779 test_dc_visrgn();
780 test_begin_paint();
781 test_scroll_window();
782 test_invisible_create();
783 test_dc_layout();
784 /* this should be last */
785 test_destroyed_window();