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 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 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 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 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 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 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 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 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 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 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();