/* * Unit tests for dc functions * * Copyright (c) 2005 Huw Davies * Copyright (c) 2005 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define WINVER 0x0501 /* request latest DEVMODE */ #include #include #include "wine/test.h" #include "winbase.h" #include "wingdi.h" #include "winuser.h" #include "winspool.h" #include "winerror.h" static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout); static void dump_region(HRGN hrgn) { DWORD i, size; RGNDATA *data = NULL; RECT *rect; if (!hrgn) { printf( "(null) region\n" ); return; } if (!(size = GetRegionData( hrgn, 0, NULL ))) return; if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return; GetRegionData( hrgn, size, data ); printf( "%d rects:", data->rdh.nCount ); for (i = 0, rect = (RECT *)data->Buffer; i < data->rdh.nCount; i++, rect++) printf( " (%d,%d)-(%d,%d)", rect->left, rect->top, rect->right, rect->bottom ); printf( "\n" ); HeapFree( GetProcessHeap(), 0, data ); } static void test_savedc_2(void) { HWND hwnd; HDC hdc; HRGN hrgn; RECT rc, rc_clip; int ret; hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100, 0, 0, 0, NULL); assert(hwnd != 0); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); hrgn = CreateRectRgn(0, 0, 0, 0); assert(hrgn != 0); hdc = GetDC(hwnd); ok(hdc != NULL, "GetDC failed\n"); ret = GetClipBox(hdc, &rc_clip); ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret); ret = GetClipRgn(hdc, hrgn); ok(ret == 0, "GetClipRgn returned %d instead of 0\n", ret); ret = GetRgnBox(hrgn, &rc); ok(ret == NULLREGION, "GetRgnBox returned %d (%d,%d-%d,%d) instead of NULLREGION\n", ret, rc.left, rc.top, rc.right, rc.bottom); /*dump_region(hrgn);*/ SetRect(&rc, 0, 0, 100, 100); ok(EqualRect(&rc, &rc_clip), "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom, rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom); ret = SaveDC(hdc); todo_wine { ok(ret == 1, "ret = %d\n", ret); } ret = IntersectClipRect(hdc, 0, 0, 50, 50); if (ret == COMPLEXREGION) { /* XP returns COMPLEXREGION although dump_region reports only 1 rect */ trace("Windows BUG: IntersectClipRect returned %d instead of SIMPLEREGION\n", ret); /* let's make sure that it's a simple region */ ret = GetClipRgn(hdc, hrgn); ok(ret == 1, "GetClipRgn returned %d instead of 1\n", ret); dump_region(hrgn); } else ok(ret == SIMPLEREGION, "IntersectClipRect returned %d instead of SIMPLEREGION\n", ret); ret = GetClipBox(hdc, &rc_clip); ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret); SetRect(&rc, 0, 0, 50, 50); ok(EqualRect(&rc, &rc_clip), "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom, rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom); ret = RestoreDC(hdc, 1); ok(ret, "ret = %d\n", ret); ret = GetClipBox(hdc, &rc_clip); ok(ret == SIMPLEREGION || broken(ret == COMPLEXREGION), "GetClipBox returned %d instead of SIMPLEREGION\n", ret); SetRect(&rc, 0, 0, 100, 100); ok(EqualRect(&rc, &rc_clip), "rects are not equal: (%d,%d-%d,%d) - (%d,%d-%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom, rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom); DeleteObject(hrgn); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); } static void test_savedc(void) { HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); int ret; ok(hdc != NULL, "CreateDC rets %p\n", hdc); ret = SaveDC(hdc); ok(ret == 1, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 2, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 3, "ret = %d\n", ret); ret = RestoreDC(hdc, -1); ok(ret, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 3, "ret = %d\n", ret); ret = RestoreDC(hdc, 1); ok(ret, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 1, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 2, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 3, "ret = %d\n", ret); ret = RestoreDC(hdc, -2); ok(ret, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 2, "ret = %d\n", ret); ret = RestoreDC(hdc, -2); ok(ret, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 1, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 2, "ret = %d\n", ret); ret = RestoreDC(hdc, -4); ok(!ret, "ret = %d\n", ret); ret = RestoreDC(hdc, 3); ok(!ret, "ret = %d\n", ret); /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */ ret = RestoreDC(hdc, -3); ok(!ret || broken(ret), /* Win9x */ "ret = %d\n", ret); /* Trying to clear an empty save stack fails. */ ret = RestoreDC(hdc, -3); ok(!ret, "ret = %d\n", ret); ret = SaveDC(hdc); ok(ret == 3 || broken(ret == 1), /* Win9x */ "ret = %d\n", ret); /* Under Win9x the following RestoreDC call succeeds and clears the save stack. */ ret = RestoreDC(hdc, 0); ok(!ret || broken(ret), /* Win9x */ "ret = %d\n", ret); /* Trying to clear an empty save stack fails. */ ret = RestoreDC(hdc, 0); ok(!ret, "ret = %d\n", ret); ret = RestoreDC(hdc, 1); ok(ret || broken(!ret), /* Win9x */ "ret = %d\n", ret); DeleteDC(hdc); } static void test_GdiConvertToDevmodeW(void) { DEVMODEW * (WINAPI *pGdiConvertToDevmodeW)(const DEVMODEA *); DEVMODEA dmA; DEVMODEW *dmW; BOOL ret; pGdiConvertToDevmodeW = (void *)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GdiConvertToDevmodeW"); if (!pGdiConvertToDevmodeW) { win_skip("GdiConvertToDevmodeW is not available on this platform\n"); return; } ret = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &dmA); ok(ret, "EnumDisplaySettingsExA error %u\n", GetLastError()); ok(dmA.dmSize >= FIELD_OFFSET(DEVMODEA, dmICMMethod), "dmSize is too small: %04x\n", dmA.dmSize); ok(dmA.dmSize <= sizeof(DEVMODEA), "dmSize is too large: %04x\n", dmA.dmSize); dmW = pGdiConvertToDevmodeW(&dmA); ok(dmW->dmSize >= FIELD_OFFSET(DEVMODEW, dmICMMethod), "dmSize is too small: %04x\n", dmW->dmSize); ok(dmW->dmSize <= sizeof(DEVMODEW), "dmSize is too large: %04x\n", dmW->dmSize); HeapFree(GetProcessHeap(), 0, dmW); dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields) + sizeof(dmA.dmFields); dmW = pGdiConvertToDevmodeW(&dmA); ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields) + sizeof(dmW->dmFields), "wrong size %u\n", dmW->dmSize); HeapFree(GetProcessHeap(), 0, dmW); dmA.dmICMMethod = DMICMMETHOD_NONE; dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmICMMethod) + sizeof(dmA.dmICMMethod); dmW = pGdiConvertToDevmodeW(&dmA); ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod) + sizeof(dmW->dmICMMethod), "wrong size %u\n", dmW->dmSize); ok(dmW->dmICMMethod == DMICMMETHOD_NONE, "expected DMICMMETHOD_NONE, got %u\n", dmW->dmICMMethod); HeapFree(GetProcessHeap(), 0, dmW); dmA.dmSize = 1024; dmW = pGdiConvertToDevmodeW(&dmA); ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmPanningHeight) + sizeof(dmW->dmPanningHeight), "wrong size %u\n", dmW->dmSize); HeapFree(GetProcessHeap(), 0, dmW); SetLastError(0xdeadbeef); dmA.dmSize = 0; dmW = pGdiConvertToDevmodeW(&dmA); ok(!dmW, "GdiConvertToDevmodeW should fail\n"); ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %u\n", GetLastError()); /* this is the minimal dmSize that XP accepts */ dmA.dmSize = FIELD_OFFSET(DEVMODEA, dmFields); dmW = pGdiConvertToDevmodeW(&dmA); ok(dmW->dmSize == FIELD_OFFSET(DEVMODEW, dmFields), "expected %04x, got %04x\n", FIELD_OFFSET(DEVMODEW, dmFields), dmW->dmSize); HeapFree(GetProcessHeap(), 0, dmW); } static void test_CreateCompatibleDC(void) { BOOL bRet; HDC hdc, hNewDC, hdcMetafile; HBITMAP bitmap; INT caps; bitmap = CreateBitmap( 10, 10, 1, 1, NULL ); /* Create a DC compatible with the screen */ hdc = CreateCompatibleDC(NULL); ok(hdc != NULL, "CreateCompatibleDC returned %p\n", hdc); ok( SelectObject( hdc, bitmap ) != 0, "SelectObject failed\n" ); caps = GetDeviceCaps( hdc, TECHNOLOGY ); ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps ); /* Delete this DC, this should succeed */ bRet = DeleteDC(hdc); ok(bRet == TRUE, "DeleteDC returned %u\n", bRet); /* Try to create a DC compatible to the deleted DC. This has to fail */ hNewDC = CreateCompatibleDC(hdc); ok(hNewDC == NULL, "CreateCompatibleDC returned %p\n", hNewDC); hdc = GetDC( 0 ); hdcMetafile = CreateEnhMetaFileA(hdc, NULL, NULL, NULL); ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n"); hNewDC = CreateCompatibleDC( hdcMetafile ); ok(hNewDC != NULL, "CreateCompatibleDC failed\n"); ok( SelectObject( hNewDC, bitmap ) != 0, "SelectObject failed\n" ); caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY ); ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps ); caps = GetDeviceCaps( hNewDC, TECHNOLOGY ); ok( caps == DT_RASDISPLAY, "wrong caps %u\n", caps ); DeleteDC( hNewDC ); DeleteEnhMetaFile( CloseEnhMetaFile( hdcMetafile )); ReleaseDC( 0, hdc ); hdcMetafile = CreateMetaFileA(NULL); ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n"); hNewDC = CreateCompatibleDC( hdcMetafile ); ok(hNewDC == NULL, "CreateCompatibleDC succeeded\n"); caps = GetDeviceCaps( hdcMetafile, TECHNOLOGY ); ok( caps == DT_METAFILE, "wrong caps %u\n", caps ); DeleteMetaFile( CloseMetaFile( hdcMetafile )); DeleteObject( bitmap ); } static void test_DC_bitmap(void) { HDC hdc, hdcmem; DWORD bits[64]; HBITMAP hbmp, oldhbmp; COLORREF col; int i, bitspixel; /* fill bitmap data with b&w pattern */ for( i = 0; i < 64; i++) bits[i] = i & 1 ? 0 : 0xffffff; hdc = GetDC(0); ok( hdc != NULL, "CreateDC rets %p\n", hdc); bitspixel = GetDeviceCaps( hdc, BITSPIXEL); /* create a memory dc */ hdcmem = CreateCompatibleDC( hdc); ok( hdcmem != NULL, "CreateCompatibleDC rets %p\n", hdcmem); /* tests */ /* test monochrome bitmap: should always work */ hbmp = CreateBitmap(32, 32, 1, 1, bits); ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp); oldhbmp = SelectObject( hdcmem, hbmp); ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); /* a memdc always has a bitmap selected */ col = GetPixel( hdcmem, 0, 0); ok( col == 0xffffff, "GetPixel returned %08x, expected 00ffffff\n", col); col = GetPixel( hdcmem, 1, 1); ok( col == 0x000000, "GetPixel returned %08x, expected 00000000\n", col); col = GetPixel( hdcmem, 100, 1); ok( col == CLR_INVALID, "GetPixel returned %08x, expected ffffffff\n", col); SelectObject( hdcmem, oldhbmp); DeleteObject( hbmp); /* test with 2 bits color depth, not likely to succeed */ hbmp = CreateBitmap(16, 16, 1, 2, bits); ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp); oldhbmp = SelectObject( hdcmem, hbmp); if( bitspixel != 2) ok( !oldhbmp, "SelectObject of a bitmap with 2 bits/pixel should return NULL\n"); if( oldhbmp) SelectObject( hdcmem, oldhbmp); DeleteObject( hbmp); /* test with 16 bits color depth, might succeed */ hbmp = CreateBitmap(6, 6, 1, 16, bits); ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp); oldhbmp = SelectObject( hdcmem, hbmp); if( bitspixel == 16) { ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); col = GetPixel( hdcmem, 0, 0); ok( col == 0xffffff, "GetPixel of a bitmap with 16 bits/pixel returned %08x, expected 00ffffff\n", col); col = GetPixel( hdcmem, 1, 1); ok( col == 0x000000, "GetPixel of a bitmap with 16 bits/pixel returned returned %08x, expected 00000000\n", col); } if( oldhbmp) SelectObject( hdcmem, oldhbmp); DeleteObject( hbmp); /* test with 32 bits color depth, probably succeed */ hbmp = CreateBitmap(4, 4, 1, 32, bits); ok( hbmp != NULL, "CreateBitmap returns %p\n", hbmp); oldhbmp = SelectObject( hdcmem, hbmp); if( bitspixel == 32) { ok( oldhbmp != NULL, "SelectObject returned NULL\n" ); col = GetPixel( hdcmem, 0, 0); ok( col == 0xffffff, "GetPixel of a bitmap with 32 bits/pixel returned %08x, expected 00ffffff\n", col); col = GetPixel( hdcmem, 1, 1); ok( col == 0x000000, "GetPixel of a bitmap with 32 bits/pixel returned returned %08x, expected 00000000\n", col); } if( oldhbmp) SelectObject( hdcmem, oldhbmp); DeleteObject( hbmp); ReleaseDC( 0, hdc ); } static void test_DeleteDC(void) { HWND hwnd; HDC hdc, hdc_test; WNDCLASSEX cls; int ret; /* window DC */ hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100, 0, 0, 0, NULL); ok(hwnd != 0, "CreateWindowExA failed\n"); hdc = GetDC(hwnd); ok(hdc != 0, "GetDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = DeleteDC(hdc); ok(ret, "DeleteDC failed\n"); ret = GetObjectType(hdc); ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n"); hdc = GetWindowDC(hwnd); ok(hdc != 0, "GetDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = DeleteDC(hdc); ok(ret, "DeleteDC failed\n"); ret = GetObjectType(hdc); ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n"); DestroyWindow(hwnd); /* desktop window DC */ hwnd = GetDesktopWindow(); ok(hwnd != 0, "GetDesktopWindow failed\n"); hdc = GetDC(hwnd); ok(hdc != 0, "GetDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = DeleteDC(hdc); ok(ret, "DeleteDC failed\n"); ret = GetObjectType(hdc); ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n"); hdc = GetWindowDC(hwnd); ok(hdc != 0, "GetDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = DeleteDC(hdc); ok(ret, "DeleteDC failed\n"); ret = GetObjectType(hdc); ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n"); /* CS_CLASSDC */ memset(&cls, 0, sizeof(cls)); cls.cbSize = sizeof(cls); cls.style = CS_CLASSDC; cls.hInstance = GetModuleHandle(0); cls.lpszClassName = "Wine class DC"; cls.lpfnWndProc = DefWindowProcA; ret = RegisterClassExA(&cls); ok(ret, "RegisterClassExA failed\n"); hwnd = CreateWindowExA(0, "Wine class DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100, 0, 0, 0, NULL); ok(hwnd != 0, "CreateWindowExA failed\n"); hdc = GetDC(hwnd); ok(hdc != 0, "GetDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = DeleteDC(hdc); ok(ret, "DeleteDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = ReleaseDC(hwnd, hdc); ok(ret, "ReleaseDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); hdc_test = hdc; hdc = GetWindowDC(hwnd); ok(hdc != 0, "GetDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = DeleteDC(hdc); ok(ret, "DeleteDC failed\n"); ret = GetObjectType(hdc); ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n"); DestroyWindow(hwnd); ret = GetObjectType(hdc_test); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = UnregisterClassA("Wine class DC", GetModuleHandle(NULL)); ok(ret, "UnregisterClassA failed\n"); ret = GetObjectType(hdc_test); todo_wine ok(!ret, "GetObjectType should fail for a deleted DC\n"); /* CS_OWNDC */ memset(&cls, 0, sizeof(cls)); cls.cbSize = sizeof(cls); cls.style = CS_OWNDC; cls.hInstance = GetModuleHandle(0); cls.lpszClassName = "Wine own DC"; cls.lpfnWndProc = DefWindowProcA; ret = RegisterClassExA(&cls); ok(ret, "RegisterClassExA failed\n"); hwnd = CreateWindowExA(0, "Wine own DC", NULL, WS_POPUP|WS_VISIBLE, 0,0,100,100, 0, 0, 0, NULL); ok(hwnd != 0, "CreateWindowExA failed\n"); hdc = GetDC(hwnd); ok(hdc != 0, "GetDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = DeleteDC(hdc); ok(ret, "DeleteDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = ReleaseDC(hwnd, hdc); ok(ret, "ReleaseDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); hdc = GetWindowDC(hwnd); ok(hdc != 0, "GetDC failed\n"); ret = GetObjectType(hdc); ok(ret == OBJ_DC, "expected OBJ_DC, got %d\n", ret); ret = DeleteDC(hdc); ok(ret, "DeleteDC failed\n"); ret = GetObjectType(hdc); ok(!ret || broken(ret) /* win9x */, "GetObjectType should fail for a deleted DC\n"); DestroyWindow(hwnd); ret = UnregisterClassA("Wine own DC", GetModuleHandle(NULL)); ok(ret, "UnregisterClassA failed\n"); } static void test_boundsrect(void) { HDC hdc; HBITMAP bitmap; RECT rect, expect, set_rect; UINT ret; hdc = CreateCompatibleDC(0); ok(hdc != NULL, "CreateCompatibleDC failed\n"); bitmap = CreateCompatibleBitmap( hdc, 200, 200 ); SelectObject( hdc, bitmap ); ret = GetBoundsRect(hdc, NULL, 0); ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret); ret = GetBoundsRect(hdc, NULL, ~0U); ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret); /* Test parameter handling order. */ SetRect(&set_rect, 10, 20, 40, 50); ret = SetBoundsRect(hdc, &set_rect, DCB_SET); ok(ret & DCB_RESET, "Expected return flag DCB_RESET to be set, got %u\n", ret); ret = GetBoundsRect(hdc, NULL, DCB_RESET); ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_RESET, "Expected GetBoundsRect to return DCB_RESET, got %u\n", ret); SetRect(&expect, 0, 0, 0, 0); ok(EqualRect(&rect, &expect) || broken(EqualRect(&rect, &set_rect)), /* nt4 sp1-5 */ "Expected output rectangle (0,0)-(0,0), got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); ret = GetBoundsRect(NULL, NULL, 0); ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret); ret = GetBoundsRect(NULL, NULL, ~0U); ok(ret == 0, "Expected GetBoundsRect to return 0, got %u\n", ret); ret = SetBoundsRect(NULL, NULL, 0); ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret); ret = SetBoundsRect(NULL, NULL, ~0U); ok(ret == 0, "Expected SetBoundsRect to return 0, got %u\n", ret); SetRect(&set_rect, 10, 20, 40, 50); ret = SetBoundsRect(hdc, &set_rect, DCB_SET); ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret); SetRect(&expect, 10, 20, 40, 50); ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); SetMapMode( hdc, MM_ANISOTROPIC ); SetViewportExtEx( hdc, 2, 2, NULL ); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret); SetRect(&expect, 5, 10, 20, 25); ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); SetViewportOrgEx( hdc, 20, 30, NULL ); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret); SetRect(&expect, -5, -5, 10, 10); ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); SetRect(&set_rect, 10, 20, 40, 50); ret = SetBoundsRect(hdc, &set_rect, DCB_SET); ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret); SetRect(&expect, 10, 20, 40, 50); ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); SetMapMode( hdc, MM_TEXT ); SetViewportOrgEx( hdc, 0, 0, NULL ); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret); SetRect(&expect, 40, 70, 100, 130); ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); if (pSetLayout) { pSetLayout( hdc, LAYOUT_RTL ); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret); SetRect(&expect, 159, 70, 99, 130); ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); SetRect(&set_rect, 50, 25, 30, 35); ret = SetBoundsRect(hdc, &set_rect, DCB_SET); ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret); SetRect(&expect, 50, 25, 30, 35); ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); pSetLayout( hdc, LAYOUT_LTR ); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_SET, "GetBoundsRect returned %x\n", ret); SetRect(&expect, 149, 25, 169, 35); ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); } /* empty rect resets, except on nt4 */ SetRect(&expect, 20, 20, 10, 10); ret = SetBoundsRect(hdc, &set_rect, DCB_SET); ok(ret == (DCB_SET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_RESET || broken(ret == DCB_SET) /* nt4 */, "GetBoundsRect returned %x\n", ret); if (ret == DCB_RESET) { SetRect(&expect, 0, 0, 0, 0); ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); SetRect(&expect, 20, 20, 20, 20); ret = SetBoundsRect(hdc, &set_rect, DCB_SET); ok(ret == (DCB_RESET | DCB_DISABLE), "SetBoundsRect returned %x\n", ret); ret = GetBoundsRect(hdc, &rect, 0); ok(ret == DCB_RESET, "GetBoundsRect returned %x\n", ret); SetRect(&expect, 0, 0, 0, 0); ok(EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom); } DeleteDC( hdc ); DeleteObject( bitmap ); } static void test_desktop_colorres(void) { HDC hdc = GetDC(NULL); int bitspixel, colorres; bitspixel = GetDeviceCaps(hdc, BITSPIXEL); ok(bitspixel != 0, "Expected to get valid BITSPIXEL capability value\n"); colorres = GetDeviceCaps(hdc, COLORRES); ok(colorres != 0 || broken(colorres == 0), /* Win9x */ "Expected to get valid COLORRES capability value\n"); if (colorres) { switch (bitspixel) { case 8: ok(colorres == 18, "Expected COLORRES to be 18, got %d\n", colorres); break; case 16: ok(colorres == 16, "Expected COLORRES to be 16, got %d\n", colorres); break; case 24: case 32: ok(colorres == 24, "Expected COLORRES to be 24, got %d\n", bitspixel); break; default: ok(0, "Got unknown BITSPIXEL %d with COLORRES %d\n", bitspixel, colorres); break; } } ReleaseDC(NULL, hdc); } static void test_gamma(void) { BOOL ret; HDC hdc = GetDC(NULL); WORD oldramp[3][256], ramp[3][256]; INT i; ret = GetDeviceGammaRamp(hdc, &oldramp); if (!ret) { win_skip("GetDeviceGammaRamp failed, skipping tests\n"); goto done; } /* try to set back old ramp */ ret = SetDeviceGammaRamp(hdc, &oldramp); if (!ret) { win_skip("SetDeviceGammaRamp failed, skipping tests\n"); goto done; } memcpy(ramp, oldramp, sizeof(ramp)); /* set one color ramp to zeros */ memset(ramp[0], 0, sizeof(ramp[0])); ret = SetDeviceGammaRamp(hdc, &ramp); ok(!ret, "SetDeviceGammaRamp succeeded\n"); /* set one color ramp to a flat straight rising line */ for (i = 0; i < 256; i++) ramp[0][i] = i; ret = SetDeviceGammaRamp(hdc, &ramp); todo_wine ok(!ret, "SetDeviceGammaRamp succeeded\n"); /* set one color ramp to a steep straight rising line */ for (i = 0; i < 256; i++) ramp[0][i] = i * 256; ret = SetDeviceGammaRamp(hdc, &ramp); ok(ret, "SetDeviceGammaRamp failed\n"); /* try a bright gamma ramp */ ramp[0][0] = 0; ramp[0][1] = 0x7FFF; for (i = 2; i < 256; i++) ramp[0][i] = 0xFFFF; ret = SetDeviceGammaRamp(hdc, &ramp); ok(!ret, "SetDeviceGammaRamp succeeded\n"); /* try ramps which are not uniform */ ramp[0][0] = 0; for (i = 1; i < 256; i++) ramp[0][i] = ramp[0][i - 1] + 512; ret = SetDeviceGammaRamp(hdc, &ramp); ok(ret, "SetDeviceGammaRamp failed\n"); ramp[0][0] = 0; for (i = 2; i < 256; i+=2) { ramp[0][i - 1] = ramp[0][i - 2]; ramp[0][i] = ramp[0][i - 2] + 512; } ret = SetDeviceGammaRamp(hdc, &ramp); ok(ret, "SetDeviceGammaRamp failed\n"); /* cleanup: set old ramp again */ ret = SetDeviceGammaRamp(hdc, &oldramp); ok(ret, "SetDeviceGammaRamp failed\n"); done: ReleaseDC(NULL, hdc); } static HDC create_printer_dc(void) { char buffer[260]; DWORD len; PRINTER_INFO_2A *pbuf = NULL; DRIVER_INFO_3A *dbuf = NULL; HANDLE hprn = 0; HDC hdc = 0; HMODULE winspool = LoadLibraryA( "winspool.drv" ); BOOL (WINAPI *pOpenPrinterA)(LPSTR, HANDLE *, LPPRINTER_DEFAULTSA); BOOL (WINAPI *pGetDefaultPrinterA)(LPSTR, LPDWORD); BOOL (WINAPI *pGetPrinterA)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD); BOOL (WINAPI *pGetPrinterDriverA)(HANDLE, LPSTR, DWORD, LPBYTE, DWORD, LPDWORD); BOOL (WINAPI *pClosePrinter)(HANDLE); pGetDefaultPrinterA = (void *)GetProcAddress( winspool, "GetDefaultPrinterA" ); pOpenPrinterA = (void *)GetProcAddress( winspool, "OpenPrinterA" ); pGetPrinterA = (void *)GetProcAddress( winspool, "GetPrinterA" ); pGetPrinterDriverA = (void *)GetProcAddress( winspool, "GetPrinterDriverA" ); pClosePrinter = (void *)GetProcAddress( winspool, "ClosePrinter" ); if (!pGetDefaultPrinterA || !pOpenPrinterA || !pGetPrinterA || !pGetPrinterDriverA || !pClosePrinter) goto done; len = sizeof(buffer); if (!pGetDefaultPrinterA( buffer, &len )) goto done; if (!pOpenPrinterA( buffer, &hprn, NULL )) goto done; pGetPrinterA( hprn, 2, NULL, 0, &len ); pbuf = HeapAlloc( GetProcessHeap(), 0, len ); if (!pGetPrinterA( hprn, 2, (LPBYTE)pbuf, len, &len )) goto done; pGetPrinterDriverA( hprn, NULL, 3, NULL, 0, &len ); dbuf = HeapAlloc( GetProcessHeap(), 0, len ); if (!pGetPrinterDriverA( hprn, NULL, 3, (LPBYTE)dbuf, len, &len )) goto done; hdc = CreateDCA( dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, pbuf->pDevMode ); trace( "hdc %p for driver '%s' printer '%s' port '%s'\n", hdc, dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName ); done: HeapFree( GetProcessHeap(), 0, dbuf ); HeapFree( GetProcessHeap(), 0, pbuf ); if (hprn) pClosePrinter( hprn ); if (winspool) FreeLibrary( winspool ); if (!hdc) skip( "could not create a DC for the default printer\n" ); return hdc; } static void test_printer_dc(void) { HDC memdc, display_memdc; HBITMAP orig, bmp; DWORD ret; HDC hdc = create_printer_dc(); if (!hdc) return; memdc = CreateCompatibleDC( hdc ); display_memdc = CreateCompatibleDC( 0 ); ok( memdc != NULL, "CreateCompatibleDC failed for printer\n" ); ok( display_memdc != NULL, "CreateCompatibleDC failed for screen\n" ); ret = GetDeviceCaps( hdc, TECHNOLOGY ); ok( ret == DT_RASPRINTER, "wrong type %u\n", ret ); ret = GetDeviceCaps( memdc, TECHNOLOGY ); ok( ret == DT_RASPRINTER, "wrong type %u\n", ret ); ret = GetDeviceCaps( display_memdc, TECHNOLOGY ); ok( ret == DT_RASDISPLAY, "wrong type %u\n", ret ); bmp = CreateBitmap( 100, 100, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL ); orig = SelectObject( memdc, bmp ); ok( orig != NULL, "SelectObject failed\n" ); ok( BitBlt( hdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" ); ok( !SelectObject( display_memdc, bmp ), "SelectObject succeeded\n" ); SelectObject( memdc, orig ); DeleteObject( bmp ); bmp = CreateBitmap( 100, 100, 1, 1, NULL ); orig = SelectObject( display_memdc, bmp ); ok( orig != NULL, "SelectObject failed\n" ); ok( !SelectObject( memdc, bmp ), "SelectObject succeeded\n" ); ok( BitBlt( hdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" ); ok( BitBlt( memdc, 10, 10, 20, 20, display_memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" ); ok( BitBlt( display_memdc, 10, 10, 20, 20, memdc, 0, 0, SRCCOPY ), "BitBlt failed\n" ); ret = GetPixel( hdc, 0, 0 ); ok( ret == CLR_INVALID, "wrong pixel value %x\n", ret ); DeleteDC( memdc ); DeleteDC( display_memdc ); DeleteDC( hdc ); DeleteObject( bmp ); } START_TEST(dc) { pSetLayout = (void *)GetProcAddress( GetModuleHandle("gdi32.dll"), "SetLayout"); test_savedc(); test_savedc_2(); test_GdiConvertToDevmodeW(); test_CreateCompatibleDC(); test_DC_bitmap(); test_DeleteDC(); test_boundsrect(); test_desktop_colorres(); test_gamma(); test_printer_dc(); }