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