Sweden-Number/dlls/uxtheme/tests/system.c

848 lines
30 KiB
C

/* Unit test suite for uxtheme API functions
*
* Copyright 2006 Paul Vriens
*
* 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
*
*/
#include <stdarg.h>
#include "windows.h"
#include "vfwmsgs.h"
#include "uxtheme.h"
#include "msg.h"
#include "wine/test.h"
static HTHEME (WINAPI * pOpenThemeDataEx)(HWND, LPCWSTR, DWORD);
static HPAINTBUFFER (WINAPI *pBeginBufferedPaint)(HDC, const RECT *, BP_BUFFERFORMAT, BP_PAINTPARAMS *, HDC *);
static HRESULT (WINAPI *pBufferedPaintClear)(HPAINTBUFFER, const RECT *);
static HRESULT (WINAPI *pEndBufferedPaint)(HPAINTBUFFER, BOOL);
static HRESULT (WINAPI *pGetBufferedPaintBits)(HPAINTBUFFER, RGBQUAD **, int *);
static HDC (WINAPI *pGetBufferedPaintDC)(HPAINTBUFFER);
static HDC (WINAPI *pGetBufferedPaintTargetDC)(HPAINTBUFFER);
static HRESULT (WINAPI *pGetBufferedPaintTargetRect)(HPAINTBUFFER, RECT *);
/* For message tests */
enum seq_index
{
PARENT_SEQ_INDEX,
CHILD_SEQ_INDEX,
NUM_MSG_SEQUENCES
};
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
static void init_funcs(void)
{
HMODULE hUxtheme = GetModuleHandleA("uxtheme.dll");
#define UXTHEME_GET_PROC(func) p ## func = (void*)GetProcAddress(hUxtheme, #func)
UXTHEME_GET_PROC(BeginBufferedPaint);
UXTHEME_GET_PROC(BufferedPaintClear);
UXTHEME_GET_PROC(EndBufferedPaint);
UXTHEME_GET_PROC(GetBufferedPaintBits);
UXTHEME_GET_PROC(GetBufferedPaintDC);
UXTHEME_GET_PROC(GetBufferedPaintTargetDC);
UXTHEME_GET_PROC(GetBufferedPaintTargetRect);
UXTHEME_GET_PROC(BufferedPaintClear);
UXTHEME_GET_PROC(OpenThemeDataEx);
#undef UXTHEME_GET_PROC
}
/* Try to make sure pending X events have been processed before continuing */
static void flush_events(void)
{
MSG msg;
int diff = 200;
int min_timeout = 100;
DWORD time = GetTickCount() + diff;
while (diff > 0)
{
if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT)
break;
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
DispatchMessageA(&msg);
diff = time - GetTickCount();
}
}
static LRESULT WINAPI TestSetWindowThemeParentProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static LONG defwndproc_counter;
struct message msg = {0};
LRESULT ret;
/* Only care about WM_THEMECHANGED */
if (message != WM_THEMECHANGED)
return DefWindowProcA(hwnd, message, wParam, lParam);
msg.message = message;
msg.flags = sent | wparam | lparam;
if (defwndproc_counter)
msg.flags |= defwinproc;
msg.wParam = wParam;
msg.lParam = lParam;
add_message(sequences, PARENT_SEQ_INDEX, &msg);
InterlockedIncrement(&defwndproc_counter);
ret = DefWindowProcA(hwnd, message, wParam, lParam);
InterlockedDecrement(&defwndproc_counter);
return ret;
}
static LRESULT WINAPI TestSetWindowThemeChildProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static LONG defwndproc_counter;
struct message msg = {0};
LRESULT ret;
/* Only care about WM_THEMECHANGED */
if (message != WM_THEMECHANGED)
return DefWindowProcA(hwnd, message, wParam, lParam);
msg.message = message;
msg.flags = sent | wparam | lparam;
if (defwndproc_counter)
msg.flags |= defwinproc;
msg.wParam = wParam;
msg.lParam = lParam;
add_message(sequences, CHILD_SEQ_INDEX, &msg);
InterlockedIncrement(&defwndproc_counter);
ret = DefWindowProcA(hwnd, message, wParam, lParam);
InterlockedDecrement(&defwndproc_counter);
return ret;
}
static void test_IsThemed(void)
{
BOOL bThemeActive;
BOOL bAppThemed;
BOOL bTPDefined;
bThemeActive = IsThemeActive();
trace("Theming is %s\n", (bThemeActive) ? "active" : "inactive");
bAppThemed = IsAppThemed();
trace("Test executable is %s\n", (bAppThemed) ? "themed" : "not themed");
SetLastError(0xdeadbeef);
bTPDefined = IsThemePartDefined(NULL, 0 , 0);
ok( bTPDefined == FALSE, "Expected FALSE\n");
ok( GetLastError() == E_HANDLE,
"Expected E_HANDLE, got 0x%08x\n",
GetLastError());
}
static void test_GetWindowTheme(void)
{
HTHEME hTheme;
HWND hWnd;
SetLastError(0xdeadbeef);
hTheme = GetWindowTheme(NULL);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", GetLastError() );
/* Only do the bare minimum to get a valid hwnd */
hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
ok(hWnd != NULL, "Failed to create a test window.\n");
SetLastError(0xdeadbeef);
hTheme = GetWindowTheme(hWnd);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
DestroyWindow(hWnd);
}
static const struct message SetWindowThemeSeq[] =
{
{WM_THEMECHANGED, sent},
{0}
};
static const struct message EmptySeq[] =
{
{0}
};
static void test_SetWindowTheme(void)
{
WNDCLASSA cls = {0};
HWND hWnd, child;
HTHEME hTheme;
HRESULT hRes;
MSG msg;
hRes = SetWindowTheme(NULL, NULL, NULL);
ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
/* Test that WM_THEMECHANGED is sent and not posted to windows */
cls.hInstance = GetModuleHandleA(0);
cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
cls.lpfnWndProc = TestSetWindowThemeParentProcA;
cls.lpszClassName = "TestSetWindowThemeParentClass";
RegisterClassA(&cls);
cls.lpfnWndProc = TestSetWindowThemeChildProcA;
cls.lpszClassName = "TestSetWindowThemeChildClass";
RegisterClassA(&cls);
hWnd = CreateWindowA("TestSetWindowThemeParentClass", "parent",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL);
ok(!!hWnd, "Failed to create a parent window.\n");
child = CreateWindowA("TestSetWindowThemeChildClass", "child", WS_CHILD | WS_VISIBLE, 0, 0, 50,
50, hWnd, 0, 0, NULL);
ok(!!child, "Failed to create a child window.\n");
flush_events();
flush_sequences(sequences, NUM_MSG_SEQUENCES);
hRes = SetWindowTheme(hWnd, NULL, NULL);
ok(hRes == S_OK, "Expected %#x, got %#x.\n", S_OK, hRes);
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
{
struct message recv_msg = {0};
if (msg.message == WM_THEMECHANGED)
{
recv_msg.message = msg.message;
recv_msg.flags = posted | wparam | lparam;
recv_msg.wParam = msg.wParam;
recv_msg.lParam = msg.lParam;
add_message(sequences, msg.hwnd == hWnd ? PARENT_SEQ_INDEX : CHILD_SEQ_INDEX, &recv_msg);
}
DispatchMessageA(&msg);
}
ok_sequence(sequences, PARENT_SEQ_INDEX, SetWindowThemeSeq, "SetWindowTheme parent", FALSE);
ok_sequence(sequences, CHILD_SEQ_INDEX, EmptySeq, "SetWindowTheme child", FALSE);
DestroyWindow(hWnd);
UnregisterClassA("TestSetWindowThemeParentClass", GetModuleHandleA(0));
UnregisterClassA("TestSetWindowThemeChildClass", GetModuleHandleA(0));
/* Only do the bare minimum to get a valid hwnd */
hWnd = CreateWindowExA(0, "button", "test", WS_POPUP, 0, 0, 100, 100, 0, 0, 0, NULL);
ok(hWnd != NULL, "Failed to create a test window.\n");
hRes = SetWindowTheme(hWnd, NULL, NULL);
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
if (IsThemeActive())
{
hTheme = OpenThemeData(hWnd, L"Button");
ok(!!hTheme, "OpenThemeData failed.\n");
CloseThemeData(hTheme);
hRes = SetWindowTheme(hWnd, L"deadbeef", NULL);
ok(hRes == S_OK, "Expected S_OK, got 0x%08x.\n", hRes);
hTheme = OpenThemeData(hWnd, L"Button");
ok(!!hTheme, "OpenThemeData failed.\n");
CloseThemeData(hTheme);
}
else
{
skip("No active theme, skipping rest of SetWindowTheme tests.\n");
}
DestroyWindow(hWnd);
}
static void test_OpenThemeData(void)
{
HTHEME hTheme, hTheme2;
HWND hWnd;
BOOL bThemeActive;
HRESULT hRes;
BOOL bTPDefined;
const WCHAR szInvalidClassList[] = L"DEADBEEF";
const WCHAR szButtonClassList[] = L"Button";
const WCHAR szButtonClassList2[] = L"bUtToN";
const WCHAR szClassList[] = L"Button;ListBox";
bThemeActive = IsThemeActive();
/* All NULL */
SetLastError(0xdeadbeef);
hTheme = OpenThemeData(NULL, NULL);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_POINTER,
"Expected GLE() to be E_POINTER, got 0x%08x\n",
GetLastError());
/* A NULL hWnd and an invalid classlist */
SetLastError(0xdeadbeef);
hTheme = OpenThemeData(NULL, szInvalidClassList);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_PROP_ID_UNSUPPORTED, "Expected 0x%08x, got 0x%08x\n",
E_PROP_ID_UNSUPPORTED, GetLastError() );
SetLastError(0xdeadbeef);
hTheme = OpenThemeData(NULL, szClassList);
if (bThemeActive)
{
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
}
else
{
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_PROP_ID_UNSUPPORTED, "Expected 0x%08x, got 0x%08x\n",
E_PROP_ID_UNSUPPORTED, GetLastError() );
}
/* Only do the bare minimum to get a valid hdc */
hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
if (!hWnd) return;
SetLastError(0xdeadbeef);
hTheme = OpenThemeData(hWnd, NULL);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_POINTER,
"Expected GLE() to be E_POINTER, got 0x%08x\n",
GetLastError());
SetLastError(0xdeadbeef);
hTheme = OpenThemeData(hWnd, szInvalidClassList);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_PROP_ID_UNSUPPORTED, "Expected 0x%08x, got 0x%08x\n",
E_PROP_ID_UNSUPPORTED, GetLastError() );
if (!bThemeActive)
{
SetLastError(0xdeadbeef);
hTheme = OpenThemeData(hWnd, szButtonClassList);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_PROP_ID_UNSUPPORTED, "Expected 0x%08x, got 0x%08x\n",
E_PROP_ID_UNSUPPORTED, GetLastError() );
skip("No active theme, skipping rest of OpenThemeData tests\n");
return;
}
/* Only do the next checks if we have an active theme */
SetLastError(0xdeadbeef);
hTheme = OpenThemeData(hWnd, szButtonClassList);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
/* Test with bUtToN instead of Button */
SetLastError(0xdeadbeef);
hTheme = OpenThemeData(hWnd, szButtonClassList2);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
SetLastError(0xdeadbeef);
hTheme = OpenThemeData(hWnd, szClassList);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
/* GetWindowTheme should return the last handle opened by OpenThemeData */
SetLastError(0xdeadbeef);
hTheme2 = GetWindowTheme(hWnd);
ok( hTheme == hTheme2, "Expected the same HTHEME handle (%p<->%p)\n",
hTheme, hTheme2);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
hRes = CloseThemeData(hTheme);
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
/* Close a second time */
hRes = CloseThemeData(hTheme);
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
/* See if closing makes a difference for GetWindowTheme */
SetLastError(0xdeadbeef);
hTheme2 = NULL;
hTheme2 = GetWindowTheme(hWnd);
ok( hTheme == hTheme2, "Expected the same HTHEME handle (%p<->%p)\n",
hTheme, hTheme2);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
SetLastError(0xdeadbeef);
bTPDefined = IsThemePartDefined(hTheme, 0 , 0);
todo_wine
{
ok( bTPDefined == FALSE, "Expected FALSE\n");
ok( GetLastError() == ERROR_SUCCESS,
"Expected ERROR_SUCCESS, got 0x%08x\n",
GetLastError());
}
DestroyWindow(hWnd);
}
static void test_OpenThemeDataEx(void)
{
HTHEME hTheme;
HWND hWnd;
BOOL bThemeActive;
const WCHAR szInvalidClassList[] = L"DEADBEEF";
const WCHAR szButtonClassList[] = L"Button";
const WCHAR szButtonClassList2[] = L"bUtToN";
const WCHAR szClassList[] = L"Button;ListBox";
if (!pOpenThemeDataEx)
{
win_skip("OpenThemeDataEx not available\n");
return;
}
bThemeActive = IsThemeActive();
/* All NULL */
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(NULL, NULL, 0);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_POINTER,
"Expected GLE() to be E_POINTER, got 0x%08x\n",
GetLastError());
/* A NULL hWnd and an invalid classlist without flags */
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(NULL, szInvalidClassList, 0);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_PROP_ID_UNSUPPORTED, "Expected 0x%08x, got 0x%08x\n",
E_PROP_ID_UNSUPPORTED, GetLastError() );
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(NULL, szClassList, 0);
if (bThemeActive)
{
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
}
else
{
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_PROP_ID_UNSUPPORTED, "Expected 0x%08x, got 0x%08x\n",
E_PROP_ID_UNSUPPORTED, GetLastError() );
}
/* Only do the bare minimum to get a valid hdc */
hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
if (!hWnd) return;
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(hWnd, NULL, 0);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_POINTER,
"Expected GLE() to be E_POINTER, got 0x%08x\n",
GetLastError());
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(hWnd, szInvalidClassList, 0);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_PROP_ID_UNSUPPORTED, "Expected 0x%08x, got 0x%08x\n",
E_PROP_ID_UNSUPPORTED, GetLastError() );
if (!bThemeActive)
{
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(hWnd, szButtonClassList, 0);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == E_PROP_ID_UNSUPPORTED, "Expected 0x%08x, got 0x%08x\n",
E_PROP_ID_UNSUPPORTED, GetLastError() );
skip("No active theme, skipping rest of OpenThemeDataEx tests\n");
return;
}
/* Only do the next checks if we have an active theme */
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(hWnd, szButtonClassList, 0);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(hWnd, szButtonClassList, OTD_FORCE_RECT_SIZING);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(hWnd, szButtonClassList, OTD_NONCLIENT);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(hWnd, szButtonClassList, 0x3);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
/* Test with bUtToN instead of Button */
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(hWnd, szButtonClassList2, 0);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
SetLastError(0xdeadbeef);
hTheme = pOpenThemeDataEx(hWnd, szClassList, 0);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
ok( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got 0x%08x\n", GetLastError() );
DestroyWindow(hWnd);
}
static void test_GetCurrentThemeName(void)
{
BOOL bThemeActive;
HRESULT hRes;
WCHAR currentTheme[MAX_PATH];
WCHAR currentColor[MAX_PATH];
WCHAR currentSize[MAX_PATH];
bThemeActive = IsThemeActive();
/* All NULLs */
hRes = GetCurrentThemeName(NULL, 0, NULL, 0, NULL, 0);
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
/* Number of characters given is 0 */
hRes = GetCurrentThemeName(currentTheme, 0, NULL, 0, NULL, 0);
if (bThemeActive)
ok( hRes == S_OK || broken(hRes == E_FAIL /* WinXP SP1 */), "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
hRes = GetCurrentThemeName(currentTheme, 2, NULL, 0, NULL, 0);
if (bThemeActive)
todo_wine
ok(hRes == E_NOT_SUFFICIENT_BUFFER ||
broken(hRes == E_FAIL /* WinXP SP1 */),
"Expected E_NOT_SUFFICIENT_BUFFER, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
/* The same is true if the number of characters is too small for Color and/or Size */
hRes = GetCurrentThemeName(currentTheme, ARRAY_SIZE(currentTheme), currentColor, 2,
currentSize, ARRAY_SIZE(currentSize));
if (bThemeActive)
todo_wine
ok(hRes == E_NOT_SUFFICIENT_BUFFER ||
broken(hRes == E_FAIL /* WinXP SP1 */),
"Expected E_NOT_SUFFICIENT_BUFFER, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
/* Given number of characters is correct */
hRes = GetCurrentThemeName(currentTheme, ARRAY_SIZE(currentTheme), NULL, 0, NULL, 0);
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
/* Given number of characters for the theme name is too large */
hRes = GetCurrentThemeName(currentTheme, sizeof(currentTheme), NULL, 0, NULL, 0);
if (bThemeActive)
ok( hRes == E_POINTER || hRes == S_OK, "Expected E_POINTER or S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED ||
hRes == E_POINTER, /* win2k3 */
"Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
/* The too large case is only for the theme name, not for color name or size name */
hRes = GetCurrentThemeName(currentTheme, ARRAY_SIZE(currentTheme), currentColor,
sizeof(currentTheme), currentSize, ARRAY_SIZE(currentSize));
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
hRes = GetCurrentThemeName(currentTheme, ARRAY_SIZE(currentTheme), currentColor,
ARRAY_SIZE(currentTheme), currentSize, sizeof(currentSize));
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
/* Correct call */
hRes = GetCurrentThemeName(currentTheme, ARRAY_SIZE(currentTheme), currentColor,
ARRAY_SIZE(currentColor), currentSize, ARRAY_SIZE(currentSize));
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
}
static void test_CloseThemeData(void)
{
HRESULT hRes;
hRes = CloseThemeData(NULL);
ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
hRes = CloseThemeData(INVALID_HANDLE_VALUE);
ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
}
static void test_buffer_dc_props(HDC hdc, const RECT *rect)
{
static const XFORM ident = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
XFORM xform;
POINT org;
RECT box;
BOOL ret;
ret = GetWorldTransform(hdc, &xform);
ok(ret, "Failed to get world transform\n");
ok(!memcmp(&xform, &ident, sizeof(xform)), "Unexpected world transform\n");
ret = GetViewportOrgEx(hdc, &org);
ok(ret, "Failed to get vport origin\n");
ok(org.x == 0 && org.y == 0, "Unexpected vport origin\n");
ret = GetWindowOrgEx(hdc, &org);
ok(ret, "Failed to get vport origin\n");
ok(org.x == rect->left && org.y == rect->top, "Unexpected window origin\n");
ret = GetClipBox(hdc, &box);
ok(ret, "Failed to get clip box\n");
ok(box.left == rect->left && box.top == rect->top, "Unexpected clip box\n");
ok(GetGraphicsMode(hdc) == GM_COMPATIBLE, "wrong graphics mode\n");
}
static void test_buffered_paint(void)
{
HDC target, src, hdc, screen_dc;
BP_PAINTPARAMS params = { 0 };
BP_BUFFERFORMAT format;
HPAINTBUFFER buffer;
RECT rect, rect2;
RGBQUAD *bits;
HBITMAP hbm;
HRESULT hr;
int row;
if (!pBeginBufferedPaint)
{
win_skip("Buffered painting API is not supported.\n");
return;
}
buffer = pBeginBufferedPaint(NULL, NULL, BPBF_COMPATIBLEBITMAP,
NULL, NULL);
ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
target = CreateCompatibleDC(0);
buffer = pBeginBufferedPaint(target, NULL, BPBF_COMPATIBLEBITMAP,
NULL, NULL);
ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
params.cbSize = sizeof(params);
buffer = pBeginBufferedPaint(target, NULL, BPBF_COMPATIBLEBITMAP,
&params, NULL);
ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
src = (void *)0xdeadbeef;
buffer = pBeginBufferedPaint(target, NULL, BPBF_COMPATIBLEBITMAP,
&params, &src);
ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
ok(src == NULL, "Unexpected buffered dc %p\n", src);
/* target rect is mandatory */
SetRectEmpty(&rect);
src = (void *)0xdeadbeef;
buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP,
&params, &src);
ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
ok(src == NULL, "Unexpected buffered dc %p\n", src);
/* inverted rectangle */
SetRect(&rect, 10, 0, 5, 5);
src = (void *)0xdeadbeef;
buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP,
&params, &src);
ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
ok(src == NULL, "Unexpected buffered dc %p\n", src);
SetRect(&rect, 0, 10, 5, 0);
src = (void *)0xdeadbeef;
buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP,
&params, &src);
ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
ok(src == NULL, "Unexpected buffered dc %p\n", src);
/* valid rectangle, no target dc */
SetRect(&rect, 0, 0, 5, 5);
src = (void *)0xdeadbeef;
buffer = pBeginBufferedPaint(NULL, &rect, BPBF_COMPATIBLEBITMAP,
&params, &src);
ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
ok(src == NULL, "Unexpected buffered dc %p\n", src);
SetRect(&rect, 0, 0, 5, 5);
src = NULL;
buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP,
&params, &src);
ok(buffer != NULL, "Unexpected buffer %p\n", buffer);
ok(src != NULL, "Expected buffered dc\n");
hr = pEndBufferedPaint(buffer, FALSE);
ok(hr == S_OK, "Unexpected return code %#x\n", hr);
SetRect(&rect, 0, 0, 5, 5);
buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP,
&params, &src);
ok(buffer != NULL, "Unexpected buffer %p\n", buffer);
/* clearing */
hr = pBufferedPaintClear(NULL, NULL);
todo_wine
ok(hr == E_FAIL, "Unexpected return code %#x\n", hr);
hr = pBufferedPaintClear(buffer, NULL);
todo_wine
ok(hr == S_OK, "Unexpected return code %#x\n", hr);
/* access buffer attributes */
hdc = pGetBufferedPaintDC(buffer);
ok(hdc == src, "Unexpected hdc, %p, buffered dc %p\n", hdc, src);
hdc = pGetBufferedPaintTargetDC(buffer);
ok(hdc == target, "Unexpected target hdc %p, original %p\n", hdc, target);
hr = pGetBufferedPaintTargetRect(NULL, NULL);
ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);
hr = pGetBufferedPaintTargetRect(buffer, NULL);
ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);
hr = pGetBufferedPaintTargetRect(NULL, &rect2);
ok(hr == E_FAIL, "Unexpected return code %#x\n", hr);
SetRectEmpty(&rect2);
hr = pGetBufferedPaintTargetRect(buffer, &rect2);
ok(hr == S_OK, "Unexpected return code %#x\n", hr);
ok(EqualRect(&rect, &rect2), "Wrong target rect\n");
hr = pEndBufferedPaint(buffer, FALSE);
ok(hr == S_OK, "Unexpected return code %#x\n", hr);
/* invalid buffer handle */
hr = pEndBufferedPaint(NULL, FALSE);
ok(hr == E_INVALIDARG, "Unexpected return code %#x\n", hr);
hdc = pGetBufferedPaintDC(NULL);
ok(hdc == NULL, "Unexpected hdc %p\n", hdc);
hdc = pGetBufferedPaintTargetDC(NULL);
ok(hdc == NULL, "Unexpected target hdc %p\n", hdc);
hr = pGetBufferedPaintTargetRect(NULL, &rect2);
ok(hr == E_FAIL, "Unexpected return code %#x\n", hr);
hr = pGetBufferedPaintTargetRect(NULL, NULL);
ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);
bits = (void *)0xdeadbeef;
row = 10;
hr = pGetBufferedPaintBits(NULL, &bits, &row);
ok(hr == E_FAIL, "Unexpected return code %#x\n", hr);
ok(row == 10, "Unexpected row count %d\n", row);
ok(bits == (void *)0xdeadbeef, "Unexpected data pointer %p\n", bits);
hr = pGetBufferedPaintBits(NULL, NULL, NULL);
ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);
hr = pGetBufferedPaintBits(NULL, &bits, NULL);
ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);
hr = pGetBufferedPaintBits(NULL, NULL, &row);
ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);
screen_dc = GetDC(0);
hdc = CreateCompatibleDC(screen_dc);
ok(hdc != NULL, "Failed to create a DC\n");
hbm = CreateCompatibleBitmap(screen_dc, 64, 64);
ok(hbm != NULL, "Failed to create a bitmap\n");
SelectObject(hdc, hbm);
ReleaseDC(0, screen_dc);
SetRect(&rect, 1, 2, 34, 56);
buffer = pBeginBufferedPaint(hdc, &rect, BPBF_COMPATIBLEBITMAP, NULL, &src);
test_buffer_dc_props(src, &rect);
hr = pEndBufferedPaint(buffer, FALSE);
ok(hr == S_OK, "Unexpected return code %#x\n", hr);
DeleteObject(hbm);
DeleteDC(hdc);
buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP, NULL, &src);
test_buffer_dc_props(src, &rect);
hr = pEndBufferedPaint(buffer, FALSE);
ok(hr == S_OK, "Unexpected return code %#x\n", hr);
/* access buffer bits */
for (format = BPBF_COMPATIBLEBITMAP; format <= BPBF_TOPDOWNMONODIB; format++)
{
buffer = pBeginBufferedPaint(target, &rect, format, &params, &src);
/* only works for DIB buffers */
bits = NULL;
row = 0;
hr = pGetBufferedPaintBits(buffer, &bits, &row);
if (format == BPBF_COMPATIBLEBITMAP)
ok(hr == E_FAIL, "Unexpected return code %#x\n", hr);
else
{
ok(hr == S_OK, "Unexpected return code %#x\n", hr);
ok(bits != NULL, "Bitmap bits %p\n", bits);
ok(row >= (rect.right - rect.left), "format %d: bitmap width %d\n", format, row);
}
hr = pEndBufferedPaint(buffer, FALSE);
ok(hr == S_OK, "Unexpected return code %#x\n", hr);
}
DeleteDC(target);
}
START_TEST(system)
{
init_funcs();
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
/* No real functional theme API tests will be done (yet). The current tests
* only show input/return behaviour
*/
test_IsThemed();
test_GetWindowTheme();
test_SetWindowTheme();
test_OpenThemeData();
test_OpenThemeDataEx();
test_GetCurrentThemeName();
test_CloseThemeData();
test_buffered_paint();
}