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
30 #include "wine/test.h"
33 #define DCX_USESTYLE 0x00010000
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)
48 hdc
= GetDC( hwnd_cache
);
49 def_rop
= GetROP2( hdc
);
51 SetROP2( hdc
, R2_WHITE
);
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
) == 0, "wrong window\n" );
58 hdc
= GetDC( hwnd_cache
);
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
);
67 for (i
= 0; i
< 20; i
++)
69 hdc
= hdcs
[i
] = GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
72 ok( rop
== def_rop
, "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
76 SetROP2( hdc
, R2_WHITE
);
81 trace( "hdc %p not found in cache using %p\n", 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
);
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
);
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
);
104 rop
= GetROP2( 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
);
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 ok( WindowFromDC( old_hdc
) == 0, "wrong window\n" );
125 hdc
= GetDC( hwnd_owndc
);
126 SetROP2( hdc
, R2_WHITE
);
127 rop
= GetROP2( hdc
);
128 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
131 ok( WindowFromDC( hdc
) == hwnd_owndc
, "wrong window\n" );
132 ReleaseDC( hwnd_owndc
, hdc
);
133 ok( WindowFromDC( hdc
) == hwnd_owndc
, "wrong window\n" );
134 hdc
= GetDC( hwnd_owndc
);
135 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
136 rop
= GetROP2( hdc
);
137 ok( rop
== R2_WHITE
, "wrong ROP2 %d after release\n", rop
);
138 ok( WindowFromDC( hdc
) == hwnd_owndc
, "wrong window\n" );
139 ReleaseDC( hwnd_owndc
, hdc
);
140 rop
= GetROP2( hdc
);
141 ok( rop
== R2_WHITE
, "wrong ROP2 %d after second release\n", rop
);
145 hdc
= GetDC( hwnd_classdc
);
146 SetROP2( hdc
, R2_WHITE
);
147 rop
= GetROP2( hdc
);
148 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
151 ok( WindowFromDC( hdc
) == hwnd_classdc
, "wrong window\n" );
152 ReleaseDC( hwnd_classdc
, hdc
);
153 ok( WindowFromDC( hdc
) == hwnd_classdc
, "wrong window\n" );
154 hdc
= GetDC( hwnd_classdc
);
155 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
156 rop
= GetROP2( hdc
);
157 ok( rop
== R2_WHITE
, "wrong ROP2 %d after release\n", rop
);
158 ok( WindowFromDC( hdc
) == hwnd_classdc
, "wrong window\n" );
159 ReleaseDC( hwnd_classdc
, hdc
);
160 rop
= GetROP2( hdc
);
161 ok( rop
== R2_WHITE
, "wrong ROP2 %d after second release\n", rop
);
163 /* test class DC with 2 windows */
165 old_hdc
= GetDC( hwnd_classdc
);
166 SetROP2( old_hdc
, R2_BLACK
);
167 ok( WindowFromDC( old_hdc
) == hwnd_classdc
, "wrong window\n" );
168 hdc
= GetDC( hwnd_classdc2
);
169 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
170 rop
= GetROP2( hdc
);
171 ok( rop
== R2_BLACK
, "wrong ROP2 %d for other window\n", rop
);
172 ok( WindowFromDC( hdc
) == hwnd_classdc2
, "wrong window\n" );
173 ReleaseDC( hwnd_classdc
, old_hdc
);
174 ReleaseDC( hwnd_classdc
, hdc
);
175 ok( WindowFromDC( hdc
) == hwnd_classdc2
, "wrong window\n" );
176 rop
= GetROP2( hdc
);
177 ok( rop
== R2_BLACK
, "wrong ROP2 %d after release\n", rop
);
181 /* test behavior with various invalid parameters */
182 static void test_parameters(void)
186 hdc
= GetDC( hwnd_cache
);
187 ok( ReleaseDC( hwnd_owndc
, hdc
), "ReleaseDC with wrong window should succeed\n" );
189 hdc
= GetDC( hwnd_cache
);
190 ok( !ReleaseDC( hwnd_cache
, 0 ), "ReleaseDC with wrong HDC should fail\n" );
191 ok( ReleaseDC( hwnd_cache
, hdc
), "correct ReleaseDC should succeed\n" );
192 ok( !ReleaseDC( hwnd_cache
, hdc
), "second ReleaseDC should fail\n" );
194 hdc
= GetDC( hwnd_owndc
);
195 ok( ReleaseDC( hwnd_cache
, hdc
), "ReleaseDC with wrong window should succeed\n" );
196 hdc
= GetDC( hwnd_owndc
);
197 ok( ReleaseDC( hwnd_owndc
, hdc
), "correct ReleaseDC should succeed\n" );
198 ok( ReleaseDC( hwnd_owndc
, hdc
), "second ReleaseDC should succeed\n" );
200 hdc
= GetDC( hwnd_classdc
);
201 ok( ReleaseDC( hwnd_cache
, hdc
), "ReleaseDC with wrong window should succeed\n" );
202 hdc
= GetDC( hwnd_classdc
);
203 ok( ReleaseDC( hwnd_classdc
, hdc
), "correct ReleaseDC should succeed\n" );
204 ok( ReleaseDC( hwnd_classdc
, hdc
), "second ReleaseDC should succeed\n" );
208 static void test_dc_visrgn(void)
212 RECT rect
, parent_rect
;
216 SetRect( &rect
, 10, 10, 20, 20 );
217 MapWindowPoints( hwnd_cache
, 0, (POINT
*)&rect
, 2 );
218 hrgn
= CreateRectRgnIndirect( &rect
);
219 hdc
= GetDCEx( hwnd_cache
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
220 SetRectEmpty( &rect
);
221 GetClipBox( hdc
, &rect
);
222 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
223 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
224 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
225 ReleaseDC( hwnd_cache
, hdc
);
226 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
228 /* cache DC with NORESETATTRS */
230 SetRect( &rect
, 10, 10, 20, 20 );
231 MapWindowPoints( hwnd_cache
, 0, (POINT
*)&rect
, 2 );
232 hrgn
= CreateRectRgnIndirect( &rect
);
233 hdc
= GetDCEx( hwnd_cache
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_NORESETATTRS
);
234 SetRectEmpty( &rect
);
235 GetClipBox( hdc
, &rect
);
236 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
237 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
238 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
239 ReleaseDC( hwnd_cache
, hdc
);
240 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
241 hdc
= GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
242 SetRectEmpty( &rect
);
243 GetClipBox( hdc
, &rect
);
244 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
245 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect
));
246 ReleaseDC( hwnd_cache
, hdc
);
250 SetRect( &rect
, 10, 10, 20, 20 );
251 MapWindowPoints( hwnd_owndc
, 0, (POINT
*)&rect
, 2 );
252 hrgn
= CreateRectRgnIndirect( &rect
);
253 hdc
= GetDCEx( hwnd_owndc
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
254 SetRectEmpty( &rect
);
255 GetClipBox( hdc
, &rect
);
256 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
257 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
258 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
259 ReleaseDC( hwnd_owndc
, hdc
);
260 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
261 SetRectEmpty( &rect
);
262 GetClipBox( hdc
, &rect
);
263 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
264 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
265 hdc
= GetDCEx( hwnd_owndc
, 0, DCX_USESTYLE
);
266 SetRectEmpty( &rect
);
267 GetClipBox( hdc
, &rect
);
268 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
269 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
270 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
271 ReleaseDC( hwnd_owndc
, hdc
);
272 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
274 SetRect( &rect
, 20, 20, 30, 30 );
275 MapWindowPoints( hwnd_owndc
, 0, (POINT
*)&rect
, 2 );
276 hrgn2
= CreateRectRgnIndirect( &rect
);
277 hdc
= GetDCEx( hwnd_owndc
, hrgn2
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
278 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
279 SetRectEmpty( &rect
);
280 GetClipBox( hdc
, &rect
);
281 ok( rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30,
282 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
283 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
284 ReleaseDC( hwnd_owndc
, hdc
);
285 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
286 hdc
= GetDCEx( hwnd_owndc
, 0, DCX_EXCLUDERGN
| DCX_USESTYLE
);
287 ok( GetRgnBox( hrgn2
, &rect
) == ERROR
, "region must no longer be valid\n" );
288 SetRectEmpty( &rect
);
289 GetClipBox( hdc
, &rect
);
290 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
291 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect
));
292 ReleaseDC( hwnd_owndc
, hdc
);
296 SetRect( &rect
, 10, 10, 20, 20 );
297 MapWindowPoints( hwnd_classdc
, 0, (POINT
*)&rect
, 2 );
298 hrgn
= CreateRectRgnIndirect( &rect
);
299 hdc
= GetDCEx( hwnd_classdc
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
300 SetRectEmpty( &rect
);
301 GetClipBox( hdc
, &rect
);
302 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
303 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
304 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
305 ReleaseDC( hwnd_classdc
, hdc
);
306 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
307 SetRectEmpty( &rect
);
308 GetClipBox( hdc
, &rect
);
309 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
310 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
312 hdc
= GetDCEx( hwnd_classdc
, 0, DCX_USESTYLE
);
313 SetRectEmpty( &rect
);
314 GetClipBox( hdc
, &rect
);
315 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
316 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
317 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
318 ReleaseDC( hwnd_classdc
, hdc
);
319 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
321 SetRect( &rect
, 20, 20, 30, 30 );
322 MapWindowPoints( hwnd_classdc
, 0, (POINT
*)&rect
, 2 );
323 hrgn2
= CreateRectRgnIndirect( &rect
);
324 hdc
= GetDCEx( hwnd_classdc
, hrgn2
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
325 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
326 SetRectEmpty( &rect
);
327 GetClipBox( hdc
, &rect
);
328 ok( rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30,
329 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
330 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
333 hdc
= GetDCEx( hwnd_classdc2
, 0, DCX_USESTYLE
);
334 ok( old_hdc
== hdc
, "did not get the same hdc %p/%p\n", old_hdc
, hdc
);
335 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
336 SetRectEmpty( &rect
);
337 GetClipBox( hdc
, &rect
);
338 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
339 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect
));
340 ReleaseDC( hwnd_classdc2
, hdc
);
341 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
342 hdc
= GetDCEx( hwnd_classdc2
, 0, DCX_EXCLUDERGN
| DCX_USESTYLE
);
343 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
344 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
345 "clip box must have been reset %s\n", wine_dbgstr_rect( &rect
));
346 ReleaseDC( hwnd_classdc2
, hdc
);
349 hdc
= GetDC( hwnd_parentdc
);
350 GetClipBox( hdc
, &rect
);
351 ReleaseDC( hwnd_parentdc
, hdc
);
353 hdc
= GetDC( hwnd_parent
);
354 GetClipBox( hdc
, &parent_rect
);
355 ReleaseDC( hwnd_parent
, hdc
);
357 ok( EqualRect( &rect
, &parent_rect
), "rect = %s, expected %s\n", wine_dbgstr_rect( &rect
),
358 wine_dbgstr_rect( &parent_rect
));
362 /* test various BeginPaint/EndPaint behaviors */
363 static void test_begin_paint(void)
366 RECT rect
, parent_rect
;
372 /* clear update region */
373 RedrawWindow( hwnd_cache
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
374 SetRect( &rect
, 10, 10, 20, 20 );
375 RedrawWindow( hwnd_cache
, &rect
, 0, RDW_INVALIDATE
);
376 hdc
= BeginPaint( hwnd_cache
, &ps
);
377 SetRectEmpty( &rect
);
378 GetClipBox( hdc
, &rect
);
379 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
380 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
381 EndPaint( hwnd_cache
, &ps
);
385 RedrawWindow( hwnd_owndc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
386 SetRect( &rect
, 10, 10, 20, 20 );
387 RedrawWindow( hwnd_owndc
, &rect
, 0, RDW_INVALIDATE
);
388 hdc
= BeginPaint( hwnd_owndc
, &ps
);
389 SetRectEmpty( &rect
);
390 GetClipBox( hdc
, &rect
);
391 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
392 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
393 ReleaseDC( hwnd_owndc
, hdc
);
394 SetRectEmpty( &rect
);
395 GetClipBox( hdc
, &rect
);
396 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
397 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
398 ok( GetDC( hwnd_owndc
) == hdc
, "got different hdc\n" );
399 SetRectEmpty( &rect
);
400 GetClipBox( hdc
, &rect
);
401 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
402 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
403 EndPaint( hwnd_owndc
, &ps
);
404 SetRectEmpty( &rect
);
405 GetClipBox( hdc
, &rect
);
406 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
407 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect
));
408 RedrawWindow( hwnd_owndc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
409 SetRect( &rect
, 10, 10, 20, 20 );
410 RedrawWindow( hwnd_owndc
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
);
411 ok( GetDC( hwnd_owndc
) == hdc
, "got different hdc\n" );
412 SetRectEmpty( &rect
);
413 GetClipBox( hdc
, &rect
);
414 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
415 "clip box should be the whole window %s\n", wine_dbgstr_rect( &rect
));
416 RedrawWindow( hwnd_owndc
, NULL
, 0, RDW_ERASENOW
);
417 SetRectEmpty( &rect
);
418 GetClipBox( hdc
, &rect
);
419 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
420 "clip box should still be the whole window %s\n", wine_dbgstr_rect( &rect
));
424 RedrawWindow( hwnd_classdc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
425 SetRect( &rect
, 10, 10, 20, 20 );
426 RedrawWindow( hwnd_classdc
, &rect
, 0, RDW_INVALIDATE
);
427 hdc
= BeginPaint( hwnd_classdc
, &ps
);
428 SetRectEmpty( &rect
);
429 GetClipBox( hdc
, &rect
);
430 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
431 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
434 hdc
= GetDC( hwnd_classdc2
);
435 ok( old_hdc
== hdc
, "did not get the same hdc %p/%p\n", old_hdc
, hdc
);
436 SetRectEmpty( &rect
);
437 GetClipBox( hdc
, &rect
);
438 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
439 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect
));
440 ReleaseDC( hwnd_classdc2
, hdc
);
441 EndPaint( hwnd_classdc
, &ps
);
444 RedrawWindow( hwnd_parent
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
445 RedrawWindow( hwnd_parentdc
, NULL
, 0, RDW_INVALIDATE
);
446 hdc
= BeginPaint( hwnd_parentdc
, &ps
);
447 GetClipBox( hdc
, &rect
);
448 cr
= SetPixel( hdc
, 10, 10, RGB(255, 0, 0) );
449 ok( cr
!= -1, "error drawing outside of window client area\n" );
450 EndPaint( hwnd_parentdc
, &ps
);
451 GetClientRect( hwnd_parent
, &parent_rect
);
453 ok( rect
.left
== parent_rect
.left
, "rect.left = %d, expected %d\n", rect
.left
, parent_rect
.left
);
454 ok( rect
.top
== parent_rect
.top
, "rect.top = %d, expected %d\n", rect
.top
, parent_rect
.top
);
455 todo_wine
ok( rect
.right
== parent_rect
.right
, "rect.right = %d, expected %d\n", rect
.right
, parent_rect
.right
);
456 todo_wine
ok( rect
.bottom
== parent_rect
.bottom
, "rect.bottom = %d, expected %d\n", rect
.bottom
, parent_rect
.bottom
);
458 hdc
= GetDC( hwnd_parent
);
459 todo_wine
ok( GetPixel( hdc
, 10, 10 ) == cr
, "error drawing outside of window client area\n" );
460 ReleaseDC( hwnd_parent
, hdc
);
463 /* test ScrollWindow with window DCs */
464 static void test_scroll_window(void)
470 /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
472 UpdateWindow( hwnd_owndc
);
473 SetRect( &clip
, 25, 25, 50, 50 );
474 ScrollWindow( hwnd_owndc
, -5, -10, NULL
, &clip
);
475 hdc
= BeginPaint( hwnd_owndc
, &ps
);
476 SetRectEmpty( &rect
);
477 GetClipBox( hdc
, &rect
);
478 ok( rect
.left
>= 25 && rect
.top
>= 25 && rect
.right
<= 50 && rect
.bottom
<= 50,
479 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
480 EndPaint( hwnd_owndc
, &ps
);
482 SetViewportExtEx( hdc
, 2, 3, NULL
);
483 SetViewportOrgEx( hdc
, 30, 20, NULL
);
485 ScrollWindow( hwnd_owndc
, -5, -10, NULL
, &clip
);
486 hdc
= BeginPaint( hwnd_owndc
, &ps
);
487 SetRectEmpty( &rect
);
488 GetClipBox( hdc
, &rect
);
489 ok( rect
.left
>= 25 && rect
.top
>= 25 && rect
.right
<= 50 && rect
.bottom
<= 50,
490 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
491 EndPaint( hwnd_owndc
, &ps
);
493 ScrollWindowEx( hwnd_owndc
, -5, -10, NULL
, &clip
, 0, NULL
, SW_INVALIDATE
| SW_ERASE
);
494 hdc
= BeginPaint( hwnd_owndc
, &ps
);
495 SetRectEmpty( &rect
);
496 GetClipBox( hdc
, &rect
);
497 ok( rect
.left
>= -5 && rect
.top
>= 5 && rect
.right
<= 20 && rect
.bottom
<= 30,
498 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
499 EndPaint( hwnd_owndc
, &ps
);
501 SetViewportExtEx( hdc
, 1, 1, NULL
);
502 SetViewportOrgEx( hdc
, 0, 0, NULL
);
504 ScrollWindowEx( hwnd_owndc
, -5, -10, NULL
, &clip
, 0, NULL
, SW_INVALIDATE
| SW_ERASE
);
505 hdc
= BeginPaint( hwnd_owndc
, &ps
);
506 SetRectEmpty( &rect
);
507 GetClipBox( hdc
, &rect
);
508 ok( rect
.left
>= 25 && rect
.top
>= 25 && rect
.right
<= 50 && rect
.bottom
<= 50,
509 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
510 EndPaint( hwnd_owndc
, &ps
);
513 static void test_invisible_create(void)
515 HWND hwnd_owndc
= CreateWindowA("owndc_class", NULL
, WS_OVERLAPPED
,
517 0, 0, GetModuleHandleA(0), NULL
);
520 dc1
= GetDC(hwnd_owndc
);
521 dc2
= GetDC(hwnd_owndc
);
523 ok(dc1
== dc2
, "expected owndc dcs to match\n");
525 ReleaseDC(hwnd_owndc
, dc2
);
526 ReleaseDC(hwnd_owndc
, dc1
);
527 DestroyWindow(hwnd_owndc
);
530 static void test_dc_layout(void)
532 DWORD (WINAPI
*pSetLayout
)(HDC hdc
, DWORD layout
);
533 DWORD (WINAPI
*pGetLayout
)(HDC hdc
);
534 HWND hwnd_cache_rtl
, hwnd_owndc_rtl
, hwnd_classdc_rtl
, hwnd_classdc2_rtl
;
537 HMODULE mod
= GetModuleHandleA("gdi32.dll");
539 pGetLayout
= (void *)GetProcAddress( mod
, "GetLayout" );
540 pSetLayout
= (void *)GetProcAddress( mod
, "SetLayout" );
541 if (!pGetLayout
|| !pSetLayout
)
543 win_skip( "Don't have SetLayout\n" );
547 hdc
= GetDC( hwnd_cache
);
548 pSetLayout( hdc
, LAYOUT_RTL
);
549 layout
= pGetLayout( hdc
);
550 ReleaseDC( hwnd_cache
, hdc
);
553 win_skip( "SetLayout not supported\n" );
557 hwnd_cache_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "cache_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
558 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
559 hwnd_owndc_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "owndc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
560 0, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
561 hwnd_classdc_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
562 200, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
563 hwnd_classdc2_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
564 200, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
565 hdc
= GetDC( hwnd_cache_rtl
);
566 layout
= pGetLayout( hdc
);
568 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
569 pSetLayout( hdc
, 0 );
570 ReleaseDC( hwnd_cache_rtl
, hdc
);
571 hdc
= GetDC( hwnd_owndc_rtl
);
572 layout
= pGetLayout( hdc
);
573 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
574 ReleaseDC( hwnd_cache_rtl
, hdc
);
576 hdc
= GetDC( hwnd_cache
);
577 layout
= pGetLayout( hdc
);
578 ok( layout
== 0, "wrong layout %x\n", layout
);
579 ReleaseDC( hwnd_cache
, hdc
);
581 hdc
= GetDC( hwnd_owndc_rtl
);
582 layout
= pGetLayout( hdc
);
583 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
584 pSetLayout( hdc
, 0 );
585 ReleaseDC( hwnd_owndc_rtl
, hdc
);
586 hdc
= GetDC( hwnd_owndc_rtl
);
587 layout
= pGetLayout( hdc
);
588 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
589 ReleaseDC( hwnd_owndc_rtl
, hdc
);
591 hdc
= GetDC( hwnd_classdc_rtl
);
592 layout
= pGetLayout( hdc
);
593 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
594 pSetLayout( hdc
, 0 );
595 ReleaseDC( hwnd_classdc_rtl
, hdc
);
596 hdc
= GetDC( hwnd_classdc2_rtl
);
597 layout
= pGetLayout( hdc
);
598 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
599 ReleaseDC( hwnd_classdc2_rtl
, hdc
);
600 hdc
= GetDC( hwnd_classdc
);
601 layout
= pGetLayout( hdc
);
602 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
603 ReleaseDC( hwnd_classdc_rtl
, hdc
);
605 DestroyWindow(hwnd_classdc2_rtl
);
606 DestroyWindow(hwnd_classdc_rtl
);
607 DestroyWindow(hwnd_owndc_rtl
);
608 DestroyWindow(hwnd_cache_rtl
);
611 static void test_destroyed_window(void)
617 dc
= GetDC( hwnd_cache
);
618 SetROP2( dc
, R2_WHITE
);
620 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
621 ok( WindowFromDC( dc
) == hwnd_cache
, "wrong window\n" );
624 DestroyWindow( hwnd_cache
);
626 ok( rop
== 0, "wrong ROP2 %d\n", rop
);
627 ok( WindowFromDC( dc
) == 0, "wrong window\n" );
628 ok( !ReleaseDC( hwnd_cache
, dc
), "ReleaseDC succeeded\n" );
629 dc
= GetDC( hwnd_cache
);
630 ok( !dc
, "Got a non-NULL DC (%p) for a destroyed window\n", dc
);
632 for (i
= 0; i
< 30; i
++)
634 dc
= hdcs
[i
] = GetDCEx( hwnd_parent
, 0, DCX_CACHE
| DCX_USESTYLE
);
635 if (dc
== old_dc
) break;
637 ok( i
< 30, "DC for destroyed window not reused\n" );
638 while (i
> 0) ReleaseDC( hwnd_parent
, hdcs
[--i
] );
640 dc
= GetDC( hwnd_classdc
);
641 SetROP2( dc
, R2_WHITE
);
643 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
644 ok( WindowFromDC( dc
) == hwnd_classdc
, "wrong window\n" );
647 dc
= GetDC( hwnd_classdc2
);
648 ok( old_dc
== dc
, "wrong DC\n" );
650 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
651 ok( WindowFromDC( dc
) == hwnd_classdc2
, "wrong window\n" );
652 DestroyWindow( hwnd_classdc2
);
655 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
656 ok( WindowFromDC( dc
) == 0, "wrong window\n" );
657 ok( !ReleaseDC( hwnd_classdc2
, dc
), "ReleaseDC succeeded\n" );
658 dc
= GetDC( hwnd_classdc2
);
659 ok( !dc
, "Got a non-NULL DC (%p) for a destroyed window\n", dc
);
661 dc
= GetDC( hwnd_classdc
);
662 ok( dc
!= 0, "Got NULL DC\n" );
664 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
665 ok( WindowFromDC( dc
) == hwnd_classdc
, "wrong window\n" );
666 DestroyWindow( hwnd_classdc
);
669 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
670 ok( WindowFromDC( dc
) == 0, "wrong window\n" );
671 ok( !ReleaseDC( hwnd_classdc
, dc
), "ReleaseDC succeeded\n" );
672 dc
= GetDC( hwnd_classdc
);
673 ok( !dc
, "Got a non-NULL DC (%p) for a destroyed window\n", dc
);
675 dc
= GetDC( hwnd_owndc
);
676 ok( dc
!= 0, "Got NULL DC\n" );
678 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
679 ok( WindowFromDC( dc
) == hwnd_owndc
, "wrong window\n" );
680 DestroyWindow( hwnd_owndc
);
683 ok( rop
== 0, "wrong ROP2 %d\n", rop
);
684 ok( WindowFromDC( dc
) == 0, "wrong window\n" );
685 ok( !ReleaseDC( hwnd_owndc
, dc
), "ReleaseDC succeeded\n" );
686 dc
= GetDC( hwnd_owndc
);
687 ok( !dc
, "Got a non-NULL DC (%p) for a destroyed window\n", dc
);
689 DestroyWindow( hwnd_parent
);
696 cls
.style
= CS_DBLCLKS
;
697 cls
.lpfnWndProc
= DefWindowProcA
;
700 cls
.hInstance
= GetModuleHandleA(0);
702 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
703 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
704 cls
.lpszMenuName
= NULL
;
705 cls
.lpszClassName
= "cache_class";
706 RegisterClassA(&cls
);
707 cls
.style
= CS_DBLCLKS
| CS_OWNDC
;
708 cls
.lpszClassName
= "owndc_class";
709 RegisterClassA(&cls
);
710 cls
.style
= CS_DBLCLKS
| CS_CLASSDC
;
711 cls
.lpszClassName
= "classdc_class";
712 RegisterClassA(&cls
);
713 cls
.style
= CS_PARENTDC
;
714 cls
.lpszClassName
= "parentdc_class";
715 RegisterClassA(&cls
);
717 hwnd_cache
= CreateWindowA("cache_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
719 0, 0, GetModuleHandleA(0), NULL
);
720 hwnd_owndc
= CreateWindowA("owndc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
722 0, 0, GetModuleHandleA(0), NULL
);
723 hwnd_classdc
= CreateWindowA("classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
725 0, 0, GetModuleHandleA(0), NULL
);
726 hwnd_classdc2
= CreateWindowA("classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
728 0, 0, GetModuleHandleA(0), NULL
);
729 hwnd_parent
= CreateWindowA("static", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
730 400, 0, 100, 100, 0, 0, 0, NULL
);
731 hwnd_parentdc
= CreateWindowA("parentdc_class", NULL
, WS_CHILD
| WS_VISIBLE
,
732 0, 0, 1, 1, hwnd_parent
, 0, 0, NULL
);
734 test_dc_attributes();
738 test_scroll_window();
739 test_invisible_create();
741 /* this should be last */
742 test_destroyed_window();