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"
37 #define DCX_USESTYLE 0x00010000
40 static HWND hwnd_cache, hwnd_owndc, hwnd_classdc, hwnd_classdc2;
42 /* test behavior of DC attributes with various GetDC/ReleaseDC combinations */
43 static void test_dc_attributes(void)
50 hdc = GetDC( hwnd_cache );
51 def_rop = GetROP2( hdc );
53 SetROP2( hdc, R2_WHITE );
55 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
57 ReleaseDC( hwnd_cache, hdc );
58 hdc = GetDC( hwnd_cache );
60 ok( rop == def_rop, "wrong ROP2 %d after release\n", rop );
61 SetROP2( hdc, R2_WHITE );
62 ReleaseDC( hwnd_cache, hdc );
64 hdc = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
66 /* Win9x seems to silently ignore DCX_NORESETATTRS */
67 ok( rop == def_rop || rop == R2_WHITE, "wrong ROP2 %d\n", rop );
69 SetROP2( hdc, R2_WHITE );
71 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
73 ReleaseDC( hwnd_cache, hdc );
74 hdc = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
76 ok( rop == def_rop || rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
77 ReleaseDC( hwnd_cache, hdc );
79 hdc = GetDCEx( hwnd_cache, 0, DCX_USESTYLE );
81 ok( rop == def_rop, "wrong ROP2 %d after release\n", rop );
82 ReleaseDC( hwnd_cache, hdc );
86 hdc = GetDC( hwnd_owndc );
87 SetROP2( hdc, R2_WHITE );
89 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
92 ReleaseDC( hwnd_owndc, hdc );
93 hdc = GetDC( hwnd_owndc );
94 ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
96 ok( rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
97 ReleaseDC( hwnd_owndc, hdc );
99 ok( rop == R2_WHITE, "wrong ROP2 %d after second release\n", rop );
103 hdc = GetDC( hwnd_classdc );
104 SetROP2( hdc, R2_WHITE );
105 rop = GetROP2( hdc );
106 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
109 ReleaseDC( hwnd_classdc, hdc );
110 hdc = GetDC( hwnd_classdc );
111 ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
112 rop = GetROP2( hdc );
113 ok( rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
114 ReleaseDC( hwnd_classdc, hdc );
115 rop = GetROP2( hdc );
116 ok( rop == R2_WHITE, "wrong ROP2 %d after second release\n", rop );
118 /* test class DC with 2 windows */
120 old_hdc = GetDC( hwnd_classdc );
121 SetROP2( old_hdc, R2_BLACK );
122 hdc = GetDC( hwnd_classdc2 );
123 ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
124 rop = GetROP2( hdc );
125 ok( rop == R2_BLACK, "wrong ROP2 %d for other window\n", rop );
126 ReleaseDC( hwnd_classdc, old_hdc );
127 ReleaseDC( hwnd_classdc, hdc );
128 rop = GetROP2( hdc );
129 ok( rop == R2_BLACK, "wrong ROP2 %d after release\n", rop );
133 /* test behavior with various invalid parameters */
134 static void test_parameters(void)
138 hdc = GetDC( hwnd_cache );
139 ok( ReleaseDC( hwnd_owndc, hdc ), "ReleaseDC with wrong window should succeed\n" );
141 hdc = GetDC( hwnd_cache );
142 ok( !ReleaseDC( hwnd_cache, 0 ), "ReleaseDC with wrong HDC should fail\n" );
143 ok( ReleaseDC( hwnd_cache, hdc ), "correct ReleaseDC should succeed\n" );
144 ok( !ReleaseDC( hwnd_cache, hdc ), "second ReleaseDC should fail\n" );
146 hdc = GetDC( hwnd_owndc );
147 ok( ReleaseDC( hwnd_cache, hdc ), "ReleaseDC with wrong window should succeed\n" );
148 hdc = GetDC( hwnd_owndc );
149 ok( ReleaseDC( hwnd_owndc, hdc ), "correct ReleaseDC should succeed\n" );
150 ok( ReleaseDC( hwnd_owndc, hdc ), "second ReleaseDC should succeed\n" );
152 hdc = GetDC( hwnd_classdc );
153 ok( ReleaseDC( hwnd_cache, hdc ), "ReleaseDC with wrong window should succeed\n" );
154 hdc = GetDC( hwnd_classdc );
155 ok( ReleaseDC( hwnd_classdc, hdc ), "correct ReleaseDC should succeed\n" );
156 ok( ReleaseDC( hwnd_classdc, hdc ), "second ReleaseDC should succeed\n" );
160 static void test_dc_visrgn(void)
168 SetRect( &rect, 10, 10, 20, 20 );
169 MapWindowPoints( hwnd_cache, 0, (POINT *)&rect, 2 );
170 hrgn = CreateRectRgnIndirect( &rect );
171 hdc = GetDCEx( hwnd_cache, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
172 SetRectEmpty( &rect );
173 GetClipBox( hdc, &rect );
174 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
175 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
176 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
177 ReleaseDC( hwnd_cache, hdc );
178 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
180 /* cache DC with NORESETATTRS */
182 SetRect( &rect, 10, 10, 20, 20 );
183 MapWindowPoints( hwnd_cache, 0, (POINT *)&rect, 2 );
184 hrgn = CreateRectRgnIndirect( &rect );
185 hdc = GetDCEx( hwnd_cache, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE | DCX_NORESETATTRS );
186 SetRectEmpty( &rect );
187 GetClipBox( hdc, &rect );
188 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
189 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
190 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
191 ReleaseDC( hwnd_cache, hdc );
192 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
193 hdc = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
194 SetRectEmpty( &rect );
195 GetClipBox( hdc, &rect );
196 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
197 "clip box sould have been reset %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
198 ReleaseDC( hwnd_cache, hdc );
202 SetRect( &rect, 10, 10, 20, 20 );
203 MapWindowPoints( hwnd_owndc, 0, (POINT *)&rect, 2 );
204 hrgn = CreateRectRgnIndirect( &rect );
205 hdc = GetDCEx( hwnd_owndc, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
206 SetRectEmpty( &rect );
207 GetClipBox( hdc, &rect );
208 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
209 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
210 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
211 ReleaseDC( hwnd_owndc, hdc );
212 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
213 SetRectEmpty( &rect );
214 GetClipBox( hdc, &rect );
215 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
216 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
217 hdc = GetDCEx( hwnd_owndc, 0, DCX_USESTYLE );
218 SetRectEmpty( &rect );
219 GetClipBox( hdc, &rect );
220 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
221 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
222 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
223 ReleaseDC( hwnd_owndc, hdc );
224 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
226 SetRect( &rect, 20, 20, 30, 30 );
227 MapWindowPoints( hwnd_owndc, 0, (POINT *)&rect, 2 );
228 hrgn2 = CreateRectRgnIndirect( &rect );
229 hdc = GetDCEx( hwnd_owndc, hrgn2, DCX_INTERSECTRGN | DCX_USESTYLE );
230 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
231 SetRectEmpty( &rect );
232 GetClipBox( hdc, &rect );
233 ok( rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30,
234 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
235 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
236 ReleaseDC( hwnd_owndc, hdc );
237 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
238 hdc = GetDCEx( hwnd_owndc, 0, DCX_EXCLUDERGN | DCX_USESTYLE );
239 ok( GetRgnBox( hrgn2, &rect ) == ERROR, "region must no longer be valid\n" );
240 SetRectEmpty( &rect );
241 GetClipBox( hdc, &rect );
242 ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
243 "clip box should have been reset %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
244 ReleaseDC( hwnd_owndc, hdc );
248 SetRect( &rect, 10, 10, 20, 20 );
249 MapWindowPoints( hwnd_classdc, 0, (POINT *)&rect, 2 );
250 hrgn = CreateRectRgnIndirect( &rect );
251 hdc = GetDCEx( hwnd_classdc, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
252 SetRectEmpty( &rect );
253 GetClipBox( hdc, &rect );
254 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
255 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
256 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
257 ReleaseDC( hwnd_classdc, hdc );
258 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
259 SetRectEmpty( &rect );
260 GetClipBox( hdc, &rect );
261 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
262 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
264 hdc = GetDCEx( hwnd_classdc, 0, DCX_USESTYLE );
265 SetRectEmpty( &rect );
266 GetClipBox( hdc, &rect );
267 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
268 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
269 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
270 ReleaseDC( hwnd_classdc, hdc );
271 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
273 SetRect( &rect, 20, 20, 30, 30 );
274 MapWindowPoints( hwnd_classdc, 0, (POINT *)&rect, 2 );
275 hrgn2 = CreateRectRgnIndirect( &rect );
276 hdc = GetDCEx( hwnd_classdc, hrgn2, DCX_INTERSECTRGN | DCX_USESTYLE );
277 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
278 SetRectEmpty( &rect );
279 GetClipBox( hdc, &rect );
280 ok( rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30,
281 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
282 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
285 hdc = GetDCEx( hwnd_classdc2, 0, DCX_USESTYLE );
286 ok( old_hdc == hdc, "did not get the same hdc %p/%p\n", old_hdc, hdc );
287 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
288 SetRectEmpty( &rect );
289 GetClipBox( hdc, &rect );
290 ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
291 "clip box should have been reset %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
292 ReleaseDC( hwnd_classdc2, hdc );
293 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
294 hdc = GetDCEx( hwnd_classdc2, 0, DCX_EXCLUDERGN | DCX_USESTYLE );
295 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
296 ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
297 "clip box must have been reset %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
298 ReleaseDC( hwnd_classdc2, hdc );
302 /* test various BeginPaint/EndPaint behaviors */
303 static void test_begin_paint(void)
311 /* clear update region */
312 RedrawWindow( hwnd_cache, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
313 SetRect( &rect, 10, 10, 20, 20 );
314 RedrawWindow( hwnd_cache, &rect, 0, RDW_INVALIDATE );
315 hdc = BeginPaint( hwnd_cache, &ps );
316 SetRectEmpty( &rect );
317 GetClipBox( hdc, &rect );
318 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
319 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
320 EndPaint( hwnd_cache, &ps );
324 RedrawWindow( hwnd_owndc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
325 SetRect( &rect, 10, 10, 20, 20 );
326 RedrawWindow( hwnd_owndc, &rect, 0, RDW_INVALIDATE );
327 hdc = BeginPaint( hwnd_owndc, &ps );
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 %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
332 ReleaseDC( hwnd_owndc, hdc );
333 SetRectEmpty( &rect );
334 GetClipBox( hdc, &rect );
335 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
336 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
337 ok( GetDC( hwnd_owndc ) == hdc, "got different hdc\n" );
338 SetRectEmpty( &rect );
339 GetClipBox( hdc, &rect );
340 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
341 "invalid clip box %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
342 EndPaint( hwnd_owndc, &ps );
343 SetRectEmpty( &rect );
344 GetClipBox( hdc, &rect );
345 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
346 "clip box should have been reset %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
347 RedrawWindow( hwnd_owndc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
348 SetRect( &rect, 10, 10, 20, 20 );
349 RedrawWindow( hwnd_owndc, &rect, 0, RDW_INVALIDATE|RDW_ERASE );
350 ok( GetDC( hwnd_owndc ) == hdc, "got different hdc\n" );
351 SetRectEmpty( &rect );
352 GetClipBox( hdc, &rect );
353 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
354 "clip box should be the whole window %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
355 RedrawWindow( hwnd_owndc, NULL, 0, RDW_ERASENOW );
356 SetRectEmpty( &rect );
357 GetClipBox( hdc, &rect );
358 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
359 "clip box should still be the whole window %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
363 RedrawWindow( hwnd_classdc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
364 SetRect( &rect, 10, 10, 20, 20 );
365 RedrawWindow( hwnd_classdc, &rect, 0, RDW_INVALIDATE );
366 hdc = BeginPaint( hwnd_classdc, &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 %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
373 hdc = GetDC( hwnd_classdc2 );
374 ok( old_hdc == hdc, "did not get the same hdc %p/%p\n", old_hdc, hdc );
375 SetRectEmpty( &rect );
376 GetClipBox( hdc, &rect );
377 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
378 "clip box should have been reset %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
386 cls.style = CS_DBLCLKS;
387 cls.lpfnWndProc = DefWindowProcA;
390 cls.hInstance = GetModuleHandleA(0);
392 cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
393 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
394 cls.lpszMenuName = NULL;
395 cls.lpszClassName = "cache_class";
396 RegisterClassA(&cls);
397 cls.style = CS_DBLCLKS | CS_OWNDC;
398 cls.lpszClassName = "owndc_class";
399 RegisterClassA(&cls);
400 cls.style = CS_DBLCLKS | CS_CLASSDC;
401 cls.lpszClassName = "classdc_class";
402 RegisterClassA(&cls);
404 hwnd_cache = CreateWindowA("cache_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
406 0, 0, GetModuleHandleA(0), NULL );
407 hwnd_owndc = CreateWindowA("owndc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
409 0, 0, GetModuleHandleA(0), NULL );
410 hwnd_classdc = CreateWindowA("classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
412 0, 0, GetModuleHandleA(0), NULL );
413 hwnd_classdc2 = CreateWindowA("classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
415 0, 0, GetModuleHandleA(0), NULL );
416 test_dc_attributes();