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
;
38 /* test behavior of DC attributes with various GetDC/ReleaseDC combinations */
39 static void test_dc_attributes(void)
43 INT i
, rop
, def_rop
, found_dc
;
47 hdc
= GetDC( hwnd_cache
);
48 def_rop
= GetROP2( hdc
);
50 SetROP2( hdc
, R2_WHITE
);
52 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
54 ReleaseDC( hwnd_cache
, hdc
);
55 hdc
= GetDC( hwnd_cache
);
57 ok( rop
== def_rop
, "wrong ROP2 %d after release\n", rop
);
58 SetROP2( hdc
, R2_WHITE
);
59 ReleaseDC( hwnd_cache
, hdc
);
63 for (i
= 0; i
< 20; i
++)
65 hdc
= hdcs
[i
] = GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
68 ok( rop
== def_rop
, "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
72 SetROP2( hdc
, R2_WHITE
);
77 trace( "hdc %p not found in cache using %p\n", old_hdc
, hdcs
[0] );
79 SetROP2( old_hdc
, R2_WHITE
);
81 while (i
> 0) ReleaseDC( hwnd_cache
, hdcs
[--i
] );
83 for (i
= 0; i
< 20; i
++)
85 hdc
= hdcs
[i
] = GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
89 ok( rop
== R2_WHITE
|| broken( rop
== def_rop
), /* win9x doesn't support DCX_NORESETATTRS */
90 "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
92 ok( rop
== def_rop
, "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
94 while (i
> 0) ReleaseDC( hwnd_cache
, hdcs
[--i
] );
96 for (i
= 0; i
< 20; i
++)
98 hdc
= hdcs
[i
] = GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
);
100 rop
= GetROP2( hdc
);
103 ok( rop
== R2_WHITE
|| broken( rop
== def_rop
),
104 "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
105 SetROP2( old_hdc
, def_rop
);
108 ok( rop
== def_rop
, "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
110 while (i
> 0) ReleaseDC( hwnd_cache
, hdcs
[--i
] );
114 hdc
= GetDC( hwnd_owndc
);
115 SetROP2( hdc
, R2_WHITE
);
116 rop
= GetROP2( hdc
);
117 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
120 ReleaseDC( hwnd_owndc
, hdc
);
121 hdc
= GetDC( hwnd_owndc
);
122 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
123 rop
= GetROP2( hdc
);
124 ok( rop
== R2_WHITE
, "wrong ROP2 %d after release\n", rop
);
125 ReleaseDC( hwnd_owndc
, hdc
);
126 rop
= GetROP2( hdc
);
127 ok( rop
== R2_WHITE
, "wrong ROP2 %d after second release\n", rop
);
131 hdc
= GetDC( hwnd_classdc
);
132 SetROP2( hdc
, R2_WHITE
);
133 rop
= GetROP2( hdc
);
134 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
137 ReleaseDC( hwnd_classdc
, hdc
);
138 hdc
= GetDC( hwnd_classdc
);
139 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
140 rop
= GetROP2( hdc
);
141 ok( rop
== R2_WHITE
, "wrong ROP2 %d after release\n", rop
);
142 ReleaseDC( hwnd_classdc
, hdc
);
143 rop
= GetROP2( hdc
);
144 ok( rop
== R2_WHITE
, "wrong ROP2 %d after second release\n", rop
);
146 /* test class DC with 2 windows */
148 old_hdc
= GetDC( hwnd_classdc
);
149 SetROP2( old_hdc
, R2_BLACK
);
150 hdc
= GetDC( hwnd_classdc2
);
151 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
152 rop
= GetROP2( hdc
);
153 ok( rop
== R2_BLACK
, "wrong ROP2 %d for other window\n", rop
);
154 ReleaseDC( hwnd_classdc
, old_hdc
);
155 ReleaseDC( hwnd_classdc
, hdc
);
156 rop
= GetROP2( hdc
);
157 ok( rop
== R2_BLACK
, "wrong ROP2 %d after release\n", rop
);
161 /* test behavior with various invalid parameters */
162 static void test_parameters(void)
166 hdc
= GetDC( hwnd_cache
);
167 ok( ReleaseDC( hwnd_owndc
, hdc
), "ReleaseDC with wrong window should succeed\n" );
169 hdc
= GetDC( hwnd_cache
);
170 ok( !ReleaseDC( hwnd_cache
, 0 ), "ReleaseDC with wrong HDC should fail\n" );
171 ok( ReleaseDC( hwnd_cache
, hdc
), "correct ReleaseDC should succeed\n" );
172 ok( !ReleaseDC( hwnd_cache
, hdc
), "second ReleaseDC should fail\n" );
174 hdc
= GetDC( hwnd_owndc
);
175 ok( ReleaseDC( hwnd_cache
, hdc
), "ReleaseDC with wrong window should succeed\n" );
176 hdc
= GetDC( hwnd_owndc
);
177 ok( ReleaseDC( hwnd_owndc
, hdc
), "correct ReleaseDC should succeed\n" );
178 ok( ReleaseDC( hwnd_owndc
, hdc
), "second ReleaseDC should succeed\n" );
180 hdc
= GetDC( hwnd_classdc
);
181 ok( ReleaseDC( hwnd_cache
, hdc
), "ReleaseDC with wrong window should succeed\n" );
182 hdc
= GetDC( hwnd_classdc
);
183 ok( ReleaseDC( hwnd_classdc
, hdc
), "correct ReleaseDC should succeed\n" );
184 ok( ReleaseDC( hwnd_classdc
, hdc
), "second ReleaseDC should succeed\n" );
188 static void test_dc_visrgn(void)
196 SetRect( &rect
, 10, 10, 20, 20 );
197 MapWindowPoints( hwnd_cache
, 0, (POINT
*)&rect
, 2 );
198 hrgn
= CreateRectRgnIndirect( &rect
);
199 hdc
= GetDCEx( hwnd_cache
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
200 SetRectEmpty( &rect
);
201 GetClipBox( hdc
, &rect
);
202 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
203 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
204 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
205 ReleaseDC( hwnd_cache
, hdc
);
206 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
208 /* cache DC with NORESETATTRS */
210 SetRect( &rect
, 10, 10, 20, 20 );
211 MapWindowPoints( hwnd_cache
, 0, (POINT
*)&rect
, 2 );
212 hrgn
= CreateRectRgnIndirect( &rect
);
213 hdc
= GetDCEx( hwnd_cache
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_NORESETATTRS
);
214 SetRectEmpty( &rect
);
215 GetClipBox( hdc
, &rect
);
216 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
217 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
218 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
219 ReleaseDC( hwnd_cache
, hdc
);
220 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
221 hdc
= GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
222 SetRectEmpty( &rect
);
223 GetClipBox( hdc
, &rect
);
224 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
225 "clip box should have been reset %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
226 ReleaseDC( hwnd_cache
, hdc
);
230 SetRect( &rect
, 10, 10, 20, 20 );
231 MapWindowPoints( hwnd_owndc
, 0, (POINT
*)&rect
, 2 );
232 hrgn
= CreateRectRgnIndirect( &rect
);
233 hdc
= GetDCEx( hwnd_owndc
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
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 %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
238 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
239 ReleaseDC( hwnd_owndc
, hdc
);
240 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
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 %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
245 hdc
= GetDCEx( hwnd_owndc
, 0, DCX_USESTYLE
);
246 SetRectEmpty( &rect
);
247 GetClipBox( hdc
, &rect
);
248 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
249 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
250 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
251 ReleaseDC( hwnd_owndc
, hdc
);
252 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
254 SetRect( &rect
, 20, 20, 30, 30 );
255 MapWindowPoints( hwnd_owndc
, 0, (POINT
*)&rect
, 2 );
256 hrgn2
= CreateRectRgnIndirect( &rect
);
257 hdc
= GetDCEx( hwnd_owndc
, hrgn2
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
258 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
259 SetRectEmpty( &rect
);
260 GetClipBox( hdc
, &rect
);
261 ok( rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30,
262 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
263 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
264 ReleaseDC( hwnd_owndc
, hdc
);
265 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
266 hdc
= GetDCEx( hwnd_owndc
, 0, DCX_EXCLUDERGN
| DCX_USESTYLE
);
267 ok( GetRgnBox( hrgn2
, &rect
) == ERROR
, "region must no longer be valid\n" );
268 SetRectEmpty( &rect
);
269 GetClipBox( hdc
, &rect
);
270 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
271 "clip box should have been reset %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
272 ReleaseDC( hwnd_owndc
, hdc
);
276 SetRect( &rect
, 10, 10, 20, 20 );
277 MapWindowPoints( hwnd_classdc
, 0, (POINT
*)&rect
, 2 );
278 hrgn
= CreateRectRgnIndirect( &rect
);
279 hdc
= GetDCEx( hwnd_classdc
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
280 SetRectEmpty( &rect
);
281 GetClipBox( hdc
, &rect
);
282 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
283 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
284 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
285 ReleaseDC( hwnd_classdc
, hdc
);
286 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
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 %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
292 hdc
= GetDCEx( hwnd_classdc
, 0, DCX_USESTYLE
);
293 SetRectEmpty( &rect
);
294 GetClipBox( hdc
, &rect
);
295 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
296 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
297 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
298 ReleaseDC( hwnd_classdc
, hdc
);
299 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
301 SetRect( &rect
, 20, 20, 30, 30 );
302 MapWindowPoints( hwnd_classdc
, 0, (POINT
*)&rect
, 2 );
303 hrgn2
= CreateRectRgnIndirect( &rect
);
304 hdc
= GetDCEx( hwnd_classdc
, hrgn2
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
305 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
306 SetRectEmpty( &rect
);
307 GetClipBox( hdc
, &rect
);
308 ok( rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30,
309 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
310 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
313 hdc
= GetDCEx( hwnd_classdc2
, 0, DCX_USESTYLE
);
314 ok( old_hdc
== hdc
, "did not get the same hdc %p/%p\n", old_hdc
, hdc
);
315 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
316 SetRectEmpty( &rect
);
317 GetClipBox( hdc
, &rect
);
318 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
319 "clip box should have been reset %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
320 ReleaseDC( hwnd_classdc2
, hdc
);
321 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
322 hdc
= GetDCEx( hwnd_classdc2
, 0, DCX_EXCLUDERGN
| DCX_USESTYLE
);
323 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
324 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
325 "clip box must have been reset %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
326 ReleaseDC( hwnd_classdc2
, hdc
);
330 /* test various BeginPaint/EndPaint behaviors */
331 static void test_begin_paint(void)
339 /* clear update region */
340 RedrawWindow( hwnd_cache
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
341 SetRect( &rect
, 10, 10, 20, 20 );
342 RedrawWindow( hwnd_cache
, &rect
, 0, RDW_INVALIDATE
);
343 hdc
= BeginPaint( hwnd_cache
, &ps
);
344 SetRectEmpty( &rect
);
345 GetClipBox( hdc
, &rect
);
346 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
347 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
348 EndPaint( hwnd_cache
, &ps
);
352 RedrawWindow( hwnd_owndc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
353 SetRect( &rect
, 10, 10, 20, 20 );
354 RedrawWindow( hwnd_owndc
, &rect
, 0, RDW_INVALIDATE
);
355 hdc
= BeginPaint( hwnd_owndc
, &ps
);
356 SetRectEmpty( &rect
);
357 GetClipBox( hdc
, &rect
);
358 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
359 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
360 ReleaseDC( hwnd_owndc
, hdc
);
361 SetRectEmpty( &rect
);
362 GetClipBox( hdc
, &rect
);
363 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
364 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
365 ok( GetDC( hwnd_owndc
) == hdc
, "got different hdc\n" );
366 SetRectEmpty( &rect
);
367 GetClipBox( hdc
, &rect
);
368 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
369 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
370 EndPaint( hwnd_owndc
, &ps
);
371 SetRectEmpty( &rect
);
372 GetClipBox( hdc
, &rect
);
373 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
374 "clip box should have been reset %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
375 RedrawWindow( hwnd_owndc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
376 SetRect( &rect
, 10, 10, 20, 20 );
377 RedrawWindow( hwnd_owndc
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
);
378 ok( GetDC( hwnd_owndc
) == hdc
, "got different hdc\n" );
379 SetRectEmpty( &rect
);
380 GetClipBox( hdc
, &rect
);
381 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
382 "clip box should be the whole window %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
383 RedrawWindow( hwnd_owndc
, NULL
, 0, RDW_ERASENOW
);
384 SetRectEmpty( &rect
);
385 GetClipBox( hdc
, &rect
);
386 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
387 "clip box should still be the whole window %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
391 RedrawWindow( hwnd_classdc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
392 SetRect( &rect
, 10, 10, 20, 20 );
393 RedrawWindow( hwnd_classdc
, &rect
, 0, RDW_INVALIDATE
);
394 hdc
= BeginPaint( hwnd_classdc
, &ps
);
395 SetRectEmpty( &rect
);
396 GetClipBox( hdc
, &rect
);
397 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
398 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
401 hdc
= GetDC( hwnd_classdc2
);
402 ok( old_hdc
== hdc
, "did not get the same hdc %p/%p\n", old_hdc
, hdc
);
403 SetRectEmpty( &rect
);
404 GetClipBox( hdc
, &rect
);
405 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
406 "clip box should have been reset %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
409 /* test ScrollWindow with window DCs */
410 static void test_scroll_window(void)
416 /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
418 UpdateWindow( hwnd_owndc
);
419 SetRect( &clip
, 25, 25, 50, 50 );
420 ScrollWindow( hwnd_owndc
, -5, -10, NULL
, &clip
);
421 hdc
= BeginPaint( hwnd_owndc
, &ps
);
422 SetRectEmpty( &rect
);
423 GetClipBox( hdc
, &rect
);
424 ok( rect
.left
>= 25 && rect
.top
>= 25 && rect
.right
<= 50 && rect
.bottom
<= 50,
425 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
426 EndPaint( hwnd_owndc
, &ps
);
428 SetViewportExtEx( hdc
, 2, 3, NULL
);
429 SetViewportOrgEx( hdc
, 30, 20, NULL
);
431 ScrollWindow( hwnd_owndc
, -5, -10, NULL
, &clip
);
432 hdc
= BeginPaint( hwnd_owndc
, &ps
);
433 SetRectEmpty( &rect
);
434 GetClipBox( hdc
, &rect
);
435 ok( rect
.left
>= 25 && rect
.top
>= 25 && rect
.right
<= 50 && rect
.bottom
<= 50,
436 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
437 EndPaint( hwnd_owndc
, &ps
);
439 ScrollWindowEx( hwnd_owndc
, -5, -10, NULL
, &clip
, 0, NULL
, SW_INVALIDATE
| SW_ERASE
);
440 hdc
= BeginPaint( hwnd_owndc
, &ps
);
441 SetRectEmpty( &rect
);
442 GetClipBox( hdc
, &rect
);
443 ok( rect
.left
>= -5 && rect
.top
>= 5 && rect
.right
<= 20 && rect
.bottom
<= 30,
444 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
445 EndPaint( hwnd_owndc
, &ps
);
447 SetViewportExtEx( hdc
, 1, 1, NULL
);
448 SetViewportOrgEx( hdc
, 0, 0, NULL
);
450 ScrollWindowEx( hwnd_owndc
, -5, -10, NULL
, &clip
, 0, NULL
, SW_INVALIDATE
| SW_ERASE
);
451 hdc
= BeginPaint( hwnd_owndc
, &ps
);
452 SetRectEmpty( &rect
);
453 GetClipBox( hdc
, &rect
);
454 ok( rect
.left
>= 25 && rect
.top
>= 25 && rect
.right
<= 50 && rect
.bottom
<= 50,
455 "invalid clip box %d,%d-%d,%d\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
456 EndPaint( hwnd_owndc
, &ps
);
459 static void test_invisible_create(void)
461 HWND hwnd_owndc
= CreateWindowA("owndc_class", NULL
, WS_OVERLAPPED
,
463 0, 0, GetModuleHandleA(0), NULL
);
466 dc1
= GetDC(hwnd_owndc
);
467 dc2
= GetDC(hwnd_owndc
);
469 ok(dc1
== dc2
, "expected owndc dcs to match\n");
471 ReleaseDC(hwnd_owndc
, dc2
);
472 ReleaseDC(hwnd_owndc
, dc1
);
473 DestroyWindow(hwnd_owndc
);
476 static void test_dc_layout(void)
478 DWORD (WINAPI
*pSetLayout
)(HDC hdc
, DWORD layout
);
479 DWORD (WINAPI
*pGetLayout
)(HDC hdc
);
480 HWND hwnd_cache_rtl
, hwnd_owndc_rtl
, hwnd_classdc_rtl
, hwnd_classdc2_rtl
;
483 HMODULE mod
= GetModuleHandleA("gdi32.dll");
485 pGetLayout
= (void *)GetProcAddress( mod
, "GetLayout" );
486 pSetLayout
= (void *)GetProcAddress( mod
, "SetLayout" );
487 if (!pGetLayout
|| !pSetLayout
)
489 win_skip( "Don't have SetLayout\n" );
493 hdc
= GetDC( hwnd_cache
);
494 pSetLayout( hdc
, LAYOUT_RTL
);
495 layout
= pGetLayout( hdc
);
496 ReleaseDC( hwnd_cache
, hdc
);
499 win_skip( "SetLayout not supported\n" );
503 hwnd_cache_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "cache_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
504 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
505 hwnd_owndc_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "owndc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
506 0, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
507 hwnd_classdc_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
508 200, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
509 hwnd_classdc2_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
510 200, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
511 hdc
= GetDC( hwnd_cache_rtl
);
512 layout
= pGetLayout( hdc
);
514 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
515 pSetLayout( hdc
, 0 );
516 ReleaseDC( hwnd_cache_rtl
, hdc
);
517 hdc
= GetDC( hwnd_owndc_rtl
);
518 layout
= pGetLayout( hdc
);
519 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
520 ReleaseDC( hwnd_cache_rtl
, hdc
);
522 hdc
= GetDC( hwnd_cache
);
523 layout
= pGetLayout( hdc
);
524 ok( layout
== 0, "wrong layout %x\n", layout
);
525 ReleaseDC( hwnd_cache
, hdc
);
527 hdc
= GetDC( hwnd_owndc_rtl
);
528 layout
= pGetLayout( hdc
);
529 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
530 pSetLayout( hdc
, 0 );
531 ReleaseDC( hwnd_owndc_rtl
, hdc
);
532 hdc
= GetDC( hwnd_owndc_rtl
);
533 layout
= pGetLayout( hdc
);
534 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
535 ReleaseDC( hwnd_owndc_rtl
, hdc
);
537 hdc
= GetDC( hwnd_classdc_rtl
);
538 layout
= pGetLayout( hdc
);
539 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
540 pSetLayout( hdc
, 0 );
541 ReleaseDC( hwnd_classdc_rtl
, hdc
);
542 hdc
= GetDC( hwnd_classdc2_rtl
);
543 layout
= pGetLayout( hdc
);
544 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
545 ReleaseDC( hwnd_classdc2_rtl
, hdc
);
546 hdc
= GetDC( hwnd_classdc
);
547 layout
= pGetLayout( hdc
);
548 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
549 ReleaseDC( hwnd_classdc_rtl
, hdc
);
551 DestroyWindow(hwnd_classdc2_rtl
);
552 DestroyWindow(hwnd_classdc_rtl
);
553 DestroyWindow(hwnd_owndc_rtl
);
554 DestroyWindow(hwnd_cache_rtl
);
557 static void test_destroyed_window(void)
561 dc
= GetDCEx(hwnd_cache
, 0, DCX_USESTYLE
);
562 ok(!dc
, "Got a non-NULL DC (%p) for a destroyed window.\n", dc
);
564 dc
= GetDCEx(hwnd_owndc
, 0, DCX_USESTYLE
);
565 ok(!dc
, "Got a non-NULL DC (%p) for a destroyed window.\n", dc
);
567 dc
= GetDCEx(hwnd_classdc
, 0, DCX_USESTYLE
);
568 ok(!dc
, "Got a non-NULL DC (%p) for a destroyed window.\n", dc
);
570 dc
= GetDCEx(hwnd_classdc2
, 0, DCX_USESTYLE
);
571 ok(!dc
, "Got a non-NULL DC (%p) for a destroyed window.\n", dc
);
578 cls
.style
= CS_DBLCLKS
;
579 cls
.lpfnWndProc
= DefWindowProcA
;
582 cls
.hInstance
= GetModuleHandleA(0);
584 cls
.hCursor
= LoadCursorA(0, IDC_ARROW
);
585 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
586 cls
.lpszMenuName
= NULL
;
587 cls
.lpszClassName
= "cache_class";
588 RegisterClassA(&cls
);
589 cls
.style
= CS_DBLCLKS
| CS_OWNDC
;
590 cls
.lpszClassName
= "owndc_class";
591 RegisterClassA(&cls
);
592 cls
.style
= CS_DBLCLKS
| CS_CLASSDC
;
593 cls
.lpszClassName
= "classdc_class";
594 RegisterClassA(&cls
);
596 hwnd_cache
= CreateWindowA("cache_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
598 0, 0, GetModuleHandleA(0), NULL
);
599 hwnd_owndc
= CreateWindowA("owndc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
601 0, 0, GetModuleHandleA(0), NULL
);
602 hwnd_classdc
= CreateWindowA("classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
604 0, 0, GetModuleHandleA(0), NULL
);
605 hwnd_classdc2
= CreateWindowA("classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
607 0, 0, GetModuleHandleA(0), NULL
);
608 test_dc_attributes();
612 test_scroll_window();
613 test_invisible_create();
616 DestroyWindow(hwnd_classdc2
);
617 DestroyWindow(hwnd_classdc
);
618 DestroyWindow(hwnd_owndc
);
619 DestroyWindow(hwnd_cache
);
621 test_destroyed_window();