1aa548ef6d3c9547509d3f50b9d47e6cf0045a0c
[reactos.git] / rostests / winetests / user32 / dce.c
1 /*
2 * Unit tests for DCE support
3 *
4 * Copyright 2005 Alexandre Julliard
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29
30 #include "wine/test.h"
31
32 #ifndef DCX_USESTYLE
33 #define DCX_USESTYLE 0x00010000
34 #endif
35
36 static HWND hwnd_cache, hwnd_owndc, hwnd_classdc, hwnd_classdc2;
37
38 /* test behavior of DC attributes with various GetDC/ReleaseDC combinations */
39 static void test_dc_attributes(void)
40 {
41 HDC hdc, old_hdc;
42 HDC hdcs[20];
43 INT i, rop, def_rop, found_dc;
44
45 /* test cache DC */
46
47 hdc = GetDC( hwnd_cache );
48 def_rop = GetROP2( hdc );
49
50 SetROP2( hdc, R2_WHITE );
51 rop = GetROP2( hdc );
52 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
53
54 ReleaseDC( hwnd_cache, hdc );
55 hdc = GetDC( hwnd_cache );
56 rop = GetROP2( hdc );
57 ok( rop == def_rop, "wrong ROP2 %d after release\n", rop );
58 SetROP2( hdc, R2_WHITE );
59 ReleaseDC( hwnd_cache, hdc );
60 old_hdc = hdc;
61
62 found_dc = 0;
63 for (i = 0; i < 20; i++)
64 {
65 hdc = hdcs[i] = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
66 if (!hdc) break;
67 rop = GetROP2( hdc );
68 ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
69 if (hdc == old_hdc)
70 {
71 found_dc = 1;
72 SetROP2( hdc, R2_WHITE );
73 }
74 }
75 if (!found_dc)
76 {
77 trace( "hdc %p not found in cache using %p\n", old_hdc, hdcs[0] );
78 old_hdc = hdcs[0];
79 SetROP2( old_hdc, R2_WHITE );
80 }
81 while (i >= 0) ReleaseDC( hwnd_cache, hdcs[--i] );
82
83 for (i = 0; i < 20; i++)
84 {
85 hdc = hdcs[i] = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
86 if (!hdc) break;
87 rop = GetROP2( hdc );
88 if (hdc == old_hdc)
89 ok( rop == R2_WHITE || broken( rop == def_rop), /* win9x doesn't support DCX_NORESETATTRS */
90 "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
91 else
92 ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
93 }
94 while (i >= 0) ReleaseDC( hwnd_cache, hdcs[--i] );
95
96 for (i = 0; i < 20; i++)
97 {
98 hdc = hdcs[i] = GetDCEx( hwnd_cache, 0, DCX_USESTYLE );
99 if (!hdc) break;
100 rop = GetROP2( hdc );
101 if (hdc == old_hdc)
102 {
103 ok( rop == R2_WHITE || broken( rop == def_rop),
104 "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
105 SetROP2( old_hdc, def_rop );
106 }
107 else
108 ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
109 }
110 while (i >= 0) ReleaseDC( hwnd_cache, hdcs[--i] );
111
112 /* test own DC */
113
114 hdc = GetDC( hwnd_owndc );
115 SetROP2( hdc, R2_WHITE );
116 rop = GetROP2( hdc );
117 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
118
119 old_hdc = hdc;
120 ReleaseDC( hwnd_owndc, hdc );
121 hdc = GetDC( hwnd_owndc );
122 ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
123 rop = GetROP2( hdc );
124 ok( rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
125 ReleaseDC( hwnd_owndc, hdc );
126 rop = GetROP2( hdc );
127 ok( rop == R2_WHITE, "wrong ROP2 %d after second release\n", rop );
128
129 /* test class DC */
130
131 hdc = GetDC( hwnd_classdc );
132 SetROP2( hdc, R2_WHITE );
133 rop = GetROP2( hdc );
134 ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
135
136 old_hdc = hdc;
137 ReleaseDC( hwnd_classdc, hdc );
138 hdc = GetDC( hwnd_classdc );
139 ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
140 rop = GetROP2( hdc );
141 ok( rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
142 ReleaseDC( hwnd_classdc, hdc );
143 rop = GetROP2( hdc );
144 ok( rop == R2_WHITE, "wrong ROP2 %d after second release\n", rop );
145
146 /* test class DC with 2 windows */
147
148 old_hdc = GetDC( hwnd_classdc );
149 SetROP2( old_hdc, R2_BLACK );
150 hdc = GetDC( hwnd_classdc2 );
151 ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
152 rop = GetROP2( hdc );
153 ok( rop == R2_BLACK, "wrong ROP2 %d for other window\n", rop );
154 ReleaseDC( hwnd_classdc, old_hdc );
155 ReleaseDC( hwnd_classdc, hdc );
156 rop = GetROP2( hdc );
157 ok( rop == R2_BLACK, "wrong ROP2 %d after release\n", rop );
158 }
159
160
161 /* test behavior with various invalid parameters */
162 static void test_parameters(void)
163 {
164 HDC hdc;
165
166 hdc = GetDC( hwnd_cache );
167 ok( ReleaseDC( hwnd_owndc, hdc ), "ReleaseDC with wrong window should succeed\n" );
168
169 hdc = GetDC( hwnd_cache );
170 ok( !ReleaseDC( hwnd_cache, 0 ), "ReleaseDC with wrong HDC should fail\n" );
171 ok( ReleaseDC( hwnd_cache, hdc ), "correct ReleaseDC should succeed\n" );
172 ok( !ReleaseDC( hwnd_cache, hdc ), "second ReleaseDC should fail\n" );
173
174 hdc = GetDC( hwnd_owndc );
175 ok( ReleaseDC( hwnd_cache, hdc ), "ReleaseDC with wrong window should succeed\n" );
176 hdc = GetDC( hwnd_owndc );
177 ok( ReleaseDC( hwnd_owndc, hdc ), "correct ReleaseDC should succeed\n" );
178 ok( ReleaseDC( hwnd_owndc, hdc ), "second ReleaseDC should succeed\n" );
179
180 hdc = GetDC( hwnd_classdc );
181 ok( ReleaseDC( hwnd_cache, hdc ), "ReleaseDC with wrong window should succeed\n" );
182 hdc = GetDC( hwnd_classdc );
183 ok( ReleaseDC( hwnd_classdc, hdc ), "correct ReleaseDC should succeed\n" );
184 ok( ReleaseDC( hwnd_classdc, hdc ), "second ReleaseDC should succeed\n" );
185 }
186
187
188 static void test_dc_visrgn(void)
189 {
190 HDC old_hdc, hdc;
191 HRGN hrgn, hrgn2;
192 RECT rect;
193
194 /* cache DC */
195
196 SetRect( &rect, 10, 10, 20, 20 );
197 MapWindowPoints( hwnd_cache, 0, (POINT *)&rect, 2 );
198 hrgn = CreateRectRgnIndirect( &rect );
199 hdc = GetDCEx( hwnd_cache, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
200 SetRectEmpty( &rect );
201 GetClipBox( hdc, &rect );
202 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
203 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
204 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
205 ReleaseDC( hwnd_cache, hdc );
206 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
207
208 /* cache DC with NORESETATTRS */
209
210 SetRect( &rect, 10, 10, 20, 20 );
211 MapWindowPoints( hwnd_cache, 0, (POINT *)&rect, 2 );
212 hrgn = CreateRectRgnIndirect( &rect );
213 hdc = GetDCEx( hwnd_cache, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE | DCX_NORESETATTRS );
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 %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
218 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
219 ReleaseDC( hwnd_cache, hdc );
220 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
221 hdc = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
222 SetRectEmpty( &rect );
223 GetClipBox( hdc, &rect );
224 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
225 "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
226 ReleaseDC( hwnd_cache, hdc );
227
228 /* window DC */
229
230 SetRect( &rect, 10, 10, 20, 20 );
231 MapWindowPoints( hwnd_owndc, 0, (POINT *)&rect, 2 );
232 hrgn = CreateRectRgnIndirect( &rect );
233 hdc = GetDCEx( hwnd_owndc, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
234 SetRectEmpty( &rect );
235 GetClipBox( hdc, &rect );
236 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
237 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
238 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
239 ReleaseDC( hwnd_owndc, hdc );
240 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
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 %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
245 hdc = GetDCEx( hwnd_owndc, 0, DCX_USESTYLE );
246 SetRectEmpty( &rect );
247 GetClipBox( hdc, &rect );
248 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
249 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
250 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
251 ReleaseDC( hwnd_owndc, hdc );
252 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
253
254 SetRect( &rect, 20, 20, 30, 30 );
255 MapWindowPoints( hwnd_owndc, 0, (POINT *)&rect, 2 );
256 hrgn2 = CreateRectRgnIndirect( &rect );
257 hdc = GetDCEx( hwnd_owndc, hrgn2, DCX_INTERSECTRGN | DCX_USESTYLE );
258 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
259 SetRectEmpty( &rect );
260 GetClipBox( hdc, &rect );
261 ok( rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30,
262 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
263 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
264 ReleaseDC( hwnd_owndc, hdc );
265 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
266 hdc = GetDCEx( hwnd_owndc, 0, DCX_EXCLUDERGN | DCX_USESTYLE );
267 ok( GetRgnBox( hrgn2, &rect ) == ERROR, "region must no longer be valid\n" );
268 SetRectEmpty( &rect );
269 GetClipBox( hdc, &rect );
270 ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
271 "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
272 ReleaseDC( hwnd_owndc, hdc );
273
274 /* class DC */
275
276 SetRect( &rect, 10, 10, 20, 20 );
277 MapWindowPoints( hwnd_classdc, 0, (POINT *)&rect, 2 );
278 hrgn = CreateRectRgnIndirect( &rect );
279 hdc = GetDCEx( hwnd_classdc, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
280 SetRectEmpty( &rect );
281 GetClipBox( hdc, &rect );
282 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
283 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
284 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
285 ReleaseDC( hwnd_classdc, hdc );
286 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
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 %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
291
292 hdc = GetDCEx( hwnd_classdc, 0, DCX_USESTYLE );
293 SetRectEmpty( &rect );
294 GetClipBox( hdc, &rect );
295 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
296 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
297 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
298 ReleaseDC( hwnd_classdc, hdc );
299 ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
300
301 SetRect( &rect, 20, 20, 30, 30 );
302 MapWindowPoints( hwnd_classdc, 0, (POINT *)&rect, 2 );
303 hrgn2 = CreateRectRgnIndirect( &rect );
304 hdc = GetDCEx( hwnd_classdc, hrgn2, DCX_INTERSECTRGN | DCX_USESTYLE );
305 ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
306 SetRectEmpty( &rect );
307 GetClipBox( hdc, &rect );
308 ok( rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30,
309 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
310 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
311
312 old_hdc = hdc;
313 hdc = GetDCEx( hwnd_classdc2, 0, DCX_USESTYLE );
314 ok( old_hdc == hdc, "did not get the same hdc %p/%p\n", old_hdc, hdc );
315 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
316 SetRectEmpty( &rect );
317 GetClipBox( hdc, &rect );
318 ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
319 "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
320 ReleaseDC( hwnd_classdc2, hdc );
321 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
322 hdc = GetDCEx( hwnd_classdc2, 0, DCX_EXCLUDERGN | DCX_USESTYLE );
323 ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
324 ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
325 "clip box must have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
326 ReleaseDC( hwnd_classdc2, hdc );
327 }
328
329
330 /* test various BeginPaint/EndPaint behaviors */
331 static void test_begin_paint(void)
332 {
333 HDC old_hdc, hdc;
334 RECT rect;
335 PAINTSTRUCT ps;
336
337 /* cache DC */
338
339 /* clear update region */
340 RedrawWindow( hwnd_cache, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
341 SetRect( &rect, 10, 10, 20, 20 );
342 RedrawWindow( hwnd_cache, &rect, 0, RDW_INVALIDATE );
343 hdc = BeginPaint( hwnd_cache, &ps );
344 SetRectEmpty( &rect );
345 GetClipBox( hdc, &rect );
346 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
347 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
348 EndPaint( hwnd_cache, &ps );
349
350 /* window DC */
351
352 RedrawWindow( hwnd_owndc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
353 SetRect( &rect, 10, 10, 20, 20 );
354 RedrawWindow( hwnd_owndc, &rect, 0, RDW_INVALIDATE );
355 hdc = BeginPaint( hwnd_owndc, &ps );
356 SetRectEmpty( &rect );
357 GetClipBox( hdc, &rect );
358 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
359 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
360 ReleaseDC( hwnd_owndc, hdc );
361 SetRectEmpty( &rect );
362 GetClipBox( hdc, &rect );
363 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
364 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
365 ok( GetDC( hwnd_owndc ) == hdc, "got different hdc\n" );
366 SetRectEmpty( &rect );
367 GetClipBox( hdc, &rect );
368 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
369 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
370 EndPaint( hwnd_owndc, &ps );
371 SetRectEmpty( &rect );
372 GetClipBox( hdc, &rect );
373 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
374 "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
375 RedrawWindow( hwnd_owndc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
376 SetRect( &rect, 10, 10, 20, 20 );
377 RedrawWindow( hwnd_owndc, &rect, 0, RDW_INVALIDATE|RDW_ERASE );
378 ok( GetDC( hwnd_owndc ) == hdc, "got different hdc\n" );
379 SetRectEmpty( &rect );
380 GetClipBox( hdc, &rect );
381 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
382 "clip box should be the whole window %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
383 RedrawWindow( hwnd_owndc, NULL, 0, RDW_ERASENOW );
384 SetRectEmpty( &rect );
385 GetClipBox( hdc, &rect );
386 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
387 "clip box should still be the whole window %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
388
389 /* class DC */
390
391 RedrawWindow( hwnd_classdc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
392 SetRect( &rect, 10, 10, 20, 20 );
393 RedrawWindow( hwnd_classdc, &rect, 0, RDW_INVALIDATE );
394 hdc = BeginPaint( hwnd_classdc, &ps );
395 SetRectEmpty( &rect );
396 GetClipBox( hdc, &rect );
397 ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
398 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
399
400 old_hdc = hdc;
401 hdc = GetDC( hwnd_classdc2 );
402 ok( old_hdc == hdc, "did not get the same hdc %p/%p\n", old_hdc, hdc );
403 SetRectEmpty( &rect );
404 GetClipBox( hdc, &rect );
405 ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
406 "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
407 }
408
409 /* test ScrollWindow with window DCs */
410 static void test_scroll_window(void)
411 {
412 PAINTSTRUCT ps;
413 HDC hdc;
414 RECT clip, rect;
415
416 /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
417
418 UpdateWindow( hwnd_owndc );
419 SetRect( &clip, 25, 25, 50, 50 );
420 ScrollWindow( hwnd_owndc, -5, -10, NULL, &clip );
421 hdc = BeginPaint( hwnd_owndc, &ps );
422 SetRectEmpty( &rect );
423 GetClipBox( hdc, &rect );
424 ok( rect.left >= 25 && rect.top >= 25 && rect.right <= 50 && rect.bottom <= 50,
425 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
426 EndPaint( hwnd_owndc, &ps );
427
428 SetViewportExtEx( hdc, 2, 3, NULL );
429 SetViewportOrgEx( hdc, 30, 20, NULL );
430
431 ScrollWindow( hwnd_owndc, -5, -10, NULL, &clip );
432 hdc = BeginPaint( hwnd_owndc, &ps );
433 SetRectEmpty( &rect );
434 GetClipBox( hdc, &rect );
435 ok( rect.left >= 25 && rect.top >= 25 && rect.right <= 50 && rect.bottom <= 50,
436 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
437 EndPaint( hwnd_owndc, &ps );
438
439 ScrollWindowEx( hwnd_owndc, -5, -10, NULL, &clip, 0, NULL, SW_INVALIDATE | SW_ERASE );
440 hdc = BeginPaint( hwnd_owndc, &ps );
441 SetRectEmpty( &rect );
442 GetClipBox( hdc, &rect );
443 ok( rect.left >= -5 && rect.top >= 5 && rect.right <= 20 && rect.bottom <= 30,
444 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
445 EndPaint( hwnd_owndc, &ps );
446
447 SetViewportExtEx( hdc, 1, 1, NULL );
448 SetViewportOrgEx( hdc, 0, 0, NULL );
449
450 ScrollWindowEx( hwnd_owndc, -5, -10, NULL, &clip, 0, NULL, SW_INVALIDATE | SW_ERASE );
451 hdc = BeginPaint( hwnd_owndc, &ps );
452 SetRectEmpty( &rect );
453 GetClipBox( hdc, &rect );
454 ok( rect.left >= 25 && rect.top >= 25 && rect.right <= 50 && rect.bottom <= 50,
455 "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
456 EndPaint( hwnd_owndc, &ps );
457 }
458
459 static void test_invisible_create(void)
460 {
461 HWND hwnd_owndc = CreateWindowA("owndc_class", NULL, WS_OVERLAPPED,
462 0, 200, 100, 100,
463 0, 0, GetModuleHandleA(0), NULL );
464 HDC dc1, dc2;
465
466 dc1 = GetDC(hwnd_owndc);
467 dc2 = GetDC(hwnd_owndc);
468
469 ok(dc1 == dc2, "expected owndc dcs to match\n");
470
471 ReleaseDC(hwnd_owndc, dc2);
472 ReleaseDC(hwnd_owndc, dc1);
473 DestroyWindow(hwnd_owndc);
474 }
475
476 static void test_dc_layout(void)
477 {
478 DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
479 DWORD (WINAPI *pGetLayout)(HDC hdc);
480 HWND hwnd_cache_rtl, hwnd_owndc_rtl, hwnd_classdc_rtl, hwnd_classdc2_rtl;
481 HDC hdc;
482 DWORD layout;
483 HMODULE mod = GetModuleHandleA("gdi32.dll");
484
485 pGetLayout = (void *)GetProcAddress( mod, "GetLayout" );
486 pSetLayout = (void *)GetProcAddress( mod, "SetLayout" );
487 if (!pGetLayout || !pSetLayout)
488 {
489 win_skip( "Don't have SetLayout\n" );
490 return;
491 }
492
493 hdc = GetDC( hwnd_cache );
494 pSetLayout( hdc, LAYOUT_RTL );
495 layout = pGetLayout( hdc );
496 ReleaseDC( hwnd_cache, hdc );
497 if (!layout)
498 {
499 win_skip( "SetLayout not supported\n" );
500 return;
501 }
502
503 hwnd_cache_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "cache_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
504 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
505 hwnd_owndc_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "owndc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
506 0, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
507 hwnd_classdc_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
508 200, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
509 hwnd_classdc2_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
510 200, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
511 hdc = GetDC( hwnd_cache_rtl );
512 layout = pGetLayout( hdc );
513
514 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
515 pSetLayout( hdc, 0 );
516 ReleaseDC( hwnd_cache_rtl, hdc );
517 hdc = GetDC( hwnd_owndc_rtl );
518 layout = pGetLayout( hdc );
519 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
520 ReleaseDC( hwnd_cache_rtl, hdc );
521
522 hdc = GetDC( hwnd_cache );
523 layout = pGetLayout( hdc );
524 ok( layout == 0, "wrong layout %x\n", layout );
525 ReleaseDC( hwnd_cache, hdc );
526
527 hdc = GetDC( hwnd_owndc_rtl );
528 layout = pGetLayout( hdc );
529 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
530 pSetLayout( hdc, 0 );
531 ReleaseDC( hwnd_owndc_rtl, hdc );
532 hdc = GetDC( hwnd_owndc_rtl );
533 layout = pGetLayout( hdc );
534 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
535 ReleaseDC( hwnd_owndc_rtl, hdc );
536
537 hdc = GetDC( hwnd_classdc_rtl );
538 layout = pGetLayout( hdc );
539 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
540 pSetLayout( hdc, 0 );
541 ReleaseDC( hwnd_classdc_rtl, hdc );
542 hdc = GetDC( hwnd_classdc2_rtl );
543 layout = pGetLayout( hdc );
544 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
545 ReleaseDC( hwnd_classdc2_rtl, hdc );
546 hdc = GetDC( hwnd_classdc );
547 layout = pGetLayout( hdc );
548 ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
549 ReleaseDC( hwnd_classdc_rtl, hdc );
550
551 DestroyWindow(hwnd_classdc2_rtl);
552 DestroyWindow(hwnd_classdc_rtl);
553 DestroyWindow(hwnd_owndc_rtl);
554 DestroyWindow(hwnd_cache_rtl);
555 }
556
557 static void test_destroyed_window(void)
558 {
559 HDC dc;
560
561 dc = GetDCEx(hwnd_cache, 0, DCX_USESTYLE);
562 ok(!dc, "Got a non-NULL DC (%p) for a destroyed window.\n", dc);
563
564 dc = GetDCEx(hwnd_owndc, 0, DCX_USESTYLE);
565 ok(!dc, "Got a non-NULL DC (%p) for a destroyed window.\n", dc);
566
567 dc = GetDCEx(hwnd_classdc, 0, DCX_USESTYLE);
568 ok(!dc, "Got a non-NULL DC (%p) for a destroyed window.\n", dc);
569
570 dc = GetDCEx(hwnd_classdc2, 0, DCX_USESTYLE);
571 ok(!dc, "Got a non-NULL DC (%p) for a destroyed window.\n", dc);
572 }
573
574 START_TEST(dce)
575 {
576 WNDCLASSA cls;
577
578 cls.style = CS_DBLCLKS;
579 cls.lpfnWndProc = DefWindowProcA;
580 cls.cbClsExtra = 0;
581 cls.cbWndExtra = 0;
582 cls.hInstance = GetModuleHandleA(0);
583 cls.hIcon = 0;
584 cls.hCursor = LoadCursorA(0, IDC_ARROW);
585 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
586 cls.lpszMenuName = NULL;
587 cls.lpszClassName = "cache_class";
588 RegisterClassA(&cls);
589 cls.style = CS_DBLCLKS | CS_OWNDC;
590 cls.lpszClassName = "owndc_class";
591 RegisterClassA(&cls);
592 cls.style = CS_DBLCLKS | CS_CLASSDC;
593 cls.lpszClassName = "classdc_class";
594 RegisterClassA(&cls);
595
596 hwnd_cache = CreateWindowA("cache_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
597 0, 0, 100, 100,
598 0, 0, GetModuleHandleA(0), NULL );
599 hwnd_owndc = CreateWindowA("owndc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
600 0, 200, 100, 100,
601 0, 0, GetModuleHandleA(0), NULL );
602 hwnd_classdc = CreateWindowA("classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
603 200, 0, 100, 100,
604 0, 0, GetModuleHandleA(0), NULL );
605 hwnd_classdc2 = CreateWindowA("classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
606 200, 200, 100, 100,
607 0, 0, GetModuleHandleA(0), NULL );
608 test_dc_attributes();
609 test_parameters();
610 test_dc_visrgn();
611 test_begin_paint();
612 test_scroll_window();
613 test_invisible_create();
614 test_dc_layout();
615
616 DestroyWindow(hwnd_classdc2);
617 DestroyWindow(hwnd_classdc);
618 DestroyWindow(hwnd_owndc);
619 DestroyWindow(hwnd_cache);
620
621 test_destroyed_window();
622 }