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