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)
43 INT i
, rop
, def_rop
, caps
;
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
) != hwnd_cache
, "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 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" );
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
);
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
);
146 hdc
= GetDC( hwnd_owndc
);
147 SetROP2( hdc
, R2_WHITE
);
148 rop
= GetROP2( hdc
);
149 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
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
);
166 hdc
= GetDC( hwnd_classdc
);
167 SetROP2( hdc
, R2_WHITE
);
168 rop
= GetROP2( hdc
);
169 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
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)
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)
233 RECT rect
, parent_rect
;
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
);
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
);
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" );
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
);
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)
387 RECT rect
, parent_rect
, client_rect
;
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
);
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
);
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
));
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
);
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)
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
,
580 0, 0, GetModuleHandleA(0), NULL
);
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
;
599 hdc
= GetDC( hwnd_cache
);
600 SetLayout( hdc
, LAYOUT_RTL
);
601 layout
= GetLayout( hdc
);
602 ReleaseDC( hwnd_cache
, hdc
);
605 win_skip( "SetLayout not supported\n" );
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
);
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
);
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
);
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)
668 dc
= GetDC( hwnd_cache
);
669 SetROP2( dc
, R2_WHITE
);
671 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
672 ok( WindowFromDC( dc
) == hwnd_cache
, "wrong window\n" );
675 DestroyWindow( hwnd_cache
);
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
);
686 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
687 ok( WindowFromDC( dc
) == hwnd_classdc
, "wrong window\n" );
690 dc
= GetDC( hwnd_classdc2
);
691 ok( old_dc
== dc
, "wrong DC\n" );
693 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
694 ok( WindowFromDC( dc
) == hwnd_classdc2
, "wrong window\n" );
695 DestroyWindow( hwnd_classdc2
);
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" );
707 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
708 ok( WindowFromDC( dc
) == hwnd_classdc
, "wrong window\n" );
709 DestroyWindow( hwnd_classdc
);
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" );
721 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
722 ok( WindowFromDC( dc
) == hwnd_owndc
, "wrong window\n" );
723 DestroyWindow( hwnd_owndc
);
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
);
739 cls
.style
= CS_DBLCLKS
;
740 cls
.lpfnWndProc
= DefWindowProcA
;
743 cls
.hInstance
= GetModuleHandleA(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
,
762 0, 0, GetModuleHandleA(0), NULL
);
763 hwnd_owndc
= CreateWindowA("owndc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
765 0, 0, GetModuleHandleA(0), NULL
);
766 hwnd_classdc
= CreateWindowA("classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
768 0, 0, GetModuleHandleA(0), NULL
);
769 hwnd_classdc2
= CreateWindowA("classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
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();
781 test_scroll_window();
782 test_invisible_create();
784 /* this should be last */
785 test_destroyed_window();