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
24 #define DCX_USESTYLE 0x00010000
27 static HWND hwnd_cache
, hwnd_owndc
, hwnd_classdc
, hwnd_classdc2
, hwnd_parent
, hwnd_parentdc
;
29 /* test behavior of DC attributes with various GetDC/ReleaseDC combinations */
30 static void test_dc_attributes(void)
39 hdc
= GetDC( hwnd_cache
);
40 def_rop
= GetROP2( hdc
);
42 SetROP2( hdc
, R2_WHITE
);
44 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
46 ReleaseDC( hwnd_cache
, hdc
);
47 hdc
= GetDC( hwnd_cache
);
49 ok( rop
== def_rop
, "wrong ROP2 %d after release\n", rop
);
50 SetROP2( hdc
, R2_WHITE
);
51 ReleaseDC( hwnd_cache
, hdc
);
55 for (i
= 0; i
< 20; i
++)
57 hdc
= hdcs
[i
] = GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
60 ok( rop
== def_rop
, "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
64 SetROP2( hdc
, R2_WHITE
);
69 trace( "hdc %p not found in cache using %p\n", old_hdc
, hdcs
[0] );
71 SetROP2( old_hdc
, R2_WHITE
);
73 while (i
> 0) ReleaseDC( hwnd_cache
, hdcs
[--i
] );
75 for (i
= 0; i
< 20; i
++)
77 hdc
= hdcs
[i
] = GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
81 ok( rop
== R2_WHITE
|| broken( rop
== def_rop
), /* win9x doesn't support DCX_NORESETATTRS */
82 "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
84 ok( rop
== def_rop
, "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
86 while (i
> 0) ReleaseDC( hwnd_cache
, hdcs
[--i
] );
88 for (i
= 0; i
< 20; i
++)
90 hdc
= hdcs
[i
] = GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
);
95 ok( rop
== R2_WHITE
|| broken( rop
== def_rop
),
96 "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
97 SetROP2( old_hdc
, def_rop
);
100 ok( rop
== def_rop
, "wrong ROP2 %d after release %p/%p\n", rop
, old_hdc
, hdc
);
102 while (i
> 0) ReleaseDC( hwnd_cache
, hdcs
[--i
] );
104 /* Released cache DCs are 'disabled' */
105 rop
= SetROP2( old_hdc
, R2_BLACK
);
106 ok( rop
== 0, "got %d\n", rop
);
107 rop
= GetROP2( old_hdc
);
108 ok( rop
== 0, "got %d\n", rop
);
112 hdc
= GetDC( hwnd_owndc
);
113 SetROP2( hdc
, R2_WHITE
);
114 rop
= GetROP2( hdc
);
115 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
118 ReleaseDC( hwnd_owndc
, hdc
);
119 hdc
= GetDC( hwnd_owndc
);
120 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
121 rop
= GetROP2( hdc
);
122 ok( rop
== R2_WHITE
, "wrong ROP2 %d after release\n", rop
);
123 ReleaseDC( hwnd_owndc
, hdc
);
124 rop
= GetROP2( hdc
);
125 ok( rop
== R2_WHITE
, "wrong ROP2 %d after second release\n", rop
);
129 hdc
= GetDC( hwnd_classdc
);
130 SetROP2( hdc
, R2_WHITE
);
131 rop
= GetROP2( hdc
);
132 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
135 ReleaseDC( hwnd_classdc
, hdc
);
136 hdc
= GetDC( hwnd_classdc
);
137 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
138 rop
= GetROP2( hdc
);
139 ok( rop
== R2_WHITE
, "wrong ROP2 %d after release\n", rop
);
140 ReleaseDC( hwnd_classdc
, hdc
);
141 rop
= GetROP2( hdc
);
142 ok( rop
== R2_WHITE
, "wrong ROP2 %d after second release\n", rop
);
144 /* test class DC with 2 windows */
146 old_hdc
= GetDC( hwnd_classdc
);
147 SetROP2( old_hdc
, R2_BLACK
);
148 hdc
= GetDC( hwnd_classdc2
);
149 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
150 rop
= GetROP2( hdc
);
151 ok( rop
== R2_BLACK
, "wrong ROP2 %d for other window\n", rop
);
152 ReleaseDC( hwnd_classdc
, old_hdc
);
153 ReleaseDC( hwnd_classdc
, hdc
);
154 rop
= GetROP2( hdc
);
155 ok( rop
== R2_BLACK
, "wrong ROP2 %d after release\n", rop
);
159 /* test behavior with various invalid parameters */
160 static void test_parameters(void)
164 hdc
= GetDC( hwnd_cache
);
165 ok( ReleaseDC( hwnd_owndc
, hdc
), "ReleaseDC with wrong window should succeed\n" );
167 hdc
= GetDC( hwnd_cache
);
168 ok( !ReleaseDC( hwnd_cache
, 0 ), "ReleaseDC with wrong HDC should fail\n" );
169 ok( ReleaseDC( hwnd_cache
, hdc
), "correct ReleaseDC should succeed\n" );
170 ok( !ReleaseDC( hwnd_cache
, hdc
), "second ReleaseDC should fail\n" );
172 hdc
= GetDC( hwnd_owndc
);
173 ok( ReleaseDC( hwnd_cache
, hdc
), "ReleaseDC with wrong window should succeed\n" );
174 hdc
= GetDC( hwnd_owndc
);
175 ok( ReleaseDC( hwnd_owndc
, hdc
), "correct ReleaseDC should succeed\n" );
176 ok( ReleaseDC( hwnd_owndc
, hdc
), "second ReleaseDC should succeed\n" );
178 hdc
= GetDC( hwnd_classdc
);
179 ok( ReleaseDC( hwnd_cache
, hdc
), "ReleaseDC with wrong window should succeed\n" );
180 hdc
= GetDC( hwnd_classdc
);
181 ok( ReleaseDC( hwnd_classdc
, hdc
), "correct ReleaseDC should succeed\n" );
182 ok( ReleaseDC( hwnd_classdc
, hdc
), "second ReleaseDC should succeed\n" );
186 static void test_dc_visrgn(void)
190 RECT rect
, parent_rect
;
194 SetRect( &rect
, 10, 10, 20, 20 );
195 MapWindowPoints( hwnd_cache
, 0, (POINT
*)&rect
, 2 );
196 hrgn
= CreateRectRgnIndirect( &rect
);
197 hdc
= GetDCEx( hwnd_cache
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
198 SetRectEmpty( &rect
);
199 GetClipBox( hdc
, &rect
);
200 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
201 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
202 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
203 ReleaseDC( hwnd_cache
, hdc
);
204 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
206 /* cache DC with NORESETATTRS */
208 SetRect( &rect
, 10, 10, 20, 20 );
209 MapWindowPoints( hwnd_cache
, 0, (POINT
*)&rect
, 2 );
210 hrgn
= CreateRectRgnIndirect( &rect
);
211 hdc
= GetDCEx( hwnd_cache
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_NORESETATTRS
);
212 SetRectEmpty( &rect
);
213 GetClipBox( hdc
, &rect
);
214 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
215 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
216 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
217 ReleaseDC( hwnd_cache
, hdc
);
218 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
219 hdc
= GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
220 SetRectEmpty( &rect
);
221 GetClipBox( hdc
, &rect
);
222 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
223 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect
));
224 ReleaseDC( hwnd_cache
, hdc
);
228 SetRect( &rect
, 10, 10, 20, 20 );
229 MapWindowPoints( hwnd_owndc
, 0, (POINT
*)&rect
, 2 );
230 hrgn
= CreateRectRgnIndirect( &rect
);
231 hdc
= GetDCEx( hwnd_owndc
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
232 SetRectEmpty( &rect
);
233 GetClipBox( hdc
, &rect
);
234 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
235 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
236 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
237 ReleaseDC( hwnd_owndc
, hdc
);
238 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
239 SetRectEmpty( &rect
);
240 GetClipBox( hdc
, &rect
);
241 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
242 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
243 hdc
= GetDCEx( hwnd_owndc
, 0, DCX_USESTYLE
);
244 SetRectEmpty( &rect
);
245 GetClipBox( hdc
, &rect
);
246 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
247 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
248 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
249 ReleaseDC( hwnd_owndc
, hdc
);
250 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
252 SetRect( &rect
, 20, 20, 30, 30 );
253 MapWindowPoints( hwnd_owndc
, 0, (POINT
*)&rect
, 2 );
254 hrgn2
= CreateRectRgnIndirect( &rect
);
255 hdc
= GetDCEx( hwnd_owndc
, hrgn2
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
256 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
257 SetRectEmpty( &rect
);
258 GetClipBox( hdc
, &rect
);
259 ok( rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30,
260 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
261 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
262 ReleaseDC( hwnd_owndc
, hdc
);
263 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
264 hdc
= GetDCEx( hwnd_owndc
, 0, DCX_EXCLUDERGN
| DCX_USESTYLE
);
265 ok( GetRgnBox( hrgn2
, &rect
) == ERROR
, "region must no longer be valid\n" );
266 SetRectEmpty( &rect
);
267 GetClipBox( hdc
, &rect
);
268 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
269 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect
));
270 ReleaseDC( hwnd_owndc
, hdc
);
274 SetRect( &rect
, 10, 10, 20, 20 );
275 MapWindowPoints( hwnd_classdc
, 0, (POINT
*)&rect
, 2 );
276 hrgn
= CreateRectRgnIndirect( &rect
);
277 hdc
= GetDCEx( hwnd_classdc
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
278 SetRectEmpty( &rect
);
279 GetClipBox( hdc
, &rect
);
280 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
281 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
282 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
283 ReleaseDC( hwnd_classdc
, hdc
);
284 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
285 SetRectEmpty( &rect
);
286 GetClipBox( hdc
, &rect
);
287 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
288 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
290 hdc
= GetDCEx( hwnd_classdc
, 0, DCX_USESTYLE
);
291 SetRectEmpty( &rect
);
292 GetClipBox( hdc
, &rect
);
293 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
294 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
295 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
296 ReleaseDC( hwnd_classdc
, hdc
);
297 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
299 SetRect( &rect
, 20, 20, 30, 30 );
300 MapWindowPoints( hwnd_classdc
, 0, (POINT
*)&rect
, 2 );
301 hrgn2
= CreateRectRgnIndirect( &rect
);
302 hdc
= GetDCEx( hwnd_classdc
, hrgn2
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
303 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
304 SetRectEmpty( &rect
);
305 GetClipBox( hdc
, &rect
);
306 ok( rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30,
307 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
308 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
311 hdc
= GetDCEx( hwnd_classdc2
, 0, DCX_USESTYLE
);
312 ok( old_hdc
== hdc
, "did not get the same hdc %p/%p\n", old_hdc
, hdc
);
313 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
314 SetRectEmpty( &rect
);
315 GetClipBox( hdc
, &rect
);
316 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
317 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect
));
318 ReleaseDC( hwnd_classdc2
, hdc
);
319 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
320 hdc
= GetDCEx( hwnd_classdc2
, 0, DCX_EXCLUDERGN
| DCX_USESTYLE
);
321 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
322 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
323 "clip box must have been reset %s\n", wine_dbgstr_rect( &rect
));
324 ReleaseDC( hwnd_classdc2
, hdc
);
327 hdc
= GetDC( hwnd_parentdc
);
328 GetClipBox( hdc
, &rect
);
329 ReleaseDC( hwnd_parentdc
, hdc
);
331 hdc
= GetDC( hwnd_parent
);
332 GetClipBox( hdc
, &parent_rect
);
333 ReleaseDC( hwnd_parent
, hdc
);
335 ok( EqualRect( &rect
, &parent_rect
), "rect = %s, expected %s\n", wine_dbgstr_rect( &rect
),
336 wine_dbgstr_rect( &parent_rect
));
340 /* test various BeginPaint/EndPaint behaviors */
341 static void test_begin_paint(void)
344 RECT rect
, parent_rect
;
350 /* clear update region */
351 RedrawWindow( hwnd_cache
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
352 SetRect( &rect
, 10, 10, 20, 20 );
353 RedrawWindow( hwnd_cache
, &rect
, 0, RDW_INVALIDATE
);
354 hdc
= BeginPaint( hwnd_cache
, &ps
);
355 SetRectEmpty( &rect
);
356 GetClipBox( hdc
, &rect
);
357 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
358 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
359 EndPaint( hwnd_cache
, &ps
);
363 RedrawWindow( hwnd_owndc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
364 SetRect( &rect
, 10, 10, 20, 20 );
365 RedrawWindow( hwnd_owndc
, &rect
, 0, RDW_INVALIDATE
);
366 hdc
= BeginPaint( hwnd_owndc
, &ps
);
367 SetRectEmpty( &rect
);
368 GetClipBox( hdc
, &rect
);
369 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
370 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
371 ReleaseDC( hwnd_owndc
, hdc
);
372 SetRectEmpty( &rect
);
373 GetClipBox( hdc
, &rect
);
374 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
375 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
376 ok( GetDC( hwnd_owndc
) == hdc
, "got different hdc\n" );
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_owndc
, &ps
);
382 SetRectEmpty( &rect
);
383 GetClipBox( hdc
, &rect
);
384 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
385 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect
));
386 RedrawWindow( hwnd_owndc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
387 SetRect( &rect
, 10, 10, 20, 20 );
388 RedrawWindow( hwnd_owndc
, &rect
, 0, RDW_INVALIDATE
|RDW_ERASE
);
389 ok( GetDC( hwnd_owndc
) == hdc
, "got different hdc\n" );
390 SetRectEmpty( &rect
);
391 GetClipBox( hdc
, &rect
);
392 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
393 "clip box should be the whole window %s\n", wine_dbgstr_rect( &rect
));
394 RedrawWindow( hwnd_owndc
, NULL
, 0, RDW_ERASENOW
);
395 SetRectEmpty( &rect
);
396 GetClipBox( hdc
, &rect
);
397 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
398 "clip box should still be the whole window %s\n", wine_dbgstr_rect( &rect
));
402 RedrawWindow( hwnd_classdc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
403 SetRect( &rect
, 10, 10, 20, 20 );
404 RedrawWindow( hwnd_classdc
, &rect
, 0, RDW_INVALIDATE
);
405 hdc
= BeginPaint( hwnd_classdc
, &ps
);
406 SetRectEmpty( &rect
);
407 GetClipBox( hdc
, &rect
);
408 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
409 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
412 hdc
= GetDC( hwnd_classdc2
);
413 ok( old_hdc
== hdc
, "did not get the same hdc %p/%p\n", old_hdc
, hdc
);
414 SetRectEmpty( &rect
);
415 GetClipBox( hdc
, &rect
);
416 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
417 "clip box should have been reset %s\n", wine_dbgstr_rect( &rect
));
418 ReleaseDC( hwnd_classdc2
, hdc
);
419 EndPaint( hwnd_classdc
, &ps
);
422 RedrawWindow( hwnd_parent
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
423 RedrawWindow( hwnd_parentdc
, NULL
, 0, RDW_INVALIDATE
);
424 hdc
= BeginPaint( hwnd_parentdc
, &ps
);
425 GetClipBox( hdc
, &rect
);
426 cr
= SetPixel( hdc
, 10, 10, RGB(255, 0, 0) );
427 ok( cr
!= -1, "error drawing outside of window client area\n" );
428 EndPaint( hwnd_parentdc
, &ps
);
429 GetClientRect( hwnd_parent
, &parent_rect
);
431 ok( rect
.left
== parent_rect
.left
, "rect.left = %d, expected %d\n", rect
.left
, parent_rect
.left
);
432 ok( rect
.top
== parent_rect
.top
, "rect.top = %d, expected %d\n", rect
.top
, parent_rect
.top
);
433 todo_wine
ok( rect
.right
== parent_rect
.right
, "rect.right = %d, expected %d\n", rect
.right
, parent_rect
.right
);
434 todo_wine
ok( rect
.bottom
== parent_rect
.bottom
, "rect.bottom = %d, expected %d\n", rect
.bottom
, parent_rect
.bottom
);
436 hdc
= GetDC( hwnd_parent
);
437 todo_wine
ok( GetPixel( hdc
, 10, 10 ) == cr
, "error drawing outside of window client area\n" );
438 ReleaseDC( hwnd_parent
, hdc
);
441 /* test ScrollWindow with window DCs */
442 static void test_scroll_window(void)
448 /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
450 UpdateWindow( hwnd_owndc
);
451 SetRect( &clip
, 25, 25, 50, 50 );
452 ScrollWindow( hwnd_owndc
, -5, -10, NULL
, &clip
);
453 hdc
= BeginPaint( hwnd_owndc
, &ps
);
454 SetRectEmpty( &rect
);
455 GetClipBox( hdc
, &rect
);
456 ok( rect
.left
>= 25 && rect
.top
>= 25 && rect
.right
<= 50 && rect
.bottom
<= 50,
457 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
458 EndPaint( hwnd_owndc
, &ps
);
460 SetViewportExtEx( hdc
, 2, 3, NULL
);
461 SetViewportOrgEx( hdc
, 30, 20, NULL
);
463 ScrollWindow( hwnd_owndc
, -5, -10, NULL
, &clip
);
464 hdc
= BeginPaint( hwnd_owndc
, &ps
);
465 SetRectEmpty( &rect
);
466 GetClipBox( hdc
, &rect
);
467 ok( rect
.left
>= 25 && rect
.top
>= 25 && rect
.right
<= 50 && rect
.bottom
<= 50,
468 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
469 EndPaint( hwnd_owndc
, &ps
);
471 ScrollWindowEx( hwnd_owndc
, -5, -10, NULL
, &clip
, 0, NULL
, SW_INVALIDATE
| SW_ERASE
);
472 hdc
= BeginPaint( hwnd_owndc
, &ps
);
473 SetRectEmpty( &rect
);
474 GetClipBox( hdc
, &rect
);
475 ok( rect
.left
>= -5 && rect
.top
>= 5 && rect
.right
<= 20 && rect
.bottom
<= 30,
476 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
477 EndPaint( hwnd_owndc
, &ps
);
479 SetViewportExtEx( hdc
, 1, 1, NULL
);
480 SetViewportOrgEx( hdc
, 0, 0, NULL
);
482 ScrollWindowEx( hwnd_owndc
, -5, -10, NULL
, &clip
, 0, NULL
, SW_INVALIDATE
| SW_ERASE
);
483 hdc
= BeginPaint( hwnd_owndc
, &ps
);
484 SetRectEmpty( &rect
);
485 GetClipBox( hdc
, &rect
);
486 ok( rect
.left
>= 25 && rect
.top
>= 25 && rect
.right
<= 50 && rect
.bottom
<= 50,
487 "invalid clip box %s\n", wine_dbgstr_rect( &rect
));
488 EndPaint( hwnd_owndc
, &ps
);
491 static void test_invisible_create(void)
493 HWND hwnd_owndc
= CreateWindowA("owndc_class", NULL
, WS_OVERLAPPED
,
495 0, 0, GetModuleHandleA(0), NULL
);
498 dc1
= GetDC(hwnd_owndc
);
499 dc2
= GetDC(hwnd_owndc
);
501 ok(dc1
== dc2
, "expected owndc dcs to match\n");
503 ReleaseDC(hwnd_owndc
, dc2
);
504 ReleaseDC(hwnd_owndc
, dc1
);
505 DestroyWindow(hwnd_owndc
);
508 static void test_dc_layout(void)
510 DWORD (WINAPI
*pSetLayout
)(HDC hdc
, DWORD layout
);
511 DWORD (WINAPI
*pGetLayout
)(HDC hdc
);
512 HWND hwnd_cache_rtl
, hwnd_owndc_rtl
, hwnd_classdc_rtl
, hwnd_classdc2_rtl
;
515 HMODULE mod
= GetModuleHandleA("gdi32.dll");
517 pGetLayout
= (void *)GetProcAddress( mod
, "GetLayout" );
518 pSetLayout
= (void *)GetProcAddress( mod
, "SetLayout" );
519 if (!pGetLayout
|| !pSetLayout
)
521 win_skip( "Don't have SetLayout\n" );
525 hdc
= GetDC( hwnd_cache
);
526 pSetLayout( hdc
, LAYOUT_RTL
);
527 layout
= pGetLayout( hdc
);
528 ReleaseDC( hwnd_cache
, hdc
);
531 win_skip( "SetLayout not supported\n" );
535 hwnd_cache_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "cache_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
536 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
537 hwnd_owndc_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "owndc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
538 0, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
539 hwnd_classdc_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
540 200, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
541 hwnd_classdc2_rtl
= CreateWindowExA(WS_EX_LAYOUTRTL
, "classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
542 200, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL
);
543 hdc
= GetDC( hwnd_cache_rtl
);
544 layout
= pGetLayout( hdc
);
546 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
547 pSetLayout( hdc
, 0 );
548 ReleaseDC( hwnd_cache_rtl
, hdc
);
549 hdc
= GetDC( hwnd_owndc_rtl
);
550 layout
= pGetLayout( hdc
);
551 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
552 ReleaseDC( hwnd_cache_rtl
, hdc
);
554 hdc
= GetDC( hwnd_cache
);
555 layout
= pGetLayout( hdc
);
556 ok( layout
== 0, "wrong layout %x\n", layout
);
557 ReleaseDC( hwnd_cache
, hdc
);
559 hdc
= GetDC( hwnd_owndc_rtl
);
560 layout
= pGetLayout( hdc
);
561 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
562 pSetLayout( hdc
, 0 );
563 ReleaseDC( hwnd_owndc_rtl
, hdc
);
564 hdc
= GetDC( hwnd_owndc_rtl
);
565 layout
= pGetLayout( hdc
);
566 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
567 ReleaseDC( hwnd_owndc_rtl
, hdc
);
569 hdc
= GetDC( hwnd_classdc_rtl
);
570 layout
= pGetLayout( hdc
);
571 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
572 pSetLayout( hdc
, 0 );
573 ReleaseDC( hwnd_classdc_rtl
, hdc
);
574 hdc
= GetDC( hwnd_classdc2_rtl
);
575 layout
= pGetLayout( hdc
);
576 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
577 ReleaseDC( hwnd_classdc2_rtl
, hdc
);
578 hdc
= GetDC( hwnd_classdc
);
579 layout
= pGetLayout( hdc
);
580 ok( layout
== LAYOUT_RTL
, "wrong layout %x\n", layout
);
581 ReleaseDC( hwnd_classdc_rtl
, hdc
);
583 DestroyWindow(hwnd_classdc2_rtl
);
584 DestroyWindow(hwnd_classdc_rtl
);
585 DestroyWindow(hwnd_owndc_rtl
);
586 DestroyWindow(hwnd_cache_rtl
);
589 static void test_destroyed_window(void)
593 dc
= GetDCEx(hwnd_cache
, 0, DCX_USESTYLE
);
594 ok(!dc
, "Got a non-NULL DC (%p) for a destroyed window.\n", dc
);
596 dc
= GetDCEx(hwnd_owndc
, 0, DCX_USESTYLE
);
597 ok(!dc
, "Got a non-NULL DC (%p) for a destroyed window.\n", dc
);
599 dc
= GetDCEx(hwnd_classdc
, 0, DCX_USESTYLE
);
600 ok(!dc
, "Got a non-NULL DC (%p) for a destroyed window.\n", dc
);
602 dc
= GetDCEx(hwnd_classdc2
, 0, DCX_USESTYLE
);
603 ok(!dc
, "Got a non-NULL DC (%p) for a destroyed window.\n", dc
);
610 cls
.style
= CS_DBLCLKS
;
611 cls
.lpfnWndProc
= DefWindowProcA
;
614 cls
.hInstance
= GetModuleHandleA(0);
616 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
617 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
618 cls
.lpszMenuName
= NULL
;
619 cls
.lpszClassName
= "cache_class";
620 RegisterClassA(&cls
);
621 cls
.style
= CS_DBLCLKS
| CS_OWNDC
;
622 cls
.lpszClassName
= "owndc_class";
623 RegisterClassA(&cls
);
624 cls
.style
= CS_DBLCLKS
| CS_CLASSDC
;
625 cls
.lpszClassName
= "classdc_class";
626 RegisterClassA(&cls
);
627 cls
.style
= CS_PARENTDC
;
628 cls
.lpszClassName
= "parentdc_class";
629 RegisterClassA(&cls
);
631 hwnd_cache
= CreateWindowA("cache_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
633 0, 0, GetModuleHandleA(0), NULL
);
634 hwnd_owndc
= CreateWindowA("owndc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
636 0, 0, GetModuleHandleA(0), NULL
);
637 hwnd_classdc
= CreateWindowA("classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
639 0, 0, GetModuleHandleA(0), NULL
);
640 hwnd_classdc2
= CreateWindowA("classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
642 0, 0, GetModuleHandleA(0), NULL
);
643 hwnd_parent
= CreateWindowA("static", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
644 400, 0, 100, 100, 0, 0, 0, NULL
);
645 hwnd_parentdc
= CreateWindowA("parentdc_class", NULL
, WS_CHILD
| WS_VISIBLE
,
646 0, 0, 1, 1, hwnd_parent
, 0, 0, NULL
);
648 test_dc_attributes();
652 test_scroll_window();
653 test_invisible_create();
656 DestroyWindow(hwnd_parent
);
657 DestroyWindow(hwnd_classdc2
);
658 DestroyWindow(hwnd_classdc
);
659 DestroyWindow(hwnd_owndc
);
660 DestroyWindow(hwnd_cache
);
662 test_destroyed_window();