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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
34 #include "wine/test.h"
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)
46 hdc
= GetDC( hwnd_cache
);
47 def_rop
= GetROP2( hdc
);
49 SetROP2( hdc
, R2_WHITE
);
51 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
53 ReleaseDC( hwnd_cache
, hdc
);
54 hdc
= GetDC( hwnd_cache
);
56 ok( rop
== def_rop
, "wrong ROP2 %d after release\n", rop
);
57 SetROP2( hdc
, R2_WHITE
);
58 ReleaseDC( hwnd_cache
, hdc
);
60 hdc
= GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
62 /* Win9x seems to silently ignore DCX_NORESETATTRS */
63 ok( rop
== def_rop
|| rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
65 SetROP2( hdc
, R2_WHITE
);
67 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
69 ReleaseDC( hwnd_cache
, hdc
);
70 hdc
= GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
72 ok( rop
== def_rop
|| rop
== R2_WHITE
, "wrong ROP2 %d after release\n", rop
);
73 ReleaseDC( hwnd_cache
, hdc
);
75 hdc
= GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
);
77 ok( rop
== def_rop
, "wrong ROP2 %d after release\n", rop
);
78 ReleaseDC( hwnd_cache
, hdc
);
82 hdc
= GetDC( hwnd_owndc
);
83 SetROP2( hdc
, R2_WHITE
);
85 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
88 ReleaseDC( hwnd_owndc
, hdc
);
89 hdc
= GetDC( hwnd_owndc
);
90 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
92 ok( rop
== R2_WHITE
, "wrong ROP2 %d after release\n", rop
);
93 ReleaseDC( hwnd_owndc
, hdc
);
95 ok( rop
== R2_WHITE
, "wrong ROP2 %d after second release\n", rop
);
99 hdc
= GetDC( hwnd_classdc
);
100 SetROP2( hdc
, R2_WHITE
);
101 rop
= GetROP2( hdc
);
102 ok( rop
== R2_WHITE
, "wrong ROP2 %d\n", rop
);
105 ReleaseDC( hwnd_classdc
, hdc
);
106 hdc
= GetDC( hwnd_classdc
);
107 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
108 rop
= GetROP2( hdc
);
109 ok( rop
== R2_WHITE
, "wrong ROP2 %d after release\n", rop
);
110 ReleaseDC( hwnd_classdc
, hdc
);
111 rop
= GetROP2( hdc
);
112 ok( rop
== R2_WHITE
, "wrong ROP2 %d after second release\n", rop
);
114 /* test class DC with 2 windows */
116 old_hdc
= GetDC( hwnd_classdc
);
117 SetROP2( old_hdc
, R2_BLACK
);
118 hdc
= GetDC( hwnd_classdc2
);
119 ok( old_hdc
== hdc
, "didn't get same DC %p/%p\n", old_hdc
, hdc
);
120 rop
= GetROP2( hdc
);
121 ok( rop
== R2_BLACK
, "wrong ROP2 %d for other window\n", rop
);
122 ReleaseDC( hwnd_classdc
, old_hdc
);
123 ReleaseDC( hwnd_classdc
, hdc
);
124 rop
= GetROP2( hdc
);
125 ok( rop
== R2_BLACK
, "wrong ROP2 %d after release\n", rop
);
129 /* test behavior with various invalid parameters */
130 static void test_parameters(void)
134 hdc
= GetDC( hwnd_cache
);
135 ok( ReleaseDC( hwnd_owndc
, hdc
), "ReleaseDC with wrong window should succeed\n" );
137 hdc
= GetDC( hwnd_cache
);
138 ok( !ReleaseDC( hwnd_cache
, 0 ), "ReleaseDC with wrong HDC should fail\n" );
139 ok( ReleaseDC( hwnd_cache
, hdc
), "correct ReleaseDC should succeed\n" );
140 ok( !ReleaseDC( hwnd_cache
, hdc
), "second ReleaseDC should fail\n" );
142 hdc
= GetDC( hwnd_owndc
);
143 ok( ReleaseDC( hwnd_cache
, hdc
), "ReleaseDC with wrong window should succeed\n" );
144 hdc
= GetDC( hwnd_owndc
);
145 ok( ReleaseDC( hwnd_owndc
, hdc
), "correct ReleaseDC should succeed\n" );
146 ok( ReleaseDC( hwnd_owndc
, hdc
), "second ReleaseDC should succeed\n" );
148 hdc
= GetDC( hwnd_classdc
);
149 ok( ReleaseDC( hwnd_cache
, hdc
), "ReleaseDC with wrong window should succeed\n" );
150 hdc
= GetDC( hwnd_classdc
);
151 ok( ReleaseDC( hwnd_classdc
, hdc
), "correct ReleaseDC should succeed\n" );
152 ok( ReleaseDC( hwnd_classdc
, hdc
), "second ReleaseDC should succeed\n" );
156 static void test_dc_visrgn(void)
164 SetRect( &rect
, 10, 10, 20, 20 );
165 MapWindowPoints( hwnd_cache
, 0, (POINT
*)&rect
, 2 );
166 hrgn
= CreateRectRgnIndirect( &rect
);
167 hdc
= GetDCEx( hwnd_cache
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
168 SetRectEmpty( &rect
);
169 GetClipBox( hdc
, &rect
);
170 todo_wine
ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
171 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
172 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
173 ReleaseDC( hwnd_cache
, hdc
);
174 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
176 /* cache DC with NORESETATTRS */
178 SetRect( &rect
, 10, 10, 20, 20 );
179 MapWindowPoints( hwnd_cache
, 0, (POINT
*)&rect
, 2 );
180 hrgn
= CreateRectRgnIndirect( &rect
);
181 hdc
= GetDCEx( hwnd_cache
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
| DCX_NORESETATTRS
);
182 SetRectEmpty( &rect
);
183 GetClipBox( hdc
, &rect
);
184 todo_wine
ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
185 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
186 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
187 ReleaseDC( hwnd_cache
, hdc
);
188 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
189 hdc
= GetDCEx( hwnd_cache
, 0, DCX_USESTYLE
| DCX_NORESETATTRS
);
190 SetRectEmpty( &rect
);
191 GetClipBox( hdc
, &rect
);
192 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
193 "clip box sould have been reset %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
194 ReleaseDC( hwnd_cache
, hdc
);
198 SetRect( &rect
, 10, 10, 20, 20 );
199 MapWindowPoints( hwnd_owndc
, 0, (POINT
*)&rect
, 2 );
200 hrgn
= CreateRectRgnIndirect( &rect
);
201 hdc
= GetDCEx( hwnd_owndc
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
202 SetRectEmpty( &rect
);
203 GetClipBox( hdc
, &rect
);
204 todo_wine
ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
205 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
206 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
207 ReleaseDC( hwnd_owndc
, hdc
);
208 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
209 SetRectEmpty( &rect
);
210 GetClipBox( hdc
, &rect
);
211 todo_wine
ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
212 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
213 hdc
= GetDCEx( hwnd_owndc
, 0, DCX_USESTYLE
);
214 SetRectEmpty( &rect
);
215 GetClipBox( hdc
, &rect
);
216 todo_wine
ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
217 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
218 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
219 ReleaseDC( hwnd_owndc
, hdc
);
220 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
222 SetRect( &rect
, 20, 20, 30, 30 );
223 MapWindowPoints( hwnd_owndc
, 0, (POINT
*)&rect
, 2 );
224 hrgn2
= CreateRectRgnIndirect( &rect
);
225 hdc
= GetDCEx( hwnd_owndc
, hrgn2
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
226 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
227 SetRectEmpty( &rect
);
228 GetClipBox( hdc
, &rect
);
229 todo_wine
ok( rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30,
230 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
231 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
232 ReleaseDC( hwnd_owndc
, hdc
);
233 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
234 hdc
= GetDCEx( hwnd_owndc
, 0, DCX_EXCLUDERGN
| DCX_USESTYLE
);
235 ok( GetRgnBox( hrgn2
, &rect
) == ERROR
, "region must no longer be valid\n" );
236 SetRectEmpty( &rect
);
237 GetClipBox( hdc
, &rect
);
238 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
239 "clip box should have been reset %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
240 ReleaseDC( hwnd_owndc
, hdc
);
244 SetRect( &rect
, 10, 10, 20, 20 );
245 MapWindowPoints( hwnd_classdc
, 0, (POINT
*)&rect
, 2 );
246 hrgn
= CreateRectRgnIndirect( &rect
);
247 hdc
= GetDCEx( hwnd_classdc
, hrgn
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
248 SetRectEmpty( &rect
);
249 GetClipBox( hdc
, &rect
);
250 todo_wine
ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
251 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
252 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
253 ReleaseDC( hwnd_classdc
, hdc
);
254 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
255 SetRectEmpty( &rect
);
256 GetClipBox( hdc
, &rect
);
257 todo_wine
ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
258 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
260 hdc
= GetDCEx( hwnd_classdc
, 0, DCX_USESTYLE
);
261 SetRectEmpty( &rect
);
262 GetClipBox( hdc
, &rect
);
263 todo_wine
ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
264 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
265 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
266 ReleaseDC( hwnd_classdc
, hdc
);
267 ok( GetRgnBox( hrgn
, &rect
) != ERROR
, "region must still be valid\n" );
269 SetRect( &rect
, 20, 20, 30, 30 );
270 MapWindowPoints( hwnd_classdc
, 0, (POINT
*)&rect
, 2 );
271 hrgn2
= CreateRectRgnIndirect( &rect
);
272 hdc
= GetDCEx( hwnd_classdc
, hrgn2
, DCX_INTERSECTRGN
| DCX_USESTYLE
);
273 ok( GetRgnBox( hrgn
, &rect
) == ERROR
, "region must no longer be valid\n" );
274 SetRectEmpty( &rect
);
275 GetClipBox( hdc
, &rect
);
276 todo_wine
ok( rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30,
277 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
278 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
281 hdc
= GetDCEx( hwnd_classdc2
, 0, DCX_USESTYLE
);
282 ok( old_hdc
== hdc
, "did not get the same hdc %p/%p\n", old_hdc
, hdc
);
283 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
284 SetRectEmpty( &rect
);
285 GetClipBox( hdc
, &rect
);
286 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
287 "clip box should have been reset %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
288 ReleaseDC( hwnd_classdc2
, hdc
);
289 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
290 hdc
= GetDCEx( hwnd_classdc2
, 0, DCX_EXCLUDERGN
| DCX_USESTYLE
);
291 ok( GetRgnBox( hrgn2
, &rect
) != ERROR
, "region2 must still be valid\n" );
292 ok( !(rect
.left
>= 20 && rect
.top
>= 20 && rect
.right
<= 30 && rect
.bottom
<= 30),
293 "clip box must have been reset %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
294 ReleaseDC( hwnd_classdc2
, hdc
);
298 /* test various BeginPaint/EndPaint behaviors */
299 static void test_begin_paint(void)
307 /* clear update region */
308 RedrawWindow( hwnd_cache
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
309 SetRect( &rect
, 10, 10, 20, 20 );
310 RedrawWindow( hwnd_cache
, &rect
, 0, RDW_INVALIDATE
);
311 hdc
= BeginPaint( hwnd_cache
, &ps
);
312 SetRectEmpty( &rect
);
313 GetClipBox( hdc
, &rect
);
314 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
315 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
316 EndPaint( hwnd_cache
, &ps
);
320 RedrawWindow( hwnd_owndc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
321 SetRect( &rect
, 10, 10, 20, 20 );
322 RedrawWindow( hwnd_owndc
, &rect
, 0, RDW_INVALIDATE
);
323 hdc
= BeginPaint( hwnd_owndc
, &ps
);
324 SetRectEmpty( &rect
);
325 GetClipBox( hdc
, &rect
);
326 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
327 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
328 ReleaseDC( hwnd_owndc
, hdc
);
329 SetRectEmpty( &rect
);
330 GetClipBox( hdc
, &rect
);
331 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
332 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
333 ok( GetDC( hwnd_owndc
) == hdc
, "got different hdc\n" );
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 %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
338 EndPaint( hwnd_owndc
, &ps
);
339 SetRectEmpty( &rect
);
340 GetClipBox( hdc
, &rect
);
341 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
342 "clip box should have been reset %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
346 RedrawWindow( hwnd_classdc
, NULL
, 0, RDW_VALIDATE
|RDW_NOFRAME
|RDW_NOERASE
);
347 SetRect( &rect
, 10, 10, 20, 20 );
348 RedrawWindow( hwnd_classdc
, &rect
, 0, RDW_INVALIDATE
);
349 hdc
= BeginPaint( hwnd_classdc
, &ps
);
350 SetRectEmpty( &rect
);
351 GetClipBox( hdc
, &rect
);
352 ok( rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20,
353 "invalid clip box %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
356 hdc
= GetDC( hwnd_classdc2
);
357 ok( old_hdc
== hdc
, "did not get the same hdc %p/%p\n", old_hdc
, hdc
);
358 SetRectEmpty( &rect
);
359 GetClipBox( hdc
, &rect
);
360 ok( !(rect
.left
>= 10 && rect
.top
>= 10 && rect
.right
<= 20 && rect
.bottom
<= 20),
361 "clip box should have been reset %ld,%ld-%ld,%ld\n", rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
369 cls
.style
= CS_DBLCLKS
;
370 cls
.lpfnWndProc
= DefWindowProcA
;
373 cls
.hInstance
= GetModuleHandleA(0);
375 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
376 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
377 cls
.lpszMenuName
= NULL
;
378 cls
.lpszClassName
= "cache_class";
379 RegisterClassA(&cls
);
380 cls
.style
= CS_DBLCLKS
| CS_OWNDC
;
381 cls
.lpszClassName
= "owndc_class";
382 RegisterClassA(&cls
);
383 cls
.style
= CS_DBLCLKS
| CS_CLASSDC
;
384 cls
.lpszClassName
= "classdc_class";
385 RegisterClassA(&cls
);
387 hwnd_cache
= CreateWindowA("cache_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
389 0, 0, GetModuleHandleA(0), NULL
);
390 hwnd_owndc
= CreateWindowA("owndc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
392 0, 0, GetModuleHandleA(0), NULL
);
393 hwnd_classdc
= CreateWindowA("classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
395 0, 0, GetModuleHandleA(0), NULL
);
396 hwnd_classdc2
= CreateWindowA("classdc_class", NULL
, WS_OVERLAPPED
| WS_VISIBLE
,
398 0, 0, GetModuleHandleA(0), NULL
);
399 test_dc_attributes();