remove_definitions(-DWINVER=0x502 -D_WIN32_WINNT=0x502)
-add_definitions(-DWINVER=0x600 -D_WIN32_WINNT=0x600)
+add_definitions(-DWINVER=0x602 -D_WIN32_WINNT=0x602)
if(MSVC)
# Disable warning C4477 (printf format warnings)
menu.c
monitor.c
msg.c
+ rawinput.c
resource.c
scroll.c
static.c
ok(0, "Returned: %d\n", ret);
}
- recips = BSM_APPLICATIONS;
- ResetEvent(hevent);
- ret = broadcast( BSF_POSTMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, 0 );
- ok(ret==1, "Returned: %d\n", ret);
- ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
- PulseEvent(hevent);
-
SetLastError( 0xdeadbeef );
recips = BSM_APPLICATIONS;
ret = broadcast( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0 );
- if (ret)
- {
- ok(ret==1, "Returned: %d\n", ret);
- ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n");
- PulseEvent(hevent);
-
- recips = BSM_APPLICATIONS;
- ret = broadcast( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY );
- ok(ret==1, "Returned: %d\n", ret);
- ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
- PulseEvent(hevent);
-
- recips = BSM_APPLICATIONS;
- ret = broadcast( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY );
- ok(!ret, "Returned: %d\n", ret);
- ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
- PulseEvent(hevent);
- }
- else /* BSF_SENDNOTIFYMESSAGE not supported on NT4 */
- ok( GetLastError() == ERROR_INVALID_PARAMETER, "failed with err %u\n", GetLastError() );
+ ok(ret==1, "Returned: %d\n", ret);
+ ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n");
+ PulseEvent(hevent);
recips = BSM_APPLICATIONS;
- ret = broadcast( 0, &recips, WM_NULL, 100, 0 );
+ ret = broadcast( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY );
ok(ret==1, "Returned: %d\n", ret);
ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
PulseEvent(hevent);
ok(0, "Returned: %d\n", ret);
}
- recips = BSM_APPLICATIONS;
- ResetEvent(hevent);
- ret = broadcastex( BSF_POSTMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
- ok(ret==1, "Returned: %d\n", ret);
- ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
- PulseEvent(hevent);
-
recips = BSM_APPLICATIONS;
ret = broadcastex( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0, NULL );
ok(ret==1, "Returned: %d\n", ret);
ok(ret==1, "Returned: %d\n", ret);
ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
PulseEvent(hevent);
-
- recips = BSM_APPLICATIONS;
- ret = broadcastex( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL );
- ok(!ret, "Returned: %d\n", ret);
- ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
- PulseEvent(hevent);
-
- recips = BSM_APPLICATIONS;
- ret = broadcastex( 0, &recips, WM_NULL, 100, 0, NULL );
- ok(ret==1, "Returned: %d\n", ret);
- ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
- PulseEvent(hevent);
-}
-
-static void test_noprivileges(void)
-{
- HANDLE token;
- DWORD recips;
- BOOL ret;
-
- static const DWORD BSM_ALL_RECIPS = BSM_VXDS | BSM_NETDRIVER |
- BSM_INSTALLABLEDRIVERS | BSM_APPLICATIONS;
-
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
- {
- skip("Can't open security token for process\n");
- return;
- }
- if (!AdjustTokenPrivileges(token, TRUE, NULL, 0, NULL, NULL))
- {
- skip("Can't adjust security token for process\n");
- return;
- }
-
- trace("Trying privileged edition!\n");
- SetLastError(0xcafebabe);
- recips = BSM_ALLDESKTOPS;
- ResetEvent(hevent);
- ret = BroadcastSystemMessageExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
- ok(ret==1, "Returned: %d error %u\n", ret, GetLastError());
- ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
- ok(recips == BSM_ALLDESKTOPS ||
- recips == BSM_ALL_RECIPS, /* win2k3 */
- "Received by: %08x\n", recips);
- PulseEvent(hevent);
-
- SetLastError(0xcafebabe);
- recips = BSM_ALLCOMPONENTS;
- ResetEvent(hevent);
- ret = BroadcastSystemMessageExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
- ok(ret==1, "Returned: %d error %u\n", ret, GetLastError());
- ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
- ok(recips == BSM_ALLCOMPONENTS ||
- recips == BSM_ALL_RECIPS, /* win2k3 */
- "Received by: %08x\n", recips);
- PulseEvent(hevent);
-
- SetLastError(0xcafebabe);
- recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS;
- ResetEvent(hevent);
- ret = BroadcastSystemMessageExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
- ok(ret==1, "Returned: %d error %u\n", ret, GetLastError());
- ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
- ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS) ||
- recips == BSM_APPLICATIONS, /* win2k3 */
- "Received by: %08x\n", recips);
- PulseEvent(hevent);
-
- SetLastError(0xcafebabe);
- recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS;
- ResetEvent(hevent);
- ret = BroadcastSystemMessageExW( BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL );
- ok(!ret, "Returned: %d\n", ret);
- ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
- ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS) ||
- recips == BSM_APPLICATIONS, /* win2k3 */
- "Received by: %08x\n", recips);
- PulseEvent(hevent);
}
START_TEST(broadcast)
trace("Running BroadcastSystemMessageExW tests\n");
test_parametersEx(BroadcastSystemMessageExW);
-
- trace("Attempting privileges checking tests\n");
- test_noprivileges();
}
return;
ok(classatom, "failed to register class\n");
+ ok(GetClipboardFormatNameW(classatom, str, ARRAY_SIZE(str)) != 0, "atom not found\n");
+
ok(!RegisterClassW (&cls),
"RegisterClass of the same class should fail for the second time\n");
}
/* check GetClassName */
- i = GetClassNameW(hTestWnd, str, sizeof(str)/sizeof(str[0]));
+ i = GetClassNameW(hTestWnd, str, ARRAY_SIZE(str));
ok(i == lstrlenW(className),
"GetClassName returned incorrect length\n");
ok(!lstrcmpW(className,str),
ok(UnregisterClassW(className, hInstance),
"UnregisterClass() failed\n");
+ ok(GetClipboardFormatNameW(classatom, str, ARRAY_SIZE(str)) == 0,
+ "atom still found\n");
return;
}
"ScrollBar",
"#32770", /* dialog */
};
- static const int NUM_NORMAL_CLASSES = (sizeof(NORMAL_CLASSES)/sizeof(NORMAL_CLASSES[0]));
static const char classA[] = "deftest";
static const WCHAR classW[] = {'d','e','f','t','e','s','t',0};
WCHAR unistring[] = {0x142, 0x40e, 0x3b4, 0}; /* a string that would be destroyed by a W->A->W conversion */
WCHAR buf[128];
ATOM atom;
HWND hwnd;
- int i;
+ unsigned int i;
pDefWindowProcA = (void *)GetProcAddress(GetModuleHandleA("user32.dll"), "DefWindowProcA");
pDefWindowProcW = (void *)GetProcAddress(GetModuleHandleA("user32.dll"), "DefWindowProcW");
ok(IsWindowUnicode(hwnd) ||
broken(!IsWindowUnicode(hwnd)) /* Windows 8 and 10 */,
"Windows should be Unicode\n");
- SendMessageW(hwnd, WM_GETTEXT, sizeof(buf) / sizeof(buf[0]), (LPARAM)buf);
+ SendMessageW(hwnd, WM_GETTEXT, ARRAY_SIZE(buf), (LPARAM)buf);
if (IsWindowUnicode(hwnd))
ok(memcmp(buf, unistring, sizeof(unistring)) == 0, "WM_GETTEXT invalid return\n");
else
/* For most of the builtin controls both GetWindowLongPtrA and W returns a pointer that is executed directly
* by CallWindowProcA/W */
- for (i = 0; i < NUM_NORMAL_CLASSES; i++)
+ for (i = 0; i < ARRAY_SIZE(NORMAL_CLASSES); i++)
{
WNDPROC procA, procW;
hwnd = CreateWindowExA(0, NORMAL_CLASSES[i], classA, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 680, 260,
static LRESULT WINAPI TestDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- return DefWindowProcA(hWnd, uMsg, wParam, lParam);
+ return DefDlgProcA(hWnd, uMsg, wParam, lParam);
}
static BOOL RegisterTestDialog(HINSTANCE hInstance)
static void test_extra_values(void)
{
int i;
- for(i=0; i< sizeof(extra_values)/sizeof(extra_values[0]); i++)
+ for(i = 0; i < ARRAY_SIZE(extra_values); i++)
{
WNDCLASSEXA wcx;
BOOL ret = GetClassInfoExA(NULL,extra_values[i].name,&wcx);
SetLastError(0xdeadbeef);
ret = GetClassInfoExA(0, "static", &wcx);
ok(ret, "GetClassInfoExA() error %d\n", GetLastError());
+ ok(GetLastError() == 0xdeadbeef, "Unexpected error code %d\n", GetLastError());
ok(wcx.cbSize == 0, "expected 0, got %u\n", wcx.cbSize);
ok(wcx.lpfnWndProc != NULL, "got null proc\n");
name++;
- GetTempPathA(sizeof(path)/sizeof(path[0]), path);
+ GetTempPathA(ARRAY_SIZE(path), path);
strcat(path, "comctl32_class.manifest");
create_manifest_file(path, comctl32_manifest);
if (!ret)
goto skiptest;
- MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, sizeof(nameW)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, ARRAY_SIZE(nameW));
ret = GetClassInfoW( 0, nameW, &wcW );
ok( ret, "GetClassInfoW failed for %s\n", name );
module = GetModuleHandleA( "comctl32" );
ret = GetClassInfoA( 0, name, &wcA );
ok( ret || broken(!ret) /* <= winxp */, "GetClassInfoA failed for %s\n", name );
if (!ret) return;
- MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, sizeof(nameW)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, ARRAY_SIZE(nameW));
ret = GetClassInfoW( 0, nameW, &wcW );
ok( ret, "GetClassInfoW failed for %s\n", name );
module = GetModuleHandleA( "comctl32" );
};
winetest_get_mainargs( &argv );
- for (i = 0; i < sizeof(classes) / sizeof(classes[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(classes); i++)
{
memset( &startup, 0, sizeof(startup) );
startup.cb = sizeof( startup );
ATOM class;
HINSTANCE hinst;
char buff[64];
- HWND hwnd;
+ HWND hwnd, hwnd2;
char path[MAX_PATH];
- GetTempPathA(sizeof(path)/sizeof(path[0]), path);
+ GetTempPathA(ARRAY_SIZE(path), path);
strcat(path, "actctx_classes.manifest");
create_manifest_file(path, main_manifest);
hwnd = CreateWindowExA(0, testclass, "test", 0, 0, 0, 0, 0, 0, 0, hinst, 0);
ok(hwnd != NULL, "Failed to create a window.\n");
+ hwnd2 = FindWindowExA(NULL, NULL, "MyTestClass", NULL);
+ ok(hwnd2 == hwnd, "Failed to find test window.\n");
+
+ hwnd2 = FindWindowExA(NULL, NULL, "4.3.2.1!MyTestClass", NULL);
+ ok(hwnd2 == NULL, "Unexpected find result %p.\n", hwnd2);
+
ret = GetClassNameA(hwnd, buff, sizeof(buff));
ok(ret, "Failed to get class name.\n");
ok(!strcmp(buff, testclass), "Unexpected class name.\n");
DestroyWindow(hwnd);
+ hwnd = CreateWindowExA(0, "4.3.2.1!MyTestClass", "test", 0, 0, 0, 0, 0, 0, 0, hinst, 0);
+ ok(hwnd != NULL, "Failed to create a window.\n");
+
+ hwnd2 = FindWindowExA(NULL, NULL, "MyTestClass", NULL);
+ ok(hwnd2 == hwnd, "Failed to find test window.\n");
+
+ hwnd2 = FindWindowExA(NULL, NULL, "4.3.2.1!MyTestClass", NULL);
+ ok(hwnd2 == NULL, "Unexpected find result %p.\n", hwnd2);
+
+ DestroyWindow(hwnd);
+
ret = UnregisterClassA("MyTestClass", hinst);
ok(!ret, "Unexpected ret value %d.\n", ret);
r = CloseClipboard();
ok(r, "gle %d\n", GetLastError());
- for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
{
r = OpenClipboard(NULL);
ok(r, "%u: gle %d\n", i, GetLastError());
char bufferA[12];
WCHAR bufferW[12];
- for (i = 0; i < sizeof(test_data) / sizeof(test_data[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(test_data); i++)
{
/* 1-byte Unicode strings crash on Win64 */
#ifdef _WIN64
0xffffffff
};
-#ifndef __REACTOS__
-#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
-#endif
-
static void test_LoadImageBitmap(const char * test_desc, HBITMAP hbm)
{
BITMAP bm;
HeapFree(GetProcessHeap(), 0, buf);
}
+static void create_bitmap_file(const char *filename, const BITMAPINFO *bmi, const unsigned char *bits)
+{
+ unsigned int clr_used, bmi_size, bits_size, stride;
+ const BITMAPINFOHEADER *h = &bmi->bmiHeader;
+ BITMAPFILEHEADER hdr;
+ DWORD bytes_written;
+ HANDLE file;
+ BOOL ret;
+
+ clr_used = h->biBitCount <= 8 ? 1u << h->biBitCount : 0;
+ stride = ((h->biBitCount * h->biWidth + 7) / 8 + 3) & ~3;
+ bits_size = h->biHeight * stride;
+ bmi_size = h->biSize + clr_used * sizeof(RGBQUAD);
+
+ hdr.bfType = 0x4d42;
+ hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + bmi_size;
+ hdr.bfSize = hdr.bfOffBits + bits_size;
+ hdr.bfReserved1 = 0;
+ hdr.bfReserved2 = 0;
+
+ file = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed, result %u.\n", GetLastError());
+ ret = WriteFile(file, &hdr, sizeof(hdr), &bytes_written, NULL);
+ ok(ret && bytes_written == sizeof(hdr), "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n",
+ ret, bytes_written);
+ ret = WriteFile(file, bmi, bmi_size, &bytes_written, NULL);
+ ok(ret && bytes_written == bmi_size, "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n",
+ ret, bytes_written);
+ ret = WriteFile(file, bits, bits_size, &bytes_written, NULL);
+ ok(ret && bytes_written == bits_size, "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n",
+ ret, bytes_written);
+ CloseHandle(file);
+}
+
+static void test_LoadImage_working_directory_run(char *path)
+{
+ DWORD bytes_written;
+ HANDLE handle;
+ BOOL ret;
+ char path_icon[MAX_PATH];
+ char path_image[MAX_PATH];
+ static const test_icon_entries_t icon_desc = {32, 32};
+
+ sprintf(path_icon, "%s\\icon.ico", path);
+ sprintf(path_image, "%s\\test.bmp", path);
+
+ /* Create Files */
+ create_ico_file(path_icon, &icon_desc, 1);
+
+ handle = CreateFileA(path_image, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+ ok(handle != INVALID_HANDLE_VALUE, "run %s: CreateFileA failed. %u\n", path, GetLastError());
+ ret = WriteFile(handle, bmpimage, sizeof(bmpimage), &bytes_written, NULL);
+ ok(ret && bytes_written == sizeof(bmpimage), "run %s: Test file created improperly.\n", path);
+ CloseHandle(handle);
+
+ /* Test cursor */
+ handle = LoadImageA(NULL, "icon.ico", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
+ ok(handle != NULL, "run %s: LoadImage() failed.\n", path);
+
+ ret = DestroyIcon(handle);
+ ok(ret, "run %s: DestroyIcon failed: %d\n", path, GetLastError());
+
+ /* Test image */
+ handle = LoadImageA(NULL, "test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
+ ok(handle != NULL, "run %s: LoadImageA failed.\n", path);
+
+ ret = DeleteObject(handle);
+ ok(ret, "run %s: DeleteObject failed: %d\n", path, GetLastError());
+
+ /* Cleanup */
+ ret = DeleteFileA(path_image);
+ ok(ret, "run %s: DeleteFileA failed: %d\n", path, GetLastError());
+ ret = DeleteFileA(path_icon);
+ ok(ret, "run %s: DeleteFileA failed: %d\n", path, GetLastError());
+}
+
+static void test_LoadImage_working_directory(void)
+{
+ char old_working_dir[MAX_PATH];
+ char temp_dir_current[MAX_PATH];
+ char temp_dir_PATH[MAX_PATH];
+ char executable_path[MAX_PATH];
+ int pos_slash;
+ char old_PATH[10000];
+ char new_PATH[10000];
+ BOOL ret;
+
+ GetCurrentDirectoryA(ARRAY_SIZE(old_working_dir), old_working_dir);
+
+ GetTempPathA(ARRAY_SIZE(temp_dir_current), temp_dir_current);
+ strcat(temp_dir_current, "wine-test-dir-current\\");
+ GetTempPathA(ARRAY_SIZE(temp_dir_PATH), temp_dir_PATH);
+ strcat(temp_dir_PATH, "wine-test-dir-path\\");
+
+ GetModuleFileNameA(NULL, executable_path, ARRAY_SIZE(executable_path));
+ pos_slash = strrchr(executable_path, '\\') - executable_path;
+ executable_path[pos_slash + 1] = 0;
+
+ CreateDirectoryA(temp_dir_current, NULL);
+ CreateDirectoryA(temp_dir_PATH, NULL);
+
+ SetCurrentDirectoryA(temp_dir_current);
+
+ GetEnvironmentVariableA("PATH", old_PATH, ARRAY_SIZE(old_PATH));
+ sprintf(new_PATH, "%s;%s", old_PATH, temp_dir_PATH);
+ SetEnvironmentVariableA("PATH", new_PATH);
+
+ test_LoadImage_working_directory_run(temp_dir_current);
+ test_LoadImage_working_directory_run(executable_path);
+ test_LoadImage_working_directory_run(temp_dir_PATH);
+
+ SetCurrentDirectoryA(old_working_dir);
+ SetEnvironmentVariableA("PATH", old_PATH);
+
+ ret = RemoveDirectoryA(temp_dir_current);
+ ok(ret, "RemoveDirectoryA failed: %d\n", GetLastError());
+ ret = RemoveDirectoryA(temp_dir_PATH);
+ ok(ret, "RemoveDirectoryA failed: %d\n", GetLastError());
+}
+
static void test_LoadImage(void)
{
HANDLE handle;
bitmap_header->biSize = sizeof(BITMAPINFOHEADER);
test_LoadImageFile("Cursor (invalid dwDIBOffset)", invalid_dwDIBOffset, sizeof(invalid_dwDIBOffset), "cur", 0);
-}
-#undef ARRAY_SIZE
+ /* Test in which paths images with a relative path can be found */
+ test_LoadImage_working_directory();
+}
static void test_CreateIconFromResource(void)
{
static const test_icon_entries_t icon_desc[] = {{0,0,TRUE}, {16,16,TRUE}, {32,32}, {64,64,TRUE}};
- create_ico_file("extract.ico", icon_desc, sizeof(icon_desc)/sizeof(*icon_desc));
+ create_ico_file("extract.ico", icon_desc, ARRAY_SIZE(icon_desc));
ret = PrivateExtractIconsA("extract.ico", 0, 32, 32, &icon, NULL, 1, 0);
ok(ret == 1, "PrivateExtractIconsA returned %u\n", ret);
HeapFree(GetProcessHeap(), 0, icon_data);
}
+static COLORREF get_color_from_bits(const unsigned char *bits, const BITMAPINFO *bmi,
+ unsigned int row, unsigned int column)
+{
+ const BITMAPINFOHEADER *h = &bmi->bmiHeader;
+ unsigned int stride, shift, mask;
+ const unsigned char *data;
+ RGBQUAD color;
+ WORD color16;
+
+ stride = ((h->biBitCount * h->biWidth + 7) / 8 + 3) & ~3;
+ data = bits + row * stride + column * h->biBitCount / 8;
+ if (h->biBitCount >= 24)
+ return RGB(data[2], data[1], data[0]);
+
+ if (h->biBitCount == 16)
+ {
+ color16 = ((WORD)data[1] << 8) | data[0];
+ return RGB(((color16 >> 10) & 0x1f) << 3, ((color16 >> 5) & 0x1f) << 3,
+ (color16 & 0x1f) << 3);
+ }
+ shift = 8 - h->biBitCount - (column * h->biBitCount) % 8;
+ mask = ~(~0u << h->biBitCount);
+ color = bmi->bmiColors[(data[0] >> shift) & mask];
+ return RGB(color.rgbRed, color.rgbGreen, color.rgbBlue);
+}
+
+#define compare_bitmap_bits(a, b, c, d, e, f, g) compare_bitmap_bits_(__LINE__, a, b, c, d, e, f, g)
+static void compare_bitmap_bits_(unsigned int line, HDC hdc, HBITMAP bitmap, BITMAPINFO *bmi,
+ size_t result_bits_size, const unsigned char *expected_bits, unsigned int test_index, BOOL todo)
+{
+ unsigned char *result_bits;
+ unsigned int row, column;
+ int ret;
+
+ result_bits = HeapAlloc(GetProcessHeap(), 0, result_bits_size);
+ ret = GetDIBits(hdc, bitmap, 0, bmi->bmiHeader.biHeight,
+ result_bits, bmi, DIB_RGB_COLORS);
+ ok(ret == bmi->bmiHeader.biHeight, "Unexpected GetDIBits result %d, GetLastError() %u.\n",
+ ret, GetLastError());
+ for (row = 0; row < bmi->bmiHeader.biHeight; ++row)
+ for (column = 0; column < bmi->bmiHeader.biWidth; ++column)
+ {
+ COLORREF result, expected;
+
+ result = get_color_from_bits(result_bits, bmi, row, column);
+ expected = get_color_from_bits(expected_bits, bmi, row, column);
+
+ todo_wine_if(todo)
+ ok_(__FILE__, line)(result == expected, "Colors do not match, "
+ "got 0x%06x, expected 0x%06x, test_index %u, row %u, column %u.\n",
+ result, expected, test_index, row, column);
+ }
+ HeapFree(GetProcessHeap(), 0, result_bits);
+}
+
+static void test_Image_StretchMode(void)
+{
+ static const unsigned char test_bits_24[] =
+ {
+ 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
+ };
+ static const unsigned char expected_bits_24[] =
+ {
+ 0x3f, 0xff, 0x00, 0x3f, 0xff, 0x3f, 0x00, 0x00,
+ 0x3f, 0xff, 0x7f, 0x00, 0xff, 0x3f, 0x00, 0x00,
+ };
+#define rgb16(r, g, b) ((WORD)(((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)))
+ static const WORD test_bits_16[] =
+ {
+ rgb16(0x00, 0x20, 0x00), rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x40, 0xff), rgb16(0x00, 0x20, 0x00),
+ rgb16(0x00, 0x60, 0x00), rgb16(0xff, 0x80, 0x00), rgb16(0xff, 0x60, 0x00), rgb16(0x00, 0x80, 0x00),
+ rgb16(0x00, 0x20, 0xff), rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x40, 0xff), rgb16(0x00, 0x20, 0x00),
+ rgb16(0xff, 0x80, 0x00), rgb16(0x00, 0x60, 0xff), rgb16(0x00, 0x80, 0x00), rgb16(0x00, 0x60, 0x00),
+ };
+ static const WORD expected_bits_16[] =
+ {
+ rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x20, 0x00),
+ rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x20, 0x00),
+ };
+#undef rgb16
+ static const unsigned char test_bits_8[] =
+ {
+ 0x00, 0xff, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0x55, 0x00, 0xff,
+ 0x00, 0xff, 0xff, 0x00,
+ };
+ static const unsigned char expected_bits_8[] =
+ {
+ 0xff, 0xff, 0x00, 0x00,
+ 0x55, 0xff, 0x00, 0x00,
+ };
+ static const unsigned char test_bits_1[] =
+ {
+ 0x30, 0x0, 0x0, 0x0,
+ 0x30, 0x0, 0x0, 0x0,
+ 0x40, 0x0, 0x0, 0x0,
+ 0xc0, 0x0, 0x0, 0x0,
+ };
+ static const unsigned char expected_bits_1[] =
+ {
+ 0x40, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0,
+ };
+ static const RGBQUAD colors_bits_1[] =
+ {
+ {0, 0, 0},
+ {0xff, 0xff, 0xff},
+ };
+ static RGBQUAD colors_bits_8[256];
+
+ static const struct
+ {
+ LONG width, height, output_width, output_height;
+ WORD bit_count;
+ const unsigned char *test_bits, *expected_bits;
+ size_t test_bits_size, result_bits_size;
+ const RGBQUAD *bmi_colors;
+ size_t bmi_colors_size;
+ BOOL todo;
+ }
+ tests[] =
+ {
+ {4, 4, 2, 2, 24, test_bits_24, expected_bits_24,
+ sizeof(test_bits_24), sizeof(expected_bits_24), NULL, 0, TRUE},
+ {4, 4, 2, 2, 1, test_bits_1, expected_bits_1,
+ sizeof(test_bits_1), sizeof(expected_bits_1), colors_bits_1,
+ sizeof(colors_bits_1), FALSE},
+ {4, 4, 2, 2, 8, test_bits_8, expected_bits_8,
+ sizeof(test_bits_8), sizeof(expected_bits_8), colors_bits_8,
+ sizeof(colors_bits_8), FALSE},
+ {4, 4, 2, 2, 16, (const unsigned char *)test_bits_16, (const unsigned char *)expected_bits_16,
+ sizeof(test_bits_16), sizeof(expected_bits_16), NULL, 0, FALSE},
+ };
+ static const char filename[] = "test.bmp";
+ BITMAPINFO *bmi, *bmi_output;
+ HBITMAP bitmap, bitmap_copy;
+ unsigned int test_index;
+ unsigned char *bits;
+ size_t bmi_size;
+ unsigned int i;
+ HDC hdc;
+
+ bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
+ bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bmi_size);
+ bmi_output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bmi_size);
+ bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi->bmiHeader.biPlanes = 1;
+ bmi->bmiHeader.biCompression = BI_RGB;
+
+ for (i = 0; i < 256; ++i)
+ colors_bits_8[i].rgbRed = colors_bits_8[i].rgbGreen = colors_bits_8[i].rgbBlue = i;
+
+ hdc = GetDC(NULL);
+
+ for (test_index = 0; test_index < ARRAY_SIZE(tests); ++test_index)
+ {
+ if (tests[test_index].bmi_colors)
+ memcpy(bmi->bmiColors, tests[test_index].bmi_colors, tests[test_index].bmi_colors_size);
+ else
+ memset(bmi->bmiColors, 0, 256 * sizeof(RGBQUAD));
+
+ bmi->bmiHeader.biWidth = tests[test_index].width;
+ bmi->bmiHeader.biHeight = tests[test_index].height;
+ bmi->bmiHeader.biBitCount = tests[test_index].bit_count;
+ memcpy(bmi_output, bmi, bmi_size);
+ bmi_output->bmiHeader.biWidth = tests[test_index].output_width;
+ bmi_output->bmiHeader.biHeight = tests[test_index].output_height;
+
+ bitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, (void **)&bits, NULL, 0);
+ ok(bitmap && bits, "CreateDIBSection() failed, result %u.\n", GetLastError());
+ memcpy(bits, tests[test_index].test_bits, tests[test_index].test_bits_size);
+
+ bitmap_copy = CopyImage(bitmap, IMAGE_BITMAP, tests[test_index].output_width,
+ tests[test_index].output_height, LR_CREATEDIBSECTION);
+ ok(!!bitmap_copy, "CopyImage() failed, result %u.\n", GetLastError());
+
+ compare_bitmap_bits(hdc, bitmap_copy, bmi_output, tests[test_index].result_bits_size,
+ tests[test_index].expected_bits, test_index, tests[test_index].todo);
+ DeleteObject(bitmap);
+ DeleteObject(bitmap_copy);
+
+ create_bitmap_file(filename, bmi, tests[test_index].test_bits);
+ bitmap = LoadImageA(NULL, filename, IMAGE_BITMAP, tests[test_index].output_width,
+ tests[test_index].output_height, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
+ ok(!!bitmap, "LoadImageA() failed, result %u.\n", GetLastError());
+ DeleteFileA(filename);
+ compare_bitmap_bits(hdc, bitmap, bmi_output, tests[test_index].result_bits_size,
+ tests[test_index].expected_bits, test_index, tests[test_index].todo);
+ DeleteObject(bitmap);
+ }
+ ReleaseDC(0, hdc);
+ HeapFree(GetProcessHeap(), 0, bmi_output);
+ HeapFree(GetProcessHeap(), 0, bmi);
+}
+
START_TEST(cursoricon)
{
pGetCursorInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetCursorInfo" );
test_CopyImage_Bitmap(16);
test_CopyImage_Bitmap(24);
test_CopyImage_Bitmap(32);
+ test_Image_StretchMode();
test_initial_cursor();
test_CreateIcon();
test_LoadImage();
{ 0x4efa, 0x4efc, 0x0061, 0x4efe, 0 }, /* some Chinese chars */
{ 0x0061, 0x0062, 0x0063, 0x9152, 0 }, /* Chinese with latin characters begin */
};
-static const int nb_callbacks = 5 + sizeof(test_cmd_w_to_w)/sizeof(test_cmd_w_to_w[0]);
+static const int nb_callbacks = 5 + ARRAY_SIZE(test_cmd_w_to_w);
static HDDEDATA CALLBACK server_end_to_end_callback(UINT uType, UINT uFmt, HCONV hconv,
HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
size_a = strlen(test_cmd_a_to_a) + 1;
size_w = (lstrlenW(cmd_w) + 1) * sizeof(WCHAR);
size_a_to_w = MultiByteToWideChar( CP_ACP, 0, test_cmd_a_to_a, -1, test_cmd_a_to_w,
- sizeof(test_cmd_a_to_w)/sizeof(WCHAR) ) * sizeof(WCHAR);
+ ARRAY_SIZE(test_cmd_a_to_w)) * sizeof(WCHAR);
size_w_to_a = WideCharToMultiByte( CP_ACP, 0, cmd_w, -1,
test_cmd_w_to_a, sizeof(test_cmd_w_to_a), NULL, NULL );
switch (str_index)
/* double A->W mapping */
/* NT uses the full size, XP+ only until the first null */
DWORD nt_size = MultiByteToWideChar( CP_ACP, 0, (char *)cmd_w, size_w, test_cmd_a_to_w,
- sizeof(test_cmd_a_to_w)/sizeof(WCHAR) ) * sizeof(WCHAR);
+ ARRAY_SIZE(test_cmd_a_to_w)) * sizeof(WCHAR);
DWORD xp_size = MultiByteToWideChar( CP_ACP, 0, (char *)cmd_w, -1, NULL, 0 ) * sizeof(WCHAR);
ok(size == xp_size || broken(size == nt_size) ||
broken(str_index == 4 && IsDBCSLeadByte(cmd_w[0])) /* East Asian */,
{
todo_wine ok(size == size_w, "Wrong size %d expected %d, msg_index=%d\n", size, size_w, msg_index);
MultiByteToWideChar(CP_ACP, 0, test_cmd_w_to_a, size_w, test_cmd_a_to_w,
- sizeof(test_cmd_a_to_w)/sizeof(WCHAR));
+ ARRAY_SIZE(test_cmd_a_to_w));
todo_wine ok(!lstrcmpW((WCHAR*)buffer, cmd_w),
"Expected %s got %s, msg_index=%d\n", wine_dbgstr_w(cmd_w), wine_dbgstr_w((WCHAR *)buffer), msg_index);
}
{
todo_wine ok(size == size_w, "Wrong size %d expected %d, msg_index=%d\n", size, size_w, msg_index);
MultiByteToWideChar(CP_ACP, 0, test_cmd_w_to_a, size_w, test_cmd_a_to_w,
- sizeof(test_cmd_a_to_w)/sizeof(WCHAR));
+ ARRAY_SIZE(test_cmd_a_to_w));
if (!is_cjk())
todo_wine ok(!lstrcmpW((WCHAR*)buffer, test_cmd_a_to_w), "Expected %s, got %s, msg_index=%d\n",
wine_dbgstr_w(test_cmd_a_to_w), wine_dbgstr_w((WCHAR*)buffer), msg_index);
err = DdeGetLastError(client_pid);
ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
- for (i = 0; i < sizeof(test_cmd_w_to_w)/sizeof(test_cmd_w_to_w[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(test_cmd_w_to_w); i++)
{
hdata = DdeClientTransaction((LPBYTE)test_cmd_w_to_w[i],
(lstrlenW(test_cmd_w_to_w[i]) + 1) * sizeof(WCHAR),
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
+#include "winnls.h"
#define MAXHWNDS 1024
static HWND hwnd [MAXHWNDS];
static BOOL g_bInitialFocusInitDlgResult, g_bReceivedCommand;
static BOOL g_terminated;
+static BOOL g_button1Clicked;
typedef struct {
INT_PTR id;
{0, 0, 0, 0}
};
+static DWORD get_button_style(HWND button)
+{
+ return GetWindowLongW(button, GWL_STYLE) & BS_TYPEMASK;
+}
+
static BOOL CreateWindows (HINSTANCE hinst)
{
const h_entry *p = hierarchy;
while (p->id != 0)
{
DWORD style, exstyle;
- char ctrlname[9];
+ char ctrlname[16];
/* Basically assert that the hierarchy is valid and track the
* maximum control number
*/
if (p->id >= numwnds)
{
- if (p->id >= sizeof(hwnd)/sizeof(hwnd[0]))
+ if (p->id >= ARRAY_SIZE(hwnd))
{
trace ("Control %ld is out of range\n", p->id);
return FALSE;
g_terminated = TRUE;
return 0;
}
+ else if ((wParam == 100 || wParam == 0xFFFF) && lParam)
+ {
+ g_button1Clicked = TRUE;
+ }
break;
}
* BS_DEFPUSHBUTTON with out making it default.
*/
- /*
- * Keep the focus on Edit control.
- */
+ /* Keep the focus on Edit control. */
+ SetFocus(g_hwndTestDlgEdit);
+ ok((GetFocus() == g_hwndTestDlgEdit), "Focus didn't set on Edit control\n");
- if ( SetFocus( g_hwndTestDlgEdit ) )
- {
- ok ((GetFocus() == g_hwndTestDlgEdit), "Focus didn't set on Edit control\n");
-
- /*
- * Test message WM_NEXTDLGCTL
- */
- DefDlgProcA( g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0 );
- ok ((GetFocus() == g_hwndTestDlgBut1), "Focus didn't move to first button\n");
+ /* Test message WM_NEXTDLGCTL */
+ DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0);
+ ok((GetFocus() == g_hwndTestDlgBut1), "Focus didn't move to first button\n");
- /*
- * Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL"
- */
- dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
- ok ( IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
-
- /*
- * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and
- * the style of default button changed to BS_PUSHBUTTON.
- */
- if ( IDCANCEL == (LOWORD(dwVal)) )
- {
- ok ( ((GetWindowLongA( g_hwndTestDlgBut1, GWL_STYLE)) & BS_DEFPUSHBUTTON),
- "Button1 style not set to BS_DEFPUSHBUTTON\n" );
-
- ok ( !((GetWindowLongA( g_hwndTestDlgBut2, GWL_STYLE)) & BS_DEFPUSHBUTTON),
- "Button2's style not changed to BS_PUSHBUTTON\n" );
- }
+ /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */
+ dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
+ ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
- /*
- * Move focus to Button2 using "WM_NEXTDLGCTL"
- */
- DefDlgProcA( g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0 );
- ok ((GetFocus() == g_hwndTestDlgBut2), "Focus didn't move to second button\n");
+ /*
+ * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and
+ * the style of default button changed to BS_PUSHBUTTON.
+ */
+ ok(get_button_style(g_hwndTestDlgBut1) == BS_DEFPUSHBUTTON, "Button1's style not set to BS_DEFPUSHBUTTON");
+ ok(get_button_style(g_hwndTestDlgBut2) == BS_PUSHBUTTON, "Button2's style not set to BS_PUSHBUTTON");
- /*
- * Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL"
- */
- dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
- ok ( IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
+ /* Move focus to Button2 using "WM_NEXTDLGCTL" */
+ DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0);
+ ok((GetFocus() == g_hwndTestDlgBut2), "Focus didn't move to second button\n");
- /*
- * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and
- * the style of button which lost the focus changed to BS_PUSHBUTTON.
- */
- if ( IDCANCEL == (LOWORD(dwVal)) )
- {
- ok ( ((GetWindowLongA( g_hwndTestDlgBut2, GWL_STYLE)) & BS_DEFPUSHBUTTON),
- "Button2 style not set to BS_DEFPUSHBUTTON\n" );
+ /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */
+ dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
+ ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
- ok ( !((GetWindowLongA( g_hwndTestDlgBut1, GWL_STYLE)) & BS_DEFPUSHBUTTON),
- "Button1's style not changed to BS_PUSHBUTTON\n" );
- }
+ /*
+ * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and
+ * the style of button which lost the focus changed to BS_PUSHBUTTON.
+ */
+ ok(get_button_style(g_hwndTestDlgBut1) == BS_PUSHBUTTON, "Button1's style not set to BS_PUSHBUTTON");
+ ok(get_button_style(g_hwndTestDlgBut2) == BS_DEFPUSHBUTTON, "Button2's style not set to BS_DEFPUSHBUTTON");
- /*
- * Move focus to Edit control using "WM_NEXTDLGCTL"
- */
- DefDlgProcA( g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0 );
- ok ((GetFocus() == g_hwndTestDlgEdit), "Focus didn't move to Edit control\n");
+ /* Move focus to Edit control using "WM_NEXTDLGCTL" */
+ DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0);
+ ok((GetFocus() == g_hwndTestDlgEdit), "Focus didn't move to Edit control\n");
- /*
- * Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL"
- */
- dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
- ok ( IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
- }
+ /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */
+ dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
+ ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
/* test nested default buttons */
ok (!IsDialogMessageA(msg.hwnd, &msg), "expected failure\n");
UnhookWindowsHookEx(hook);
+ DestroyWindow(g_hwndMain);
+
+ g_hwndMain = CreateWindowA("IsDialogMessageWindowClass", "IsDialogMessageWindowClass", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hinst, 0);
+ SetFocus(g_hwndButton1);
+ g_button1Clicked = FALSE;
+ FormEnterMsg(&msg, g_hwndButton1);
+ ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
+ ok(g_button1Clicked, "Did not receive button 1 click notification\n");
+
+ g_button1Clicked = FALSE;
+ FormEnterMsg(&msg, g_hwndMain);
+ ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
+ ok(g_button1Clicked, "Did not receive button 1 click notification\n");
+
+ g_button1Clicked = FALSE;
+ FormEnterMsg(&msg, g_hwndButton2);
+ ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
+ ok(g_button1Clicked, "Did not receive button 1 click notification\n");
+
+ /* Button with id larger than 0xFFFF should also work */
+ g_button1Clicked = FALSE;
+ FormEnterMsg(&msg, g_hwndMain);
+ SetWindowLongPtrW(g_hwndButton1, GWLP_ID, 0x1FFFF);
+ ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
+ ok(g_button1Clicked, "Did not receive button 1 click notification\n");
+
+ DestroyWindow(g_hwndMain);
}
return FALSE;
}
+static INT_PTR CALLBACK EmptyProcUserTemplate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK focusChildDlgWinProc (HWND hwnd, UINT uiMsg, WPARAM wParam,
+ LPARAM lParam)
+{
+ static HWND hChildDlg;
+
+ switch (uiMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ RECT rectHwnd;
+ struct {
+ DLGTEMPLATE tmplate;
+ WORD menu,class,title;
+ } temp;
+
+ SetFocus( GetDlgItem(hwnd, 200) );
+
+ GetClientRect(hwnd,&rectHwnd);
+ temp.tmplate.style = WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | DS_CONTROL | DS_3DLOOK;
+ temp.tmplate.dwExtendedStyle = 0;
+ temp.tmplate.cdit = 0;
+ temp.tmplate.x = 0;
+ temp.tmplate.y = 0;
+ temp.tmplate.cx = 0;
+ temp.tmplate.cy = 0;
+ temp.menu = temp.class = temp.title = 0;
+
+ hChildDlg = CreateDialogIndirectParamA(g_hinst, &temp.tmplate,
+ hwnd, (DLGPROC)EmptyProcUserTemplate, 0);
+ ok(hChildDlg != 0, "Failed to create test dialog.\n");
+
+ return FALSE;
+ }
+ case WM_CLOSE:
+ DestroyWindow(hChildDlg);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/* Helper for InitialFocusTest */
static const char * GetHwndString(HWND hw)
{
DestroyWindow(hDlg);
}
+
+ /* Test 6:
+ * Select textbox's text on creation when WM_INITDIALOG creates a child dialog. */
+ {
+ HWND hDlg;
+ HRSRC hResource;
+ HANDLE hTemplate;
+ DLGTEMPLATE* pTemplate;
+ HWND edit;
+
+ hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG_3", (LPCSTR)RT_DIALOG);
+ hTemplate = LoadResource(g_hinst, hResource);
+ pTemplate = LockResource(hTemplate);
+
+ hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusChildDlgWinProc, 0);
+ ok(hDlg != 0, "Failed to create test dialog.\n");
+ edit = GetDlgItem(hDlg, 200);
+
+ ok(GetFocus() == edit, "Focus not set to edit, focus=%p, dialog=%p, edit=%p\n",
+ GetFocus(), hDlg, edit);
+
+ DestroyWindow(hDlg);
+ }
}
static void test_GetDlgItemText(void)
BOOL ret;
strcpy(string, "Overwrite Me");
- ret = GetDlgItemTextA(NULL, 0, string, sizeof(string)/sizeof(string[0]));
+ ret = GetDlgItemTextA(NULL, 0, string, ARRAY_SIZE(string));
ok(!ret, "GetDlgItemText(NULL) shouldn't have succeeded\n");
ok(string[0] == '\0' || broken(!strcmp(string, "Overwrite Me")),
"string retrieved using GetDlgItemText should have been NULL terminated\n");
}
+static INT_PTR CALLBACK getdlgitem_test_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (msg == WM_INITDIALOG)
+ {
+ char text[64];
+ LONG_PTR val;
+ HWND hwnd;
+ BOOL ret;
+
+ hwnd = GetDlgItem(hdlg, -1);
+ ok(hwnd != NULL, "Expected dialog item.\n");
+
+ *text = 0;
+ ret = GetDlgItemTextA(hdlg, -1, text, ARRAY_SIZE(text));
+ ok(ret && !strcmp(text, "Text1"), "Unexpected item text.\n");
+
+ val = GetWindowLongA(hwnd, GWLP_ID);
+ ok(val == -1, "Unexpected id.\n");
+
+ val = GetWindowLongPtrA(hwnd, GWLP_ID);
+ ok(val == -1, "Unexpected id %ld.\n", val);
+
+ hwnd = GetDlgItem(hdlg, -2);
+ ok(hwnd != NULL, "Expected dialog item.\n");
+
+ val = GetWindowLongA(hwnd, GWLP_ID);
+ ok(val == -2, "Unexpected id.\n");
+
+ val = GetWindowLongPtrA(hwnd, GWLP_ID);
+ ok(val == -2, "Unexpected id %ld.\n", val);
+
+ EndDialog(hdlg, 0xdead);
+ }
+
+ return FALSE;
+}
+
static void test_GetDlgItem(void)
{
HWND hwnd, child1, child2, hwnd2;
+ INT_PTR retval;
BOOL ret;
hwnd = CreateWindowA("button", "parent", WS_VISIBLE, 0, 0, 100, 100, NULL, 0, g_hinst, NULL);
DestroyWindow(child1);
DestroyWindow(child2);
DestroyWindow(hwnd);
+
+ retval = DialogBoxParamA(g_hinst, "GETDLGITEM_TEST_DIALOG", NULL, getdlgitem_test_dialog_proc, 0);
+ ok(retval == 0xdead, "Unexpected return value.\n");
}
static INT_PTR CALLBACK DestroyDlgWinProc (HWND hDlg, UINT uiMsg,
(BYTE)buff[0], (BYTE)buff[1], len);
memset(buffW, 0xff, sizeof(buffW));
- len = GetWindowTextW(hdlg, buffW, sizeof(buffW)/sizeof(buffW[0]));
+ len = GetWindowTextW(hdlg, buffW, ARRAY_SIZE(buffW));
ok(buffW[0] == 'W' && buffW[1] == 0xffff && len == 0, "Unexpected window text %#x, %#x, len %d\n",
buffW[0], buffW[1], len);
ok(!strcmp(buff, testtext) && len == 0, "Unexpected window text %s, len %d\n", buff, len);
memset(buffW, 0xff, sizeof(buffW));
- len = GetWindowTextW(hdlg, buffW, sizeof(buffW)/sizeof(buffW[0]));
+ len = GetWindowTextW(hdlg, buffW, ARRAY_SIZE(buffW));
ok(buffW[0] == 0 && buffW[1] == 0xffff && len == 0, "Unexpected window text %#x, %#x, len %d\n",
buffW[0], buffW[1], len);
DestroyWindow(hDlg);
}
+static const char msgbox_title[] = "%5!z9ZXw*ia;57n/FGl.bCH,Su\"mfKN;foCqAU\'j6AmoJgAc_D:Z0A\'E6PF_O/w";
+static WCHAR expectedOK[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'O','K',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+static WCHAR expectedOkCancel[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'O','K',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+static WCHAR expectedAbortRetryIgnore[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'A','b','o','r','t',' ',' ',' ','R','e','t','r','y',' ',' ',' ','I','g','n','o','r','e',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+
+static WCHAR expectedYesNo[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'Y','e','s',' ',' ',' ','N','o',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+static WCHAR expectedYesNoCancel[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'Y','e','s',' ',' ',' ','N','o',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+static WCHAR expectedRetryCancel[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'R','e','t','r','y',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+static WCHAR expectedCancelTryContinue[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'C','a','n','c','e','l',' ',' ',' ','T','r','y',' ','A','g','a','i','n',' ',' ',' ','C','o','n','t','i','n','u','e',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+
+BOOL non_english = FALSE;
+
+DWORD WINAPI WorkerThread(void *param)
+{
+ WCHAR *expected = param;
+ char windowTitle[sizeof(msgbox_title)];
+ HWND hwndMbox;
+ BOOL succeeded = FALSE;
+
+ Sleep(200);
+
+ hwndMbox = GetForegroundWindow();
+
+ /* Find the Window, if it doesn't have focus */
+ if (!(IsWindow(hwndMbox) &&
+ GetWindowTextA(hwndMbox, windowTitle, sizeof(msgbox_title)) &&
+ lstrcmpA(msgbox_title, windowTitle) == 0))
+ {
+ hwndMbox = FindWindowA(NULL, msgbox_title);
+
+ if (!IsWindow(hwndMbox))
+ goto cleanup;
+ }
+
+ SendMessageA(hwndMbox, WM_COPY, 0, 0);
+
+ if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
+ {
+ HANDLE textHandle = GetClipboardData(CF_UNICODETEXT);
+ WCHAR *text = GlobalLock(textHandle);
+
+ if (text != NULL)
+ {
+ if(non_english)
+ ok(lstrlenW(text) > 0, "Empty string on clipboard\n");
+ else
+ {
+ succeeded = lstrcmpW(expected, text) == 0;
+ if(!succeeded)
+ {
+ ok(0, "%s\n", wine_dbgstr_w(text));
+ ok(0, "%s\n", wine_dbgstr_w(expected));
+ }
+ }
+
+ GlobalUnlock(textHandle);
+ }
+ else
+ ok(0, "No text on clipboard.\n");
+
+ CloseClipboard();
+
+ }
+ else
+ trace("Clipboard error\n");
+
+ PostMessageA(hwndMbox, WM_COMMAND, IDIGNORE, 0); /* For MB_ABORTRETRYIGNORE dialog. */
+ PostMessageA(hwndMbox, WM_CLOSE, 0, 0);
+
+cleanup:
+ ok(succeeded || non_english, "Failed to get string.\n");
+
+ return 0;
+}
+
+static void test_MessageBox_WM_COPY_Test(void)
+{
+ DWORD tid = 0;
+
+ non_english = (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH);
+ trace("non_english %d\n", non_english);
+
+ CreateThread(NULL, 0, WorkerThread, &expectedOK, 0, &tid);
+ MessageBoxA(NULL, "Message", msgbox_title, MB_OK);
+
+ CreateThread(NULL, 0, WorkerThread, &expectedOkCancel, 0, &tid);
+ MessageBoxA(NULL, "Message", msgbox_title, MB_OKCANCEL);
+
+ CreateThread(NULL, 0, WorkerThread, &expectedAbortRetryIgnore, 0, &tid);
+ MessageBoxA(NULL, "Message", msgbox_title, MB_ABORTRETRYIGNORE);
+
+ CreateThread(NULL, 0, WorkerThread, &expectedYesNo, 0, &tid);
+ MessageBoxA(NULL, "Message", msgbox_title, MB_YESNO);
+
+ CreateThread(NULL, 0, WorkerThread, &expectedYesNoCancel, 0, &tid);
+ MessageBoxA(NULL, "Message", msgbox_title, MB_YESNOCANCEL);
+
+ CreateThread(NULL, 0, WorkerThread, &expectedRetryCancel, 0, &tid);
+ MessageBoxA(NULL, "Message", msgbox_title, MB_RETRYCANCEL);
+
+ CreateThread(NULL, 0, WorkerThread, &expectedCancelTryContinue, 0, &tid);
+ MessageBoxA(NULL, "Message", msgbox_title, MB_CANCELTRYCONTINUE);
+}
+
static void test_SaveRestoreFocus(void)
{
HWND hDlg;
test_SaveRestoreFocus();
test_timer_message();
test_MessageBox();
+ test_MessageBox_WM_COPY_Test();
}
DestroyWindow (hwEdit);
}
+static BOOL is_cjk_charset(HDC dc)
+{
+ switch (GdiGetCodePage(dc)) {
+ case 932: case 936: case 949: case 950: case 1361:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
static void test_margins_usefontinfo(UINT charset)
{
HWND hwnd;
HDC hdc;
+ TEXTMETRICW tm;
SIZE size;
- BOOL cjk = FALSE;
LOGFONTA lf;
HFONT hfont;
RECT rect;
- INT margins, threshold, expect, empty_expect, small_expect;
+ INT margins, threshold, expect, empty_expect;
+ const UINT small_margins = MAKELONG(1, 5);
memset(&lf, 0, sizeof(lf));
lf.lfHeight = -11;
hdc = GetDC(hwnd);
hfont = SelectObject(hdc, hfont);
- size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy );
- expect = MAKELONG(size.cx / 2, size.cx / 2);
- small_expect = 0;
- empty_expect = size.cx >= 28 ? small_expect : expect;
-
- charset = GetTextCharset(hdc);
- switch (charset)
- {
- case SHIFTJIS_CHARSET:
- case HANGUL_CHARSET:
- case GB2312_CHARSET:
- case CHINESEBIG5_CHARSET:
- cjk = TRUE;
+ size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
+ if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
+ !(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
+ skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
+ hfont = SelectObject(hdc, hfont);
+ ReleaseDC(hwnd, hdc);
+ DestroyWindow(hwnd);
+ DeleteObject(hfont);
+ return;
}
-
+ expect = MAKELONG(size.cx / 2, size.cx / 2);
hfont = SelectObject(hdc, hfont);
ReleaseDC(hwnd, hdc);
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == 0, "got %x\n", margins);
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
- margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
- if (!cjk)
- ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
- else
- {
- ok(HIWORD(margins) > 0 && LOWORD(margins) > 0, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
- expect = empty_expect = small_expect = margins;
- }
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
+ expect = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
DestroyWindow(hwnd);
- threshold = (size.cx / 2 + size.cx) * 2;
+ threshold = HIWORD(expect) + LOWORD(expect) + size.cx * 2;
+ empty_expect = threshold > 80 ? small_margins : expect;
- /* Size below which non-cjk margins are zero */
+ /* Size below the threshold, margins remain unchanged */
hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold - 1, 100, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "got %p\n", hwnd);
GetClientRect(hwnd, &rect);
ok(margins == 0, "got %x\n", margins);
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
- ok(margins == small_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
+ ok(margins == small_margins, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
DestroyWindow(hwnd);
- /* Size at which non-cjk margins become non-zero */
+ /* Size at the threshold, margins become non-zero */
hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold, 100, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "got %p\n", hwnd);
GetClientRect(hwnd, &rect);
ok(margins == 0, "got %x\n", margins);
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
DestroyWindow(hwnd);
ok(margins == 0, "got %x\n", margins);
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == empty_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
DestroyWindow(hwnd);
DeleteObject(hfont);
}
+static BOOL is_cjk_font(HDC dc)
+{
+ const DWORD FS_DBCS_MASK = FS_JISJAPAN|FS_CHINESESIMP|FS_WANSUNG|FS_CHINESETRAD|FS_JOHAB;
+ FONTSIGNATURE fs;
+ return (GetTextCharsetInfo(dc, &fs, 0) != DEFAULT_CHARSET &&
+ (fs.fsCsb[0] & FS_DBCS_MASK));
+}
+
+static INT get_cjk_fontinfo_margin(INT width, INT side_bearing)
+{
+ INT margin;
+ if (side_bearing < 0)
+ margin = min(-side_bearing, width/2);
+ else
+ margin = 0;
+ return margin;
+}
+
+static DWORD get_cjk_font_margins(HDC hdc, BOOL unicode)
+{
+ ABC abc[256];
+ SHORT left, right;
+ UINT i;
+
+ left = right = 0;
+ if (unicode) {
+ if (!GetCharABCWidthsW(hdc, 0, 255, abc))
+ return 0;
+ }
+ else {
+ if (!GetCharABCWidthsA(hdc, 0, 255, abc))
+ return 0;
+ }
+ for (i = 0; i < ARRAY_SIZE(abc); i++) {
+ if (-abc[i].abcA > right) right = -abc[i].abcA;
+ if (-abc[i].abcC > left) left = -abc[i].abcC;
+ }
+ return MAKELONG(left, right);
+}
+
+static void test_margins_default(const char* facename, UINT charset)
+{
+ HWND hwnd;
+ HDC hdc;
+ TEXTMETRICW tm;
+ SIZE size;
+ BOOL cjk_charset, cjk_font;
+ LOGFONTA lf;
+ HFONT hfont;
+ RECT rect;
+ INT margins, expect, font_expect;
+ const UINT small_margins = MAKELONG(1, 5);
+ const WCHAR EditW[] = {'E','d','i','t',0}, strW[] = {'W',0};
+ struct char_width_info {
+ INT lsb, rsb, unknown;
+ } info;
+ HMODULE hgdi32;
+ BOOL (WINAPI *pGetCharWidthInfo)(HDC, struct char_width_info *);
+
+ hgdi32 = GetModuleHandleA("gdi32.dll");
+ pGetCharWidthInfo = (void *)GetProcAddress(hgdi32, "GetCharWidthInfo");
+
+ memset(&lf, 0, sizeof(lf));
+ lf.lfHeight = -11;
+ lf.lfWeight = FW_NORMAL;
+ lf.lfCharSet = charset;
+ strcpy(lf.lfFaceName, facename);
+
+ hfont = CreateFontIndirectA(&lf);
+ ok(hfont != NULL, "got %p\n", hfont);
+
+ /* Unicode version */
+ hwnd = CreateWindowExW(0, EditW, strW, WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
+ ok(hwnd != NULL, "got %p\n", hwnd);
+ GetClientRect(hwnd, &rect);
+ ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
+
+ hdc = GetDC(hwnd);
+ hfont = SelectObject(hdc, hfont);
+ size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
+ if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
+ !(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
+ skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
+ hfont = SelectObject(hdc, hfont);
+ ReleaseDC(hwnd, hdc);
+ DestroyWindow(hwnd);
+ DeleteObject(hfont);
+ return;
+ }
+ cjk_charset = is_cjk_charset(hdc);
+ cjk_font = is_cjk_font(hdc);
+ if ((cjk_charset || cjk_font) &&
+ pGetCharWidthInfo && pGetCharWidthInfo(hdc, &info)) {
+ short left, right;
+
+ left = get_cjk_fontinfo_margin(size.cx, info.lsb);
+ right = get_cjk_fontinfo_margin(size.cx, info.rsb);
+ expect = MAKELONG(left, right);
+
+ font_expect = get_cjk_font_margins(hdc, TRUE);
+ if (!font_expect)
+ /* In this case, margins aren't updated */
+ font_expect = small_margins;
+ }
+ else
+ font_expect = expect = MAKELONG(size.cx / 2, size.cx / 2);
+
+ hfont = SelectObject(hdc, hfont);
+ ReleaseDC(hwnd, hdc);
+
+ margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
+ ok(margins == 0, "got %x\n", margins);
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
+ margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
+ ok(margins == font_expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(font_expect), LOWORD(font_expect), HIWORD(margins), LOWORD(margins));
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
+ margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
+ ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
+ DestroyWindow(hwnd);
+
+ /* ANSI version */
+ hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
+ ok(hwnd != NULL, "got %p\n", hwnd);
+ GetClientRect(hwnd, &rect);
+ ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
+
+ if (cjk_charset) {
+ hdc = GetDC(hwnd);
+ hfont = SelectObject(hdc, hfont);
+ font_expect = get_cjk_font_margins(hdc, FALSE);
+ if (!font_expect)
+ /* In this case, margins aren't updated */
+ font_expect = small_margins;
+ hfont = SelectObject(hdc, hfont);
+ ReleaseDC(hwnd, hdc);
+ }
+ else
+ /* we expect EC_USEFONTINFO size */
+ font_expect = expect;
+
+ margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
+ ok(margins == 0, "got %x\n", margins);
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
+ SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
+ margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
+ ok(margins == font_expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(font_expect), LOWORD(font_expect), HIWORD(margins), LOWORD(margins));
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
+ SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
+ margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
+ ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
+ DestroyWindow(hwnd);
+
+ DeleteObject(hfont);
+}
+
+static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
+{
+ return 0;
+}
+
+static BOOL is_font_installed(const char*name)
+{
+ HDC hdc = GetDC(NULL);
+ BOOL ret = FALSE;
+
+ if (!EnumFontFamiliesA(hdc, name, find_font_proc, 0))
+ ret = TRUE;
+
+ ReleaseDC(NULL, hdc);
+ return ret;
+}
+
static void test_margins(void)
{
HWND hwEdit;
but not by < Win 8 and Win 10. */
test_margins_usefontinfo(DEFAULT_CHARSET);
-}
-static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
-{
- return 0;
+ test_margins_default("Tahoma", ANSI_CHARSET);
+ test_margins_default("Tahoma", EASTEUROPE_CHARSET);
+
+ test_margins_default("Tahoma", HANGUL_CHARSET);
+ test_margins_default("Tahoma", CHINESEBIG5_CHARSET);
+
+ if (is_font_installed("MS PGothic")) {
+ test_margins_default("MS PGothic", SHIFTJIS_CHARSET);
+ test_margins_default("MS PGothic", GREEK_CHARSET);
+ }
+ else
+ skip("MS PGothic is not available, skipping some margin tests\n");
+
+ if (is_font_installed("Ume P Gothic")) {
+ test_margins_default("Ume P Gothic", SHIFTJIS_CHARSET);
+ test_margins_default("Ume P Gothic", GREEK_CHARSET);
+ }
+ else
+ skip("Ume P Gothic is not available, skipping some margin tests\n");
+
+ if (is_font_installed("SimSun")) {
+ test_margins_default("SimSun", GB2312_CHARSET);
+ test_margins_default("SimSun", ANSI_CHARSET);
+ }
+ else
+ skip("SimSun is not available, skipping some margin tests\n");
}
static void test_margins_font_change(void)
DWORD margins, font_margins;
LOGFONTA lf;
HFONT hfont, hfont2;
- HDC hdc = GetDC(0);
- if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
+ if (!is_font_installed("Arial"))
{
- trace("Arial not found - skipping font change margin tests\n");
- ReleaseDC(0, hdc);
+ skip("Arial not found - skipping font change margin tests\n");
return;
}
- ReleaseDC(0, hdc);
hwEdit = create_child_editcontrol(0, 0);
memset(&lf, 0, sizeof(lf));
strcpy(lf.lfFaceName, "Arial");
lf.lfHeight = 16;
- lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfCharSet = GREEK_CHARSET; /* to avoid associated charset feature */
hfont = CreateFontIndirectA(&lf);
lf.lfHeight = 30;
hfont2 = CreateFontIndirectA(&lf);
SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
- ok(LOWORD(margins) == 0 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
+ ok(LOWORD(margins) == 0,
"got %d\n", LOWORD(margins));
- ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
+ ok(HIWORD(margins) == 0,
"got %d\n", HIWORD(margins));
SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
- ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
+ ok(LOWORD(margins) == 1,
"got %d\n", LOWORD(margins));
- ok(HIWORD(margins) == 0 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
+ ok(HIWORD(margins) == 0,
"got %d\n", HIWORD(margins));
SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
- ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
+ ok(LOWORD(margins) == 1,
"got %d\n", LOWORD(margins));
- ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
+ ok(HIWORD(margins) == 1,
"got %d\n", HIWORD(margins));
SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
- ok(LOWORD(margins) == 1 || broken(LOWORD(margins) == LOWORD(font_margins)), /* win95 */
+ ok(LOWORD(margins) == 1,
"got %d\n", LOWORD(margins));
- ok(HIWORD(margins) == 1 || broken(HIWORD(margins) == HIWORD(font_margins)), /* win95 */
+ ok(HIWORD(margins) == 1,
"got %d\n", HIWORD(margins));
SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
- ok(LOWORD(margins) == 1 || broken(LOWORD(margins) != 1 && LOWORD(margins) != LOWORD(font_margins)), /* win95 */
+ ok(LOWORD(margins) == 1,
"got %d\n", LOWORD(margins));
- ok(HIWORD(margins) == 1 || broken(HIWORD(margins) != 1 && HIWORD(margins) != HIWORD(font_margins)), /* win95 */
+ ok(HIWORD(margins) == 1,
"got %d\n", HIWORD(margins));
/* Above a certain size threshold then the margin is updated */
ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins));
SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
margins = SendMessageA(hwEdit, EM_GETMARGINS, 0, 0);
- ok(LOWORD(margins) != LOWORD(font_margins) || broken(LOWORD(margins) == LOWORD(font_margins)), /* win98 */
+ ok(LOWORD(margins) != LOWORD(font_margins),
"got %d\n", LOWORD(margins));
ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins));
hwnd[0] = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
hwnd[1] = create_editcontrolW(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
- for (i = 0; i < sizeof(hwnd)/sizeof(hwnd[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(hwnd); i++)
{
static const WCHAR strW[] = {'t','e','x','t',0};
static const char *str = "text";
ok(!strcmp(buff, str), "Unexpected line data %s.\n", buff);
memset(buffW, 0, sizeof(buffW));
- *(WORD *)buffW = sizeof(buffW)/sizeof(buffW[0]);
+ *(WORD *)buffW = ARRAY_SIZE(buffW);
r = SendMessageW(hwnd[i], EM_GETLINE, 0, (LPARAM)buffW);
ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
memset(buffW, 0, sizeof(buffW));
- *(WORD *)buffW = sizeof(buffW)/sizeof(buffW[0]);
+ *(WORD *)buffW = ARRAY_SIZE(buffW);
r = SendMessageW(hwnd[i], EM_GETLINE, 1, (LPARAM)buffW);
ok(r == lstrlenW(strW), "Failed to get a line %d.\n", r);
ok(!lstrcmpW(buffW, strW), "Unexpected line data %s.\n", wine_dbgstr_w(buffW));
LONG last_hook_up;
LONG last_hook_syskey_down;
LONG last_hook_syskey_up;
+ WORD vk;
BOOL expect_alt;
BOOL sendinput_broken;
} key_status;
-static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
+static BOOL (WINAPI *pGetCurrentInputMessageSource)( INPUT_MESSAGE_SOURCE *source );
+static BOOL (WINAPI *pGetPointerType)(UINT32, POINTER_INPUT_TYPE*);
static int (WINAPI *pGetMouseMovePointsEx) (UINT, LPMOUSEMOVEPOINT, LPMOUSEMOVEPOINT, int, DWORD);
static UINT (WINAPI *pGetRawInputDeviceList) (PRAWINPUTDEVICELIST, PUINT, UINT);
+static UINT (WINAPI *pGetRawInputDeviceInfoW) (HANDLE, UINT, void *, UINT *);
+static UINT (WINAPI *pGetRawInputDeviceInfoA) (HANDLE, UINT, void *, UINT *);
static int (WINAPI *pGetWindowRgnBox)(HWND, LPRECT);
#define MAXKEYEVENTS 12
} u;
} TEST_INPUT;
-#define ADDTOINPUTS(kev) \
-inputs[evtctr].type = INPUT_KEYBOARD; \
- ((TEST_INPUT*)inputs)[evtctr].u.ki.wVk = GETVKEY[ kev]; \
- ((TEST_INPUT*)inputs)[evtctr].u.ki.wScan = GETSCAN[ kev]; \
- ((TEST_INPUT*)inputs)[evtctr].u.ki.dwFlags = GETFLAGS[ kev]; \
- ((TEST_INPUT*)inputs)[evtctr].u.ki.dwExtraInfo = 0; \
- ((TEST_INPUT*)inputs)[evtctr].u.ki.time = ++timetag; \
- if( kev) evtctr++;
-
typedef struct {
UINT message;
WPARAM wParam;
HMODULE hdll = GetModuleHandleA("user32");
#define GET_PROC(func) \
- p ## func = (void*)GetProcAddress(hdll, #func); \
- if(!p ## func) \
- trace("GetProcAddress(%s) failed\n", #func);
-
- GET_PROC(SendInput)
- GET_PROC(GetMouseMovePointsEx)
- GET_PROC(GetRawInputDeviceList)
- GET_PROC(GetWindowRgnBox)
-
+ if (!(p ## func = (void*)GetProcAddress(hdll, #func))) \
+ trace("GetProcAddress(%s) failed\n", #func)
+
+ GET_PROC(GetCurrentInputMessageSource);
+ GET_PROC(GetMouseMovePointsEx);
+ GET_PROC(GetPointerType);
+ GET_PROC(GetRawInputDeviceList);
+ GET_PROC(GetRawInputDeviceInfoW);
+ GET_PROC(GetRawInputDeviceInfoA);
+ GET_PROC(GetWindowRgnBox);
#undef GET_PROC
}
*/
static BOOL do_test( HWND hwnd, int seqnr, const KEV td[] )
{
- INPUT inputs[MAXKEYEVENTS];
+ TEST_INPUT inputs[MAXKEYEVENTS];
KMSG expmsg[MAXKEYEVENTS];
MSG msg;
char buf[100];
- UINT evtctr=0;
+ UINT evtctr=0, ret;
int kmctr, i;
buf[0]='\0';
TrackSysKey=0; /* see input.c */
- for( i = 0; i < MAXKEYEVENTS; i++) {
- ADDTOINPUTS(td[i])
+ for (i = 0; i < MAXKEYEVENTS; i++)
+ {
+ inputs[evtctr].type = INPUT_KEYBOARD;
+ inputs[evtctr].u.ki.wVk = GETVKEY[td[i]];
+ inputs[evtctr].u.ki.wScan = GETSCAN[td[i]];
+ inputs[evtctr].u.ki.dwFlags = GETFLAGS[td[i]];
+ inputs[evtctr].u.ki.dwExtraInfo = 0;
+ inputs[evtctr].u.ki.time = ++timetag;
+ if (td[i]) evtctr++;
+
strcat(buf, getdesc[td[i]]);
if(td[i])
expmsg[i].message = KbdMessage(td[i], &(expmsg[i].wParam), &(expmsg[i].lParam));
for( kmctr = 0; kmctr < MAXKEYEVENTS && expmsg[kmctr].message; kmctr++)
;
ok( evtctr <= MAXKEYEVENTS, "evtctr is above MAXKEYEVENTS\n" );
- if( evtctr != pSendInput(evtctr, &inputs[0], sizeof(INPUT)))
- ok (FALSE, "SendInput failed to send some events\n");
+ ret = SendInput(evtctr, (INPUT *)inputs, sizeof(INPUT));
+ ok(ret == evtctr, "SendInput failed to send some events\n");
i = 0;
if (winetest_debug > 1)
trace("======== key stroke sequence #%d: %s =============\n",
static UINT sent_messages_cnt;
/* Verify that only specified key state transitions occur */
-static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, const struct sendinput_test_s *test)
+static void compare_and_check(int id, BYTE *ks1, BYTE *ks2,
+ const struct sendinput_test_s *test, BOOL foreground)
{
int i, failcount = 0;
const struct transition_s *t = test->expected_transitions;
UINT actual_cnt = 0;
const struct message *expected = test->expected_messages;
- while (t->wVk) {
+ while (t->wVk && foreground) {
+ /* We won't receive any information from GetKeyboardState() if we're
+ * not the foreground window. */
BOOL matched = ((ks1[t->wVk]&0x80) == (t->before_state&0x80)
&& (ks2[t->wVk]&0x80) == (~t->before_state&0x80));
expected++;
continue;
}
+ else if (!(expected->flags & hook) && !foreground)
+ {
+ /* If we weren't able to receive foreground status, we won't get
+ * any window messages. */
+ expected++;
+ continue;
+ }
/* NT4 doesn't send SYSKEYDOWN/UP to hooks, only KEYDOWN/UP */
else if ((expected->flags & hook) &&
(expected->message == WM_SYSKEYDOWN || expected->message == WM_SYSKEYUP) &&
expected++;
}
/* skip all optional trailing messages */
- while (expected->message && (expected->flags & optional))
+ while (expected->message && ((expected->flags & optional) || (!(expected->flags & hook) && !foreground)))
expected++;
{
if (winetest_debug > 1) trace("MSG: %8x W:%8lx L:%8lx\n", Msg, wParam, lParam);
- if (Msg != WM_PAINT &&
- Msg != WM_NCPAINT &&
- Msg != WM_SYNCPAINT &&
- Msg != WM_ERASEBKGND &&
- Msg != WM_NCHITTEST &&
- Msg != WM_GETTEXT &&
- Msg != WM_GETICON &&
- Msg != WM_IME_SELECT &&
- Msg != WM_DEVICECHANGE &&
- Msg != WM_TIMECHANGE)
+ if ((Msg >= WM_KEYFIRST && Msg <= WM_KEYLAST) || Msg == WM_SYSCOMMAND)
{
ok(sent_messages_cnt < MAXKEYMESSAGES, "Too many messages\n");
if (sent_messages_cnt < MAXKEYMESSAGES)
int ii;
BYTE ks1[256], ks2[256];
LONG_PTR prevWndProc;
+ BOOL foreground;
HWND window;
HHOOK hook;
NULL, NULL);
ok(window != NULL, "error: %d\n", (int) GetLastError());
SetWindowPos( window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
- SetForegroundWindow( window );
+ foreground = SetForegroundWindow( window );
+ if (!foreground)
+ skip("Failed to set foreground window; some tests will be skipped.\n");
if (!(hook = SetWindowsHookExA(WH_KEYBOARD_LL, hook_proc, GetModuleHandleA( NULL ), 0)))
{
i.u.ki.time = 0;
i.u.ki.dwExtraInfo = 0;
- for (ii = 0; ii < sizeof(sendinput_test)/sizeof(struct sendinput_test_s)-1;
- ii++) {
+ for (ii = 0; ii < ARRAY_SIZE(sendinput_test)-1; ii++) {
GetKeyboardState(ks1);
i.u.ki.wScan = ii+1 /* useful for debugging */;
i.u.ki.dwFlags = sendinput_test[ii].dwFlags;
i.u.ki.wVk = sendinput_test[ii].wVk;
- pSendInput(1, (INPUT*)&i, sizeof(TEST_INPUT));
+ SendInput(1, (INPUT*)&i, sizeof(TEST_INPUT));
empty_message_queue();
GetKeyboardState(ks2);
- if (!ii && sent_messages_cnt <= 1 && !memcmp( ks1, ks2, sizeof(ks1) ))
- {
- win_skip( "window doesn't receive the queued input\n" );
- /* release the key */
- i.u.ki.dwFlags |= KEYEVENTF_KEYUP;
- pSendInput(1, (INPUT*)&i, sizeof(TEST_INPUT));
- break;
- }
- compare_and_check(ii, ks1, ks2, &sendinput_test[ii]);
+ compare_and_check(ii, ks1, ks2, &sendinput_test[ii], foreground);
}
empty_message_queue();
UnhookWindowsHookEx(hook);
}
-static void reset_key_status(void)
+static void reset_key_status(WORD vk)
{
key_status.last_key_down = -1;
key_status.last_key_up = -1;
key_status.last_hook_up = -1;
key_status.last_hook_syskey_down = -1;
key_status.last_hook_syskey_up = -1;
+ key_status.vk = vk;
key_status.expect_alt = FALSE;
key_status.sendinput_broken = FALSE;
}
inputs[0].u.ki.wScan = 0x3c0;
inputs[0].u.ki.dwFlags = KEYEVENTF_UNICODE;
- reset_key_status();
- pSendInput(1, (INPUT*)inputs, sizeof(INPUT));
+ reset_key_status(VK_PACKET);
+ SendInput(1, (INPUT*)inputs, sizeof(INPUT));
while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
if(msg.message == WM_KEYDOWN && msg.wParam == VK_PACKET){
TranslateMessage(&msg);
inputs[1].u.ki.wScan = 0x3c0;
inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
- reset_key_status();
- pSendInput(1, (INPUT*)(inputs+1), sizeof(INPUT));
+ reset_key_status(VK_PACKET);
+ SendInput(1, (INPUT*)(inputs+1), sizeof(INPUT));
while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
if(msg.message == WM_KEYDOWN && msg.wParam == VK_PACKET){
TranslateMessage(&msg);
inputs[1].u.ki.wScan = 0x3041;
inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE;
- reset_key_status();
+ reset_key_status(VK_PACKET);
key_status.expect_alt = TRUE;
- pSendInput(2, (INPUT*)inputs, sizeof(INPUT));
+ SendInput(2, (INPUT*)inputs, sizeof(INPUT));
while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
if(msg.message == WM_SYSKEYDOWN && msg.wParam == VK_PACKET){
TranslateMessage(&msg);
inputs[0].u.ki.wScan = 0;
inputs[0].u.ki.dwFlags = KEYEVENTF_KEYUP;
- reset_key_status();
+ reset_key_status(VK_PACKET);
key_status.expect_alt = TRUE;
- pSendInput(2, (INPUT*)inputs, sizeof(INPUT));
+ SendInput(2, (INPUT*)inputs, sizeof(INPUT));
while(PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)){
if(msg.message == WM_SYSKEYDOWN && msg.wParam == VK_PACKET){
TranslateMessage(&msg);
ok(key_status.last_hook_up == 0x3041,
"Last hook up msg should have been 0x3041, was: 0x%x\n", key_status.last_hook_up);
}
+
+ /* Press and release, non-zero key code. */
+ inputs[0].u.ki.wVk = 0x51;
+ inputs[0].u.ki.wScan = 0x123;
+ inputs[0].u.ki.dwFlags = KEYEVENTF_UNICODE;
+
+ inputs[1].u.ki.wVk = 0x51;
+ inputs[1].u.ki.wScan = 0x123;
+ inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
+
+ reset_key_status(inputs[0].u.ki.wVk);
+ SendInput(2, (INPUT*)inputs, sizeof(INPUT));
+ while (PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+
+ if (!key_status.sendinput_broken)
+ {
+ ok(key_status.last_key_down == 0x51, "Unexpected key down %#x.\n", key_status.last_key_down);
+ ok(key_status.last_key_up == 0x51, "Unexpected key up %#x.\n", key_status.last_key_up);
+ if (hook)
+ todo_wine
+ ok(key_status.last_hook_up == 0x23, "Unexpected hook message %#x.\n", key_status.last_hook_up);
+ }
}
static LRESULT CALLBACK unicode_wnd_proc( HWND hWnd, UINT msg, WPARAM wParam,
ok(info->vkCode == VK_LMENU, "vkCode should have been VK_LMENU[0x%04x], was: 0x%x\n", VK_LMENU, info->vkCode);
key_status.expect_alt = FALSE;
}else
- ok(info->vkCode == VK_PACKET, "vkCode should have been VK_PACKET[0x%04x], was: 0x%x\n", VK_PACKET, info->vkCode);
+ todo_wine_if(key_status.vk != VK_PACKET)
+ ok(info->vkCode == key_status.vk, "Unexpected vkCode %#x, expected %#x.\n", info->vkCode, key_status.vk);
}
switch(wParam){
case WM_KEYDOWN:
static void test_GetRawInputDeviceList(void)
{
RAWINPUTDEVICELIST devices[32];
- UINT ret, oret, devcount, odevcount;
+ UINT ret, oret, devcount, odevcount, i;
DWORD err;
SetLastError(0xdeadbeef);
ret = pGetRawInputDeviceList(devices, &devcount, sizeof(devices[0]));
ok(ret > 0, "expected non-zero\n");
+ for(i = 0; i < devcount; ++i)
+ {
+ WCHAR name[128];
+ char nameA[128];
+ UINT sz, len;
+ RID_DEVICE_INFO info;
+ HANDLE file;
+
+ /* get required buffer size */
+ name[0] = '\0';
+ sz = 5;
+ ret = pGetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICENAME, name, &sz);
+ ok(ret == -1, "GetRawInputDeviceInfo gave wrong failure: %d\n", err);
+ ok(sz > 5 && sz < ARRAY_SIZE(name), "Size should have been set and not too large (got: %u)\n", sz);
+
+ /* buffer size for RIDI_DEVICENAME is in CHARs, not BYTEs */
+ ret = pGetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICENAME, name, &sz);
+ ok(ret == sz, "GetRawInputDeviceInfo gave wrong return: %d\n", err);
+ len = lstrlenW(name);
+ ok(len + 1 == ret, "GetRawInputDeviceInfo returned wrong length (name: %u, ret: %u)\n", len + 1, ret);
+
+ /* test A variant with same size */
+ ret = pGetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, nameA, &sz);
+ ok(ret == sz, "GetRawInputDeviceInfoA gave wrong return: %d\n", err);
+ len = strlen(nameA);
+ ok(len + 1 == ret, "GetRawInputDeviceInfoA returned wrong length (name: %u, ret: %u)\n", len + 1, ret);
+
+ /* buffer size for RIDI_DEVICEINFO is in BYTEs */
+ memset(&info, 0, sizeof(info));
+ info.cbSize = sizeof(info);
+ sz = sizeof(info) - 1;
+ ret = pGetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICEINFO, &info, &sz);
+ ok(ret == -1, "GetRawInputDeviceInfo gave wrong failure: %d\n", err);
+ ok(sz == sizeof(info), "GetRawInputDeviceInfo set wrong size\n");
+
+ ret = pGetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICEINFO, &info, &sz);
+ ok(ret == sizeof(info), "GetRawInputDeviceInfo gave wrong return: %d\n", err);
+ ok(sz == sizeof(info), "GetRawInputDeviceInfo set wrong size\n");
+ ok(info.dwType == devices[i].dwType, "GetRawInputDeviceInfo set wrong type: 0x%x\n", info.dwType);
+
+ memset(&info, 0, sizeof(info));
+ info.cbSize = sizeof(info);
+ ret = pGetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &info, &sz);
+ ok(ret == sizeof(info), "GetRawInputDeviceInfo gave wrong return: %d\n", err);
+ ok(sz == sizeof(info), "GetRawInputDeviceInfo set wrong size\n");
+ ok(info.dwType == devices[i].dwType, "GetRawInputDeviceInfo set wrong type: 0x%x\n", info.dwType);
+
+ /* setupapi returns an NT device path, but CreateFile() < Vista can't
+ * understand that; so use the \\?\ prefix instead */
+ name[1] = '\\';
+ file = CreateFileW(name, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ todo_wine_if(info.dwType != RIM_TYPEHID)
+ ok(file != INVALID_HANDLE_VALUE, "Failed to open %s, error %u\n", wine_dbgstr_w(name), GetLastError());
+ CloseHandle(file);
+ }
+
/* check if variable changes from larger to smaller value */
- devcount = odevcount = sizeof(devices) / sizeof(devices[0]);
+ devcount = odevcount = ARRAY_SIZE(devices);
oret = ret = pGetRawInputDeviceList(devices, &odevcount, sizeof(devices[0]));
ok(ret > 0, "expected non-zero\n");
ok(devcount == odevcount, "expected %d, got %d\n", devcount, odevcount);
devcount = odevcount;
- odevcount = sizeof(devices) / sizeof(devices[0]);
+ odevcount = ARRAY_SIZE(devices);
ret = pGetRawInputDeviceList(NULL, &odevcount, sizeof(devices[0]));
ok(ret == 0, "expected 0, got %d\n", ret);
ok(odevcount == oret, "expected %d, got %d\n", oret, odevcount);
}
+static void test_GetRawInputData(void)
+{
+ UINT size;
+ UINT ret;
+
+ /* Null raw input handle */
+ ret = GetRawInputData(NULL, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
+ ok(ret == ~0U, "Expect ret %u, got %u\n", ~0U, ret);
+}
+
static void test_key_map(void)
{
HKL kl = GetKeyboardLayout(0);
"Scan code -> vKey = %x (not VK_RSHIFT)\n", kR);
/* test that MAPVK_VSC_TO_VK prefers the non-numpad vkey if there's ambiguity */
- for (i = 0; i < sizeof(numpad_collisions)/sizeof(numpad_collisions[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(numpad_collisions); i++)
{
UINT numpad_scan = MapVirtualKeyExA(numpad_collisions[i][0], MAPVK_VK_TO_VSC, kl);
UINT other_scan = MapVirtualKeyExA(numpad_collisions[i][1], MAPVK_VK_TO_VSC, kl);
"ToUnicode didn't null-terminate the buffer when there was room.\n");
}
- for (i = 0; i < sizeof(utests) / sizeof(utests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(utests); i++)
{
UINT vk = utests[i].vk, mod = utests[i].modifiers, scan;
ok( buffer[0] == 0, "wrong string '%s'\n", buffer );
memset( bufferW, 0xcc, sizeof(bufferW) );
- ret = GetKeyNameTextW( lparam, bufferW, sizeof(bufferW)/sizeof(WCHAR) );
+ ret = GetKeyNameTextW( lparam, bufferW, ARRAY_SIZE(bufferW));
ok( ret > 0, "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
ok( ret == lstrlenW(bufferW), "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) );
ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
}
+ get_dc_region(®ion, hwnd, DCX_PARENTCLIP);
+ ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
+ "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(®ion));
+ get_dc_region(®ion, hwnd, DCX_WINDOW | DCX_USESTYLE);
+ ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
+ "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(®ion));
+ get_dc_region(®ion, hwnd, DCX_USESTYLE);
+ ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
+ "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(®ion));
+ get_dc_region(®ion, static_win, DCX_PARENTCLIP);
+ ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
+ "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(®ion));
+ get_dc_region(®ion, static_win, DCX_WINDOW | DCX_USESTYLE);
+ ok(region.left == 110 && region.top == 110 && region.right == 130 && region.bottom == 130,
+ "expected region (110,110)-(130,130), got %s\n", wine_dbgstr_rect(®ion));
+ get_dc_region(®ion, static_win, DCX_USESTYLE);
+ ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
+ "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(®ion));
+
got_button_down = got_button_up = FALSE;
simulate_click(TRUE, 150, 150);
while (wait_for_message(&msg))
if (msg.message == WM_LBUTTONDOWN)
{
- todo_wine
ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
got_button_down = TRUE;
}
else if (msg.message == WM_LBUTTONUP)
{
- todo_wine
ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
got_button_up = TRUE;
break;
ok(region_type == ERROR, "expected ERROR, got %d\n", region_type);
}
- get_dc_region(®ion, hwnd, DCX_PARENTCLIP);
- ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
- "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(®ion));
- get_dc_region(®ion, hwnd, DCX_WINDOW | DCX_USESTYLE);
- ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
- "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(®ion));
- get_dc_region(®ion, hwnd, DCX_USESTYLE);
- ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
- "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(®ion));
- get_dc_region(®ion, static_win, DCX_PARENTCLIP);
- ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
- "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(®ion));
- get_dc_region(®ion, static_win, DCX_WINDOW | DCX_USESTYLE);
- ok(region.left == 110 && region.top == 110 && region.right == 130 && region.bottom == 130,
- "expected region (110,110)-(130,130), got %s\n", wine_dbgstr_rect(®ion));
- get_dc_region(®ion, static_win, DCX_USESTYLE);
- ok(region.left == 100 && region.top == 100 && region.right == 200 && region.bottom == 200,
- "expected region (100,100)-(200,200), got %s\n", wine_dbgstr_rect(®ion));
-
got_button_down = got_button_up = FALSE;
simulate_click(TRUE, 150, 150);
while (wait_for_message(&msg))
if (msg.message == WM_LBUTTONDOWN)
{
+ todo_wine
ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
got_button_down = TRUE;
}
else if (msg.message == WM_LBUTTONUP)
{
+ todo_wine
ok(msg.hwnd == button_win, "msg.hwnd = %p\n", msg.hwnd);
got_button_up = TRUE;
break;
result = WaitForSingleObject(semaphores[0], 1000);
ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result);
+ SetForegroundWindow(hwnd);
SetFocus(hwnd);
keybd_event('X', 0, 0, 0);
}
}
-START_TEST(input)
+static INPUT_MESSAGE_SOURCE expect_src;
+
+static LRESULT WINAPI msg_source_proc( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
- init_function_pointers();
+ INPUT_MESSAGE_SOURCE source;
+ MSG msg;
- if (pSendInput)
+ ok( pGetCurrentInputMessageSource( &source ), "GetCurrentInputMessageSource failed\n" );
+ switch (message)
{
- test_Input_blackbox();
- test_Input_whitebox();
- test_Input_unicode();
- test_Input_mouse();
+ case WM_KEYDOWN:
+ case WM_KEYUP:
+ case WM_SYSKEYDOWN:
+ case WM_SYSKEYUP:
+ case WM_MOUSEMOVE:
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONUP:
+ ok( source.deviceType == expect_src.deviceType || /* also accept system-generated WM_MOUSEMOVE */
+ (message == WM_MOUSEMOVE && source.deviceType == IMDT_UNAVAILABLE),
+ "%x: wrong deviceType %x/%x\n", message, source.deviceType, expect_src.deviceType );
+ ok( source.originId == expect_src.originId ||
+ (message == WM_MOUSEMOVE && source.originId == IMO_SYSTEM),
+ "%x: wrong originId %x/%x\n", message, source.originId, expect_src.originId );
+ SendMessageA( hwnd, WM_USER, 0, 0 );
+ PostMessageA( hwnd, WM_USER, 0, 0 );
+ if (PeekMessageW( &msg, hwnd, WM_USER, WM_USER, PM_REMOVE )) DispatchMessageW( &msg );
+ ok( source.deviceType == expect_src.deviceType || /* also accept system-generated WM_MOUSEMOVE */
+ (message == WM_MOUSEMOVE && source.deviceType == IMDT_UNAVAILABLE),
+ "%x: wrong deviceType %x/%x\n", message, source.deviceType, expect_src.deviceType );
+ ok( source.originId == expect_src.originId ||
+ (message == WM_MOUSEMOVE && source.originId == IMO_SYSTEM),
+ "%x: wrong originId %x/%x\n", message, source.originId, expect_src.originId );
+ break;
+ default:
+ ok( source.deviceType == IMDT_UNAVAILABLE, "%x: wrong deviceType %x\n",
+ message, source.deviceType );
+ ok( source.originId == 0, "%x: wrong originId %x\n", message, source.originId );
+ break;
}
- else win_skip("SendInput is not available\n");
+ return DefWindowProcA( hwnd, message, wp, lp );
+}
+
+static void test_input_message_source(void)
+{
+ WNDCLASSA cls;
+ TEST_INPUT inputs[2];
+ HWND hwnd;
+ RECT rc;
+ MSG msg;
+
+ cls.style = 0;
+ cls.lpfnWndProc = msg_source_proc;
+ cls.cbClsExtra = 0;
+ cls.cbWndExtra = 0;
+ cls.hInstance = GetModuleHandleA(0);
+ cls.hIcon = 0;
+ cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
+ cls.hbrBackground = 0;
+ cls.lpszMenuName = NULL;
+ cls.lpszClassName = "message source class";
+ RegisterClassA(&cls);
+ hwnd = CreateWindowA( cls.lpszClassName, "test", WS_OVERLAPPED, 0, 0, 100, 100,
+ 0, 0, 0, 0 );
+ ShowWindow( hwnd, SW_SHOWNORMAL );
+ UpdateWindow( hwnd );
+ SetForegroundWindow( hwnd );
+ SetFocus( hwnd );
+
+ inputs[0].type = INPUT_KEYBOARD;
+ inputs[0].u.ki.dwExtraInfo = 0;
+ inputs[0].u.ki.time = 0;
+ inputs[0].u.ki.wVk = 0;
+ inputs[0].u.ki.wScan = 0x3c0;
+ inputs[0].u.ki.dwFlags = KEYEVENTF_UNICODE;
+ inputs[1] = inputs[0];
+ inputs[1].u.ki.dwFlags |= KEYEVENTF_KEYUP;
+
+ expect_src.deviceType = IMDT_UNAVAILABLE;
+ expect_src.originId = IMO_UNAVAILABLE;
+ SendMessageA( hwnd, WM_KEYDOWN, 0, 0 );
+ SendMessageA( hwnd, WM_MOUSEMOVE, 0, 0 );
+
+ SendInput( 2, (INPUT *)inputs, sizeof(INPUT) );
+ while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ))
+ {
+ expect_src.deviceType = IMDT_KEYBOARD;
+ expect_src.originId = IMO_INJECTED;
+ TranslateMessage( &msg );
+ DispatchMessageW( &msg );
+ }
+ GetWindowRect( hwnd, &rc );
+ simulate_click( TRUE, (rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2 );
+ simulate_click( FALSE, (rc.left + rc.right) / 2 + 1, (rc.top + rc.bottom) / 2 + 1 );
+ while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ))
+ {
+ expect_src.deviceType = IMDT_MOUSE;
+ expect_src.originId = IMO_INJECTED;
+ TranslateMessage( &msg );
+ DispatchMessageW( &msg );
+ }
+
+ expect_src.deviceType = IMDT_UNAVAILABLE;
+ expect_src.originId = IMO_UNAVAILABLE;
+ SendMessageA( hwnd, WM_KEYDOWN, 0, 0 );
+ SendMessageA( hwnd, WM_LBUTTONDOWN, 0, 0 );
+ PostMessageA( hwnd, WM_KEYUP, 0, 0 );
+ PostMessageA( hwnd, WM_LBUTTONUP, 0, 0 );
+ while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ))
+ {
+ TranslateMessage( &msg );
+ DispatchMessageW( &msg );
+ }
+
+ expect_src.deviceType = IMDT_UNAVAILABLE;
+ expect_src.originId = IMO_SYSTEM;
+ SetCursorPos( (rc.left + rc.right) / 2 - 1, (rc.top + rc.bottom) / 2 - 1 );
+ while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ))
+ {
+ TranslateMessage( &msg );
+ DispatchMessageW( &msg );
+ }
+
+ DestroyWindow( hwnd );
+ UnregisterClassA( cls.lpszClassName, GetModuleHandleA(0) );
+}
+
+static void test_GetPointerType(void)
+{
+ BOOL ret;
+ POINTER_INPUT_TYPE type = -1;
+ UINT id = 0;
+
+ SetLastError(0xdeadbeef);
+ ret = pGetPointerType(id, NULL);
+ ok(!ret, "GetPointerType should have failed.\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER,
+ "expected error ERROR_INVALID_PARAMETER, got %u.\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pGetPointerType(id, &type);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER,
+ "expected error ERROR_INVALID_PARAMETER, got %u.\n", GetLastError());
+ ok(!ret, "GetPointerType failed, got type %d for %u.\n", type, id );
+ ok(type == -1, " type %d\n", type );
+
+ id = 1;
+ ret = pGetPointerType(id, &type);
+ ok(ret, "GetPointerType failed, got type %d for %u.\n", type, id );
+ ok(type == PT_MOUSE, " type %d\n", type );
+}
+
+static void test_GetKeyboardLayoutList(void)
+{
+ int cnt, cnt2;
+ HKL *layouts;
+ ULONG_PTR baselayout;
+ LANGID langid;
+
+ baselayout = GetUserDefaultLCID();
+ langid = PRIMARYLANGID(LANGIDFROMLCID(baselayout));
+ if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
+ baselayout = MAKELONG( baselayout, 0xe001 ); /* IME */
+ else
+ baselayout |= baselayout << 16;
+
+ cnt = GetKeyboardLayoutList(0, NULL);
+ /* Most users will not have more than a few keyboard layouts installed at a time. */
+ ok(cnt > 0 && cnt < 10, "Layout count %d\n", cnt);
+ if (cnt > 0)
+ {
+ layouts = HeapAlloc(GetProcessHeap(), 0, sizeof(*layouts) * cnt );
+
+ cnt2 = GetKeyboardLayoutList(cnt, layouts);
+ ok(cnt == cnt2, "wrong value %d!=%d\n", cnt, cnt2);
+ for(cnt = 0; cnt < cnt2; cnt++)
+ {
+ if(layouts[cnt] == (HKL)baselayout)
+ break;
+ }
+ ok(cnt < cnt2, "Didnt find current keyboard\n");
+
+ HeapFree(GetProcessHeap(), 0, layouts);
+ }
+}
+
+START_TEST(input)
+{
+ POINT pos;
+
+ init_function_pointers();
+ GetCursorPos( &pos );
+
+ test_Input_blackbox();
+ test_Input_whitebox();
+ test_Input_unicode();
+ test_Input_mouse();
test_keynames();
test_mouse_ll_hook();
test_key_map();
test_attach_input();
test_GetKeyState();
test_OemKeyScan();
+ test_GetRawInputData();
+ test_GetKeyboardLayoutList();
if(pGetMouseMovePointsEx)
test_GetMouseMovePointsEx();
test_GetRawInputDeviceList();
else
win_skip("GetRawInputDeviceList is not available\n");
+
+ if (pGetCurrentInputMessageSource)
+ test_input_message_source();
+ else
+ win_skip("GetCurrentInputMessageSource is not available\n");
+
+ SetCursorPos( pos.x, pos.y );
+
+ if(pGetPointerType)
+ test_GetPointerType();
+ else
+ win_skip("GetPointerType is not available\n");
}
WCHAR buf[1024];
if (!stra) return 1;
- MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf));
return lstrcmpW(strw, buf);
}
};
struct listbox_test {
- struct listbox_prop prop;
struct listbox_stat init, init_todo;
struct listbox_stat click, click_todo;
struct listbox_stat step, step_todo;
#define listbox_field_ok(t, s, f, got) \
ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
- ": expected %d, got %d\n", (unsigned int)t.prop.add_style, \
- t.s.f, got.f)
+ ": expected %d, got %d\n", style, t.s.f, got.f)
#define listbox_todo_field_ok(t, s, f, got) \
todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); }
listbox_todo_field_ok(t, s, selcount, got)
static void
-check (const struct listbox_test test)
+check (DWORD style, const struct listbox_test test)
{
struct listbox_stat answer;
- HWND hLB=create_listbox (test.prop.add_style, 0);
RECT second_item;
int i;
int res;
+ HWND hLB;
+
+ hLB = create_listbox (style, 0);
listbox_query (hLB, &answer);
listbox_ok (test, init, answer);
listbox_ok (test, step, answer);
DestroyWindow (hLB);
- hLB=create_listbox (test.prop.add_style, 0);
+ hLB = create_listbox(style, 0);
SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
listbox_query (hLB, &answer);
listbox_ok (test, sel, answer);
- for (i=0;i<4;i++) {
+ for (i = 0; i < 4 && !(style & LBS_NODATA); i++) {
DWORD size = SendMessageA(hLB, LB_GETTEXTLEN, i, 0);
CHAR *txt;
WCHAR *txtw;
txtw = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, 2*size+2);
resW=SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw);
- if (resA != resW) {
- trace("SendMessageW(LB_GETTEXT) not supported on this platform (resA=%d resW=%d), skipping...\n",
- resA, resW);
- } else {
- WideCharToMultiByte( CP_ACP, 0, txtw, -1, txt, size, NULL, NULL );
- ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
- }
+ ok(resA == resW, "Unexpected text length.\n");
+ WideCharToMultiByte( CP_ACP, 0, txtw, -1, txt, size, NULL, NULL );
+ ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
HeapFree (GetProcessHeap(), 0, txtw);
HeapFree (GetProcessHeap(), 0, txt);
static void test_ownerdraw(void)
{
+ static const DWORD styles[] =
+ {
+ 0,
+ LBS_NODATA
+ };
HWND parent, hLB;
INT ret;
RECT rc;
+ UINT i;
parent = create_parent();
assert(parent);
- hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
- assert(hLB);
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
+ {
+ hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE | styles[i], parent);
+ assert(hLB);
- SetForegroundWindow(hLB);
- UpdateWindow(hLB);
+ SetForegroundWindow(hLB);
+ UpdateWindow(hLB);
- /* make height short enough */
- SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
- SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
- SWP_NOZORDER | SWP_NOMOVE);
+ /* make height short enough */
+ SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
+ SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
+ SWP_NOZORDER | SWP_NOMOVE);
- /* make 0 item invisible */
- SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
- ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
- ok(ret == 1, "wrong top index %d\n", ret);
+ /* make 0 item invisible */
+ SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
+ ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
+ ok(ret == 1, "wrong top index %d\n", ret);
- SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
- trace("item 0 rect %s\n", wine_dbgstr_rect(&rc));
- ok(!IsRectEmpty(&rc), "empty item rect\n");
- ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
+ SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
+ trace("item 0 rect %s\n", wine_dbgstr_rect(&rc));
+ ok(!IsRectEmpty(&rc), "empty item rect\n");
+ ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
- DestroyWindow(hLB);
+ DestroyWindow(hLB);
+
+ /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */
+ hLB = CreateWindowA("listbox", "TestList", LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE | styles[i],
+ 0, 0, 100, 100, NULL, NULL, NULL, 0);
+ ok(hLB != NULL, "last error 0x%08x\n", GetLastError());
+
+ ok(GetWindowLongA(hLB, GWL_STYLE) & LBS_OWNERDRAWVARIABLE, "Unexpected window style.\n");
+
+ ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 13);
+ ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
+ ok(ret == 13, "Unexpected item height %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 1, 42);
+ ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
+ ok(ret == 42, "Unexpected item height %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 1, 0);
+ ok(ret == 42, "Unexpected item height %d.\n", ret);
+
+ DestroyWindow (hLB);
+ }
DestroyWindow(parent);
}
SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 32);
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
ok(ret == 2, "LB_SETCURSEL returned %d instead of 2\n", ret);
ret = GetScrollPos(hLB, SB_VERT);
ok(ret == 0, "expected vscroll 0, got %d\n", ret);
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
ret = SendMessageA(hLB, LB_SETCURSEL, 3, 0);
ok(ret == 3, "LB_SETCURSEL returned %d instead of 3\n", ret);
ret = GetScrollPos(hLB, SB_VERT);
ok(ret == 1, "expected vscroll 1, got %d\n", ret);
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ DestroyWindow(hLB);
+
+ hLB = create_listbox(0, 0);
+ ok(hLB != NULL, "Failed to create ListBox window.\n");
+
+ ret = SendMessageA(hLB, LB_SETCURSEL, 1, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ DestroyWindow(hLB);
+
+ /* LBS_EXTENDEDSEL */
+ hLB = create_listbox(LBS_EXTENDEDSEL, 0);
+ ok(hLB != NULL, "Failed to create ListBox window.\n");
+
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
+ ok(ret == -1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ DestroyWindow(hLB);
+
+ /* LBS_MULTIPLESEL */
+ hLB = create_listbox(LBS_MULTIPLESEL, 0);
+ ok(hLB != NULL, "Failed to create ListBox window.\n");
+
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
+ ok(ret == -1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
DestroyWindow(hLB);
}
+static void test_LB_SETSEL(void)
+{
+ HWND list;
+ int ret;
+
+ /* LBS_EXTENDEDSEL */
+ list = create_listbox(LBS_EXTENDEDSEL, 0);
+ ok(list != NULL, "Failed to create ListBox window.\n");
+
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 0, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 1, "Unexpected anchor index %d.\n", ret);
+
+ DestroyWindow(list);
+
+ /* LBS_MULTIPLESEL */
+ list = create_listbox(LBS_MULTIPLESEL, 0);
+ ok(list != NULL, "Failed to create ListBox window.\n");
+
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == -1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 0, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 1, "Unexpected anchor index %d.\n", ret);
+
+ ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
+ ok(ret == 1, "Unexpected anchor index %d.\n", ret);
+
+ DestroyWindow(list);
+}
+
static void test_listbox_height(void)
{
HWND hList;
DestroyWindow( hList );
}
+static void test_changing_selection_styles(void)
+{
+ static const DWORD styles[] =
+ {
+ 0,
+ LBS_NODATA | LBS_OWNERDRAWFIXED
+ };
+ static const DWORD selstyles[] =
+ {
+ 0,
+ LBS_MULTIPLESEL,
+ LBS_EXTENDEDSEL,
+ LBS_MULTIPLESEL | LBS_EXTENDEDSEL
+ };
+ static const LONG selexpect_single[] = { 0, 0, 1 };
+ static const LONG selexpect_single2[] = { 1, 0, 0 };
+ static const LONG selexpect_multi[] = { 1, 0, 1 };
+ static const LONG selexpect_multi2[] = { 1, 1, 0 };
+
+ HWND parent, listbox;
+ DWORD style;
+ LONG ret;
+ UINT i, j, k;
+
+ parent = create_parent();
+ ok(parent != NULL, "Failed to create parent window.\n");
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
+ {
+ /* Test if changing selection styles affects selection storage */
+ for (j = 0; j < ARRAY_SIZE(selstyles); j++)
+ {
+ LONG setcursel_expect, selitemrange_expect, getselcount_expect;
+ const LONG *selexpect;
+
+ listbox = CreateWindowA("listbox", "TestList", styles[i] | selstyles[j] | WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100, parent, (HMENU)1, NULL, 0);
+ ok(listbox != NULL, "%u: Failed to create ListBox window.\n", j);
+
+ if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
+ {
+ setcursel_expect = LB_ERR;
+ selitemrange_expect = LB_OKAY;
+ getselcount_expect = 2;
+ selexpect = selexpect_multi;
+ }
+ else
+ {
+ setcursel_expect = 2;
+ selitemrange_expect = LB_ERR;
+ getselcount_expect = LB_ERR;
+ selexpect = selexpect_single;
+ }
+
+ for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
+ {
+ ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"x");
+ ok(ret == k, "%u: Unexpected return value %d, expected %d.\n", j, ret, k);
+ }
+ ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
+ ok(ret == ARRAY_SIZE(selexpect_multi), "%u: Unexpected count %d.\n", j, ret);
+
+ /* Select items with different methods */
+ ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0);
+ ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
+ ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 0));
+ ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
+ ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 2));
+ ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
+
+ /* Verify that the proper items are selected */
+ for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
+ {
+ ret = SendMessageA(listbox, LB_GETSEL, k, 0);
+ ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
+ j, ret, selexpect[k]);
+ }
+
+ /* Now change the selection style */
+ style = GetWindowLongA(listbox, GWL_STYLE);
+ ok((style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == selstyles[j],
+ "%u: unexpected window styles %#x.\n", j, style);
+ if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
+ style &= ~selstyles[j];
+ else
+ style |= LBS_MULTIPLESEL | LBS_EXTENDEDSEL;
+ SetWindowLongA(listbox, GWL_STYLE, style);
+ style = GetWindowLongA(listbox, GWL_STYLE);
+ ok(!(style & selstyles[j]), "%u: unexpected window styles %#x.\n", j, style);
+
+ /* Verify that the same items are selected */
+ ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
+ ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
+ j, getselcount_expect, ret);
+
+ for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
+ {
+ ret = SendMessageA(listbox, LB_GETSEL, k, 0);
+ ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
+ j, ret, selexpect[k]);
+ }
+
+ /* Lastly see if we can still change the selection as before with old style */
+ if (setcursel_expect != LB_ERR) setcursel_expect = 0;
+ ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0);
+ ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
+ ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 1));
+ ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
+ ret = SendMessageA(listbox, LB_SELITEMRANGE, FALSE, MAKELPARAM(2, 2));
+ ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
+
+ /* And verify the selections */
+ selexpect = (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) ? selexpect_multi2 : selexpect_single2;
+ ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
+ ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
+ j, getselcount_expect, ret);
+
+ for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
+ {
+ ret = SendMessageA(listbox, LB_GETSEL, k, 0);
+ ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
+ j, ret, selexpect[k]);
+ }
+
+ DestroyWindow(listbox);
+ }
+ }
+ DestroyWindow(parent);
+}
+
static void test_itemfrompoint(void)
{
/* WS_POPUP is required in order to have a more accurate size calculation (
static void test_listbox_LB_DIR(void)
{
+ char path[MAX_PATH], curdir[MAX_PATH];
HWND hList;
int res, itemCount;
int itemCount_justFiles;
char driveletter;
const char *wildcard = "*";
HANDLE file;
+ BOOL ret;
+
+ GetCurrentDirectoryA(ARRAY_SIZE(curdir), curdir);
+
+ GetTempPathA(ARRAY_SIZE(path), path);
+ ret = SetCurrentDirectoryA(path);
+ ok(ret, "Failed to set current directory.\n");
+
+ ret = CreateDirectoryA("lb_dir_test", NULL);
+ ok(ret, "Failed to create test directory.\n");
file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
itemCount, itemCount_allDirs);
ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
- if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
+ if (itemCount)
{
memset(pathBuffer, 0, MAX_PATH);
SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
- ok( !strcmp(pathBuffer, "[..]"), "First element is not [..]\n");
+ ok( !strcmp(pathBuffer, "[..]"), "First element is %s, not [..]\n", pathBuffer);
}
/* This tests behavior when no files match the wildcard */
DestroyWindow(hList);
DeleteFileA( "wtest1.tmp.c" );
+ RemoveDirectoryA("lb_dir_test");
+
+ SetCurrentDirectoryA(curdir);
}
static HWND g_listBox;
strcpy(pathBuffer, "C:\\");
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\ folders\n");
- todo_wine ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
+ ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
"DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
strcpy(pathBuffer, "C:\\*");
SetLastError(0xdeadbeef);
strcpy(pathBuffer, "C:\\INVALID$$DIR");
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
- todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
- todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
+ ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
+ ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
"GetLastError should return 0x589, got 0x%X\n",GetLastError());
DestroyWindow(hWnd);
static void test_set_count( void )
{
+ static const DWORD styles[] =
+ {
+ LBS_OWNERDRAWFIXED,
+ LBS_HASSTRINGS,
+ };
HWND parent, listbox;
+ unsigned int i;
LONG ret;
RECT r;
GetUpdateRect( listbox, &r, TRUE );
ok( !IsRectEmpty( &r ), "got empty rect\n");
+ ret = SendMessageA( listbox, LB_SETCOUNT, -5, 0 );
+ ok( ret == 0, "got %d\n", ret );
+ ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
+ ok( ret == -5, "got %d\n", ret );
+
DestroyWindow( listbox );
+
+ for (i = 0; i < ARRAY_SIZE(styles); ++i)
+ {
+ listbox = create_listbox( styles[i] | WS_CHILD | WS_VISIBLE, parent );
+
+ SetLastError( 0xdeadbeef );
+ ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
+ ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret );
+ ok( GetLastError() == ERROR_SETCOUNT_ON_BAD_LB, "Unexpected error %d.\n", GetLastError() );
+
+ DestroyWindow( listbox );
+ }
+
DestroyWindow( parent );
}
DestroyWindow(parent);
}
+static void test_init_storage( void )
+{
+ static const DWORD styles[] =
+ {
+ LBS_HASSTRINGS,
+ LBS_NODATA | LBS_OWNERDRAWFIXED,
+ };
+ HWND parent, listbox;
+ LONG ret, items_size;
+ int i, j;
+
+ parent = create_parent();
+ for (i = 0; i < ARRAY_SIZE(styles); i++)
+ {
+ listbox = CreateWindowA("listbox", "TestList", styles[i] | WS_CHILD,
+ 0, 0, 100, 100, parent, (HMENU)1, NULL, 0);
+
+ items_size = SendMessageA(listbox, LB_INITSTORAGE, 100, 0);
+ ok(items_size >= 100, "expected at least 100, got %d\n", items_size);
+
+ ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
+ ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
+
+ /* it doesn't grow since the space was already reserved */
+ ret = SendMessageA(listbox, LB_INITSTORAGE, items_size, 0);
+ ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
+
+ /* it doesn't shrink the reserved space */
+ ret = SendMessageA(listbox, LB_INITSTORAGE, 42, 0);
+ ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
+
+ /* now populate almost all of it so it's not reserved anymore */
+ if (styles[i] & LBS_NODATA)
+ {
+ ret = SendMessageA(listbox, LB_SETCOUNT, items_size - 1, 0);
+ ok(ret == 0, "unexpected return value %d\n", ret);
+ }
+ else
+ {
+ for (j = 0; j < items_size - 1; j++)
+ {
+ ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
+ ok(ret == j, "expected %d, got %d\n", j, ret);
+ }
+ }
+
+ /* we still have one more reserved slot, so it doesn't grow yet */
+ ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
+ ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
+
+ /* fill the slot and check again, it should grow this time */
+ ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
+ ok(ret == items_size - 1, "expected %d, got %d\n", items_size - 1, ret);
+ ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
+ ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
+ ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
+ ok(ret > items_size, "expected it to grow past %d, got %d\n", items_size, ret);
+
+ DestroyWindow(listbox);
+ }
+ DestroyWindow(parent);
+}
+
static void test_missing_lbuttonup( void )
{
HWND listbox, parent, capture;
DestroyWindow(parent);
}
+static void test_LBS_NODATA(void)
+{
+ static const DWORD invalid_styles[] =
+ {
+ 0,
+ LBS_OWNERDRAWVARIABLE,
+ LBS_SORT,
+ LBS_HASSTRINGS,
+ LBS_OWNERDRAWFIXED | LBS_SORT,
+ LBS_OWNERDRAWFIXED | LBS_HASSTRINGS,
+ };
+ static const UINT invalid_idx[] = { -2, 2 };
+ static const UINT valid_idx[] = { 0, 1 };
+ static const ULONG_PTR zero_data;
+ HWND listbox, parent;
+ unsigned int i;
+ ULONG_PTR data;
+ INT ret;
+
+ listbox = CreateWindowA("listbox", "TestList", LBS_NODATA | LBS_OWNERDRAWFIXED | WS_VISIBLE,
+ 0, 0, 100, 100, NULL, NULL, NULL, 0);
+ ok(listbox != NULL, "Failed to create ListBox window.\n");
+
+ ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
+ ok(ret == 2, "Unexpected return value %d.\n", ret);
+
+ /* Invalid indices. */
+ for (i = 0; i < ARRAY_SIZE(invalid_idx); ++i)
+ {
+ ret = SendMessageA(listbox, LB_SETITEMDATA, invalid_idx[i], 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_GETTEXTLEN, invalid_idx[i], 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ if (ret == LB_ERR)
+ {
+ ret = SendMessageA(listbox, LB_GETTEXT, invalid_idx[i], (LPARAM)&data);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ }
+ ret = SendMessageA(listbox, LB_GETITEMDATA, invalid_idx[i], 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ }
+
+ /* Valid indices. */
+ for (i = 0; i < ARRAY_SIZE(valid_idx); ++i)
+ {
+ ret = SendMessageA(listbox, LB_SETITEMDATA, valid_idx[i], 42);
+ ok(ret == TRUE, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(listbox, LB_GETTEXTLEN, valid_idx[i], 0);
+ ok(ret == sizeof(data), "Unexpected return value %d.\n", ret);
+
+ memset(&data, 0xee, sizeof(data));
+ ret = SendMessageA(listbox, LB_GETTEXT, valid_idx[i], (LPARAM)&data);
+ ok(ret == sizeof(data), "Unexpected return value %d.\n", ret);
+ ok(!memcmp(&data, &zero_data, sizeof(data)), "Unexpected item data.\n");
+
+ ret = SendMessageA(listbox, LB_GETITEMDATA, valid_idx[i], 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ }
+
+ /* More messages that don't work with LBS_NODATA. */
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_FINDSTRING, 1, 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_FINDSTRING, 1, 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 0);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 42);
+ ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
+
+ DestroyWindow(listbox);
+
+ /* Invalid window style combinations. */
+ parent = create_parent();
+ ok(parent != NULL, "Failed to create parent window.\n");
+
+ for (i = 0; i < ARRAY_SIZE(invalid_styles); ++i)
+ {
+ DWORD style;
+
+ listbox = CreateWindowA("listbox", "TestList", LBS_NODATA | WS_CHILD | invalid_styles[i],
+ 0, 0, 100, 100, parent, (HMENU)1, NULL, 0);
+ ok(listbox != NULL, "Failed to create a listbox.\n");
+
+ style = GetWindowLongA(listbox, GWL_STYLE);
+ ok((style & invalid_styles[i]) == invalid_styles[i], "%u: unexpected window styles %#x.\n", i, style);
+ ret = SendMessageA(listbox, LB_SETCOUNT, 100, 0);
+ ok(ret == LB_ERR, "%u: unexpected return value %d.\n", i, ret);
+ DestroyWindow(listbox);
+ }
+
+ DestroyWindow(parent);
+}
+
START_TEST(listbox)
{
const struct listbox_test SS =
/* {add_style} */
- {{0},
- {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
+ {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,0,0,0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
/* {selected, anchor, caret, selcount}{TODO fields} */
const struct listbox_test SS_NS =
- {{LBS_NOSEL},
- {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
+ {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,0,0,0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
const struct listbox_test MS =
- {{LBS_MULTIPLESEL},
- { 0, LB_ERR, 0, 0}, {0,0,0,0},
+ {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
{ 1, 1, 1, 1}, {0,0,0,0},
{ 2, 1, 2, 1}, {0,0,0,0},
{ 0, LB_ERR, 0, 2}, {0,0,0,0}};
const struct listbox_test MS_NS =
- {{LBS_MULTIPLESEL | LBS_NOSEL},
- {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
+ {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,0,0,0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
const struct listbox_test ES =
- {{LBS_EXTENDEDSEL},
- { 0, LB_ERR, 0, 0}, {0,0,0,0},
+ {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
{ 1, 1, 1, 1}, {0,0,0,0},
{ 2, 2, 2, 1}, {0,0,0,0},
{ 0, LB_ERR, 0, 2}, {0,0,0,0}};
const struct listbox_test ES_NS =
- {{LBS_EXTENDEDSEL | LBS_NOSEL},
- {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
+ {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,0,0,0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
const struct listbox_test EMS =
- {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
- { 0, LB_ERR, 0, 0}, {0,0,0,0},
+ {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
{ 1, 1, 1, 1}, {0,0,0,0},
{ 2, 2, 2, 1}, {0,0,0,0},
{ 0, LB_ERR, 0, 2}, {0,0,0,0}};
const struct listbox_test EMS_NS =
- {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
- {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
+ {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,0,0,0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
trace (" Testing single selection...\n");
- check (SS);
+ check (0, SS);
+ trace (" ... with NOSEL\n");
+ check (LBS_NOSEL, SS_NS);
+ trace (" ... LBS_NODATA variant ...\n");
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED, SS);
trace (" ... with NOSEL\n");
- check (SS_NS);
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_NOSEL, SS_NS);
+
trace (" Testing multiple selection...\n");
- check (MS);
+ check (LBS_MULTIPLESEL, MS);
+ trace (" ... with NOSEL\n");
+ check (LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
+ trace (" ... LBS_NODATA variant ...\n");
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL, MS);
trace (" ... with NOSEL\n");
- check (MS_NS);
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
+
trace (" Testing extended selection...\n");
- check (ES);
+ check (LBS_EXTENDEDSEL, ES);
+ trace (" ... with NOSEL\n");
+ check (LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
+ trace (" ... LBS_NODATA variant ...\n");
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL, ES);
trace (" ... with NOSEL\n");
- check (ES_NS);
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
+
trace (" Testing extended and multiple selection...\n");
- check (EMS);
+ check (LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
+ trace (" ... with NOSEL\n");
+ check (LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
+ trace (" ... LBS_NODATA variant ...\n");
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
trace (" ... with NOSEL\n");
- check (EMS_NS);
+ check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
check_item_height();
test_ownerdraw();
test_LB_SELITEMRANGE();
test_LB_SETCURSEL();
test_listbox_height();
+ test_changing_selection_styles();
test_itemfrompoint();
test_listbox_item_data();
test_listbox_LB_DIR();
test_listbox_dlgdir();
test_set_count();
+ test_init_storage();
test_GetListBoxInfo();
test_missing_lbuttonup();
test_extents();
test_WM_MEASUREITEM();
+ test_LB_SETSEL();
+ test_LBS_NODATA();
}
static ATOM atomMenuCheckClass;
-static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO);
-static BOOL (WINAPI *pGetMenuBarInfo)(HWND,LONG,LONG,PMENUBARINFO);
-static UINT (WINAPI *pSendInput)(UINT, INPUT*, size_t);
-static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO);
-
-static void init_function_pointers(void)
-{
- HMODULE hdll = GetModuleHandleA("user32");
-
-#define GET_PROC(func) \
- p ## func = (void*)GetProcAddress(hdll, #func); \
- if(!p ## func) \
- trace("GetProcAddress(%s) failed\n", #func);
-
- GET_PROC(GetMenuInfo)
- GET_PROC(GetMenuBarInfo)
- GET_PROC(SendInput)
- GET_PROC(SetMenuInfo)
-
-#undef GET_PROC
-}
-
-static BOOL correct_behavior(void)
-{
- HMENU hmenu;
- MENUITEMINFOA info;
- BOOL rc;
-
- hmenu = CreateMenu();
-
- memset(&info, 0, sizeof(MENUITEMINFOA));
- info.cbSize= sizeof(MENUITEMINFOA);
- SetLastError(0xdeadbeef);
- rc = GetMenuItemInfoA(hmenu, 0, TRUE, &info);
- /* Win9x : 0xdeadbeef
- * NT4 : ERROR_INVALID_PARAMETER
- * >= W2K : ERROR_MENU_ITEM_NOT_FOUND
- */
- if (!rc && GetLastError() != ERROR_MENU_ITEM_NOT_FOUND)
- {
- win_skip("NT4 and below can't handle a bigger MENUITEMINFO struct\n");
- DestroyMenu(hmenu);
- return FALSE;
- }
-
- DestroyMenu(hmenu);
- return TRUE;
-}
-
static LRESULT WINAPI menu_check_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
HWND hwnd;
INT err;
- if (!pGetMenuBarInfo) {
- win_skip("GetMenuBarInfo is not available\n");
- return;
- }
-
mbi.cbSize = sizeof(MENUBARINFO);
hwnd = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atomMenuCheckClass), NULL,
/* no menu: getmenubarinfo should fail */
SetLastError(0xdeadbeef);
- ret = pGetMenuBarInfo(hwnd, OBJID_MENU, 0, &mbi);
+ ret = GetMenuBarInfo(hwnd, OBJID_MENU, 0, &mbi);
err = GetLastError();
ok(ret == FALSE, "GetMenuBarInfo should not have been successful\n");
ok(err == 0xdeadbeef, "err = %d\n", err);
ok(ret, "SetMenu failed with error %d\n", GetLastError());
SetLastError(0xdeadbeef);
- ret = pGetMenuBarInfo(NULL, OBJID_CLIENT, 0, &mbi);
+ ret = GetMenuBarInfo(NULL, OBJID_CLIENT, 0, &mbi);
err = GetLastError();
ok(!ret, "GetMenuBarInfo succeeded\n");
ok(err == ERROR_INVALID_WINDOW_HANDLE, "err = %d\n", err);
SetLastError(0xdeadbeef);
- ret = pGetMenuBarInfo(hwnd, OBJID_CLIENT, 0, &mbi);
+ ret = GetMenuBarInfo(hwnd, OBJID_CLIENT, 0, &mbi);
err = GetLastError();
ok(!ret, "GetMenuBarInfo succeeded\n");
ok(err==ERROR_INVALID_MENU_HANDLE || broken(err==0xdeadbeef) /* NT, W2K, XP */, "err = %d\n", err);
SetLastError(0xdeadbeef);
- ret = pGetMenuBarInfo(hwnd, OBJID_MENU, -1, &mbi);
+ ret = GetMenuBarInfo(hwnd, OBJID_MENU, -1, &mbi);
err = GetLastError();
ok(ret == FALSE, "GetMenuBarInfo should have failed\n");
ok(err == 0xdeadbeef, "err = %d\n", err);
mbi.cbSize = 1000;
SetLastError(0xdeadbeef);
- ret = pGetMenuBarInfo(hwnd, OBJID_MENU, 0, &mbi);
+ ret = GetMenuBarInfo(hwnd, OBJID_MENU, 0, &mbi);
err = GetLastError();
ok(ret == FALSE, "GetMenuBarInfo should have failed\n");
ok(err == ERROR_INVALID_PARAMETER, "err = %d\n", err);
mbi.cbSize = sizeof(MENUBARINFO);
SetLastError(0xdeadbeef);
- ret = pGetMenuBarInfo(hwnd, 123, 0, &mbi);
+ ret = GetMenuBarInfo(hwnd, 123, 0, &mbi);
err = GetLastError();
ok(ret == FALSE, "GetMenuBarInfo should have failed\n");
ok(err == 0xdeadbeef, "err = %d\n", err);
- ret = pGetMenuBarInfo(hwnd, OBJID_MENU, 0, &mbi);
+ ret = GetMenuBarInfo(hwnd, OBJID_MENU, 0, &mbi);
ok(ret, "GetMenuBarInfo failed with error %d\n", GetLastError());
ok(mbi.rcBar.left == 0 && mbi.rcBar.top == 0 && mbi.rcBar.bottom == 0 && mbi.rcBar.right == 0,
ok(ret, "SetMenu failed with error %d\n", GetLastError());
SetLastError(0xdeadbeef);
- ret = pGetMenuBarInfo(hwnd, OBJID_MENU, 200, &mbi);
+ ret = GetMenuBarInfo(hwnd, OBJID_MENU, 200, &mbi);
err = GetLastError();
ok(ret == FALSE, "GetMenuBarInfo should have failed\n");
ok(err == 0xdeadbeef, "err = %d\n", err);
/* get info for the whole menu */
- ret = pGetMenuBarInfo(hwnd, OBJID_MENU, 0, &mbi);
+ ret = GetMenuBarInfo(hwnd, OBJID_MENU, 0, &mbi);
ok(ret, "GetMenuBarInfo failed with error %d\n", GetLastError());
/* calculate menu rectangle, from window rectangle and the position of the first item */
ok(mbi.fFocused == 0, "fFocused: got %d instead of 0\n", mbi.fFocused);
/* get info for item nr.2 */
- ret = pGetMenuBarInfo(hwnd, OBJID_MENU, 2, &mbi);
+ ret = GetMenuBarInfo(hwnd, OBJID_MENU, 2, &mbi);
ok(ret, "GetMenuBarInfo failed with error %d\n", GetLastError());
ret = GetMenuItemRect(hwnd, hmenu, 1, &rci);
ok(ret, "GetMenuItemRect failed.\n");
DestroyWindow(hwnd);
}
+static void test_GetMenuItemRect(void)
+{
+ HWND hwnd;
+ HMENU hmenu;
+ HMENU popup_hmenu;
+ RECT window_rect;
+ RECT item_rect;
+ POINT client_top_left;
+ INT caption_height;
+ BOOL ret;
+
+ hwnd = CreateWindowW((LPCWSTR)MAKEINTATOM(atomMenuCheckClass), NULL, WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL,
+ NULL, NULL, NULL);
+ ok(hwnd != NULL, "CreateWindow failed with error %d\n", GetLastError());
+ hmenu = CreateMenu();
+ ok(hmenu != NULL, "CreateMenu failed with error %d\n", GetLastError());
+ popup_hmenu = CreatePopupMenu();
+ ok(popup_hmenu != NULL, "CreatePopupMenu failed with error %d\n", GetLastError());
+ ret = AppendMenuA(popup_hmenu, MF_STRING, 0, "Popup");
+ ok(ret, "AppendMenu failed with error %d\n", GetLastError());
+ ret = AppendMenuA(hmenu, MF_STRING | MF_POPUP, (UINT_PTR)popup_hmenu, "Menu");
+ ok(ret, "AppendMenu failed with error %d\n", GetLastError());
+ ret = SetMenu(hwnd, hmenu);
+ ok(ret, "SetMenu failed with error %d\n", GetLastError());
+
+ /* Get the menu item rectangle of the displayed sysmenu item */
+ ret = GetMenuItemRect(hwnd, hmenu, 0, &item_rect);
+ ok(ret, "GetMenuItemRect failed with error %d\n", GetLastError());
+ GetWindowRect(hwnd, &window_rect);
+ /* Get the screen coordinate of the left top corner of the client rectangle */
+ client_top_left.x = 0;
+ client_top_left.y = 0;
+ MapWindowPoints(hwnd, 0, &client_top_left, 1);
+ caption_height = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
+
+ ok(item_rect.left == client_top_left.x, "Expect item_rect.left %d == %d\n", item_rect.left, client_top_left.x);
+ ok(item_rect.right <= window_rect.right, "Expect item_rect.right %d <= %d\n", item_rect.right, window_rect.right);
+ /* A gap of 1 pixel is added deliberately in commit 75f9e64, so using equal operator would fail on Wine.
+ * Check that top and bottom are correct with 1 pixel margin tolerance */
+ ok(item_rect.top - (window_rect.top + caption_height) <= 1, "Expect item_rect.top %d - %d <= 1\n", item_rect.top,
+ window_rect.top + caption_height);
+ ok(item_rect.bottom - (client_top_left.y - 1) <= 1, "Expect item_rect.bottom %d - %d <= 1\n", item_rect.bottom,
+ client_top_left.y - 1);
+
+ /* Get the item rectangle of the not yet displayed popup menu item. */
+ ret = GetMenuItemRect(hwnd, popup_hmenu, 0, &item_rect);
+ ok(ret, "GetMenuItemRect failed with error %d\n", GetLastError());
+ ok(item_rect.left == client_top_left.x, "Expect item_rect.left %d == %d\n", item_rect.left, client_top_left.x);
+ ok(item_rect.right == client_top_left.x, "Expect item_rect.right %d == %d\n", item_rect.right, client_top_left.x);
+ ok(item_rect.top == client_top_left.y, "Expect item_rect.top %d == %d\n", item_rect.top, client_top_left.y);
+ ok(item_rect.bottom == client_top_left.y, "Expect item_rect.bottom %d == %d\n", item_rect.bottom,
+ client_top_left.y);
+
+ DestroyWindow(hwnd);
+}
+
static void test_system_menu(void)
{
WCHAR testW[] = {'t','e','s','t',0};
static void test_subpopup_locked_by_menu(void)
{
- DWORD gle;
BOOL ret;
HMENU hmenu, hsubmenu;
MENUINFO mi = { sizeof( MENUINFO)};
MENUITEMINFOA mii = { sizeof( MENUITEMINFOA)};
HWND hwnd;
const int itemid = 0x1234567;
- if( !pGetMenuInfo)
- {
- win_skip("GetMenuInfo is not available\n");
- return;
- }
+
/* create window, popupmenu with one subpopup */
hwnd = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atomMenuCheckClass), NULL,
WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 200, 200,
ok( ret, "GetMenuItemInfo failed error %d\n", GetLastError());
ok( mii.hSubMenu == hsubmenu, "submenu is %p\n", mii.hSubMenu);
mi.fMask |= MIM_STYLE;
- ret = pGetMenuInfo( hsubmenu, &mi);
+ ret = GetMenuInfo( hsubmenu, &mi);
ok( ret , "GetMenuInfo returned 0 with error %d\n", GetLastError());
ret = IsMenu( hsubmenu);
ok( ret , "Menu handle is not valid\n");
- SetLastError( 0xdeadbeef);
+
ret = TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL);
- if( ret == (itemid & 0xffff)) {
- win_skip("not on 16 bit menu subsystem\n");
- DestroyMenu( hsubmenu);
- } else {
- gle = GetLastError();
- ok( ret == itemid , "TrackPopupMenu returned %d error is %d\n", ret, gle);
- ok( gle == 0 ||
- broken( gle == 0xdeadbeef), /* win2k0 */
- "Last error is %d\n", gle);
- /* then destroy the sub-popup */
- ret = DestroyMenu( hsubmenu);
- ok(ret, "DestroyMenu failed with error %d\n", GetLastError());
- /* and repeat the tests */
- mii.fMask = MIIM_SUBMENU;
- ret = GetMenuItemInfoA( hmenu, 0, TRUE, &mii);
- ok( ret, "GetMenuItemInfo failed error %d\n", GetLastError());
- /* GetMenuInfo fails now */
- ok( mii.hSubMenu == hsubmenu, "submenu is %p\n", mii.hSubMenu);
- mi.fMask |= MIM_STYLE;
- ret = pGetMenuInfo( hsubmenu, &mi);
- ok( !ret , "GetMenuInfo should have failed\n");
- /* IsMenu says it is not */
- ret = IsMenu( hsubmenu);
- ok( !ret , "Menu handle should be invalid\n");
- /* but TrackPopupMenu still works! */
- SetLastError( 0xdeadbeef);
- ret = TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL);
- gle = GetLastError();
- todo_wine {
- ok( ret == itemid , "TrackPopupMenu returned %d error is %d\n", ret, gle);
- }
- ok( gle == 0 ||
- broken(gle == 0xdeadbeef) || /* wow64 */
- broken(gle == ERROR_INVALID_PARAMETER), /* win2k0 */
- "Last error is %d\n", gle);
+ ok( ret == itemid , "TrackPopupMenu returned %d error is %d\n", ret, GetLastError());
+
+ /* then destroy the sub-popup */
+ ret = DestroyMenu( hsubmenu);
+ ok(ret, "DestroyMenu failed with error %d\n", GetLastError());
+ /* and repeat the tests */
+ mii.fMask = MIIM_SUBMENU;
+ ret = GetMenuItemInfoA( hmenu, 0, TRUE, &mii);
+ ok( ret, "GetMenuItemInfo failed error %d\n", GetLastError());
+ /* GetMenuInfo fails now */
+ ok( mii.hSubMenu == hsubmenu, "submenu is %p\n", mii.hSubMenu);
+ mi.fMask |= MIM_STYLE;
+ ret = GetMenuInfo( hsubmenu, &mi);
+ ok( !ret , "GetMenuInfo should have failed\n");
+ /* IsMenu says it is not */
+ ret = IsMenu( hsubmenu);
+ ok( !ret , "Menu handle should be invalid\n");
+
+ /* but TrackPopupMenu still works! */
+ ret = TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL);
+ todo_wine {
+ ok( ret == itemid , "TrackPopupMenu returned %d error is %d\n", ret, GetLastError());
}
+
/* clean up */
DestroyMenu( hmenu);
DestroyWindow(hwnd);
ok( ret, "AppendMenu failed for %d\n", k-1);
}
MOD_maxid = k-1;
- assert( k <= sizeof(MOD_rc)/sizeof(RECT));
+ assert( k <= ARRAY_SIZE(MOD_rc));
/* display the menu */
TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL);
if( mnuopt) {
mi.cbSize = sizeof(mi);
mi.fMask = MIM_STYLE;
- pGetMenuInfo( hmenu, &mi);
+ GetMenuInfo( hmenu, &mi);
if( mnuopt) mi.dwStyle |= mnuopt == 1 ? MNS_NOCHECK : MNS_CHECKORBMP;
- ret = pSetMenuInfo( hmenu, &mi);
+ ret = SetMenuInfo( hmenu, &mi);
ok( ret, "SetMenuInfo failed with error %d\n", GetLastError());
}
ret = InsertMenuItemA( hmenu, 0, FALSE, &mii);
int count, szidx, txtidx, bmpidx, hassub, mnuopt, ispop;
BOOL got;
- if( !pGetMenuInfo)
- {
- win_skip("GetMenuInfo is not available\n");
- return;
- }
-
memset( bmfill, 0xcc, sizeof( bmfill));
hwnd = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atomMenuCheckClass), NULL, WS_SYSMENU |
WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 200, 200,
ok( hsysmenu != NULL, "GetSystemMenu failed with error %d\n", GetLastError());
mi.fMask = MIM_STYLE;
mi.dwStyle = 0;
- got = pGetMenuInfo( hsysmenu, &mi);
+ got = GetMenuInfo( hsysmenu, &mi);
ok( got, "GetMenuInfo failed gle=%d\n", GetLastError());
ok( MNS_CHECKORBMP == mi.dwStyle, "System Menu Style is %08x, without the bit %08x\n",
mi.dwStyle, MNS_CHECKORBMP);
for( ispop=1; ispop >= 0; ispop--){
static SIZE bmsizes[]= {
{10,10},{38,38},{1,30},{55,5}};
- for( szidx=0; szidx < sizeof( bmsizes) / sizeof( SIZE); szidx++) {
+ for( szidx=0; szidx < ARRAY_SIZE(bmsizes); szidx++) {
HBITMAP hbm = CreateBitmap( bmsizes[szidx].cx, bmsizes[szidx].cy,1,1,bmfill);
HBITMAP bitmaps[] = { HBMMENU_CALLBACK, hbm, HBMMENU_POPUP_CLOSE, NULL };
ok( hbm != 0, "CreateBitmap failed err %d\n", GetLastError());
- for( txtidx = 0; txtidx < sizeof(MOD_txtsizes)/sizeof(MOD_txtsizes[0]); txtidx++) {
+ for( txtidx = 0; txtidx < ARRAY_SIZE(MOD_txtsizes); txtidx++) {
for( hassub = 0; hassub < 2 ; hassub++) { /* add submenu item */
for( mnuopt = 0; mnuopt < 3 ; mnuopt++){ /* test MNS_NOCHECK/MNS_CHECKORBMP */
- for( bmpidx = 0; bmpidx <sizeof(bitmaps)/sizeof(HBITMAP); bmpidx++) {
+ for( bmpidx = 0; bmpidx <ARRAY_SIZE(bitmaps); bmpidx++) {
/* no need to test NULL bitmaps of several sizes */
if( !bitmaps[bmpidx] && szidx > 0) continue;
/* the HBMMENU_POPUP not to test for menu bars */
ok (GetMenuStringA( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
ok (!strcmp( strback, "Dummy string" ), "Menu text from Ansi version incorrect\n");
- SetLastError(0xdeadbeef);
ret = GetMenuStringW( hmenu, 0, strbackW, 99, MF_BYPOSITION );
- if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
- win_skip("GetMenuStringW is not implemented\n");
- else
- {
- ok (ret, "GetMenuStringW on ownerdraw entry failed\n");
- ok (!lstrcmpW( strbackW, expectedString ), "Menu text from Unicode version incorrect\n");
- }
+ ok (ret, "GetMenuStringW on ownerdraw entry failed\n");
+ ok (!lstrcmpW( strbackW, expectedString ), "Menu text from Unicode version incorrect\n");
/* Just try some invalid parameter tests */
SetLastError(0xdeadbeef);
ok (rc, "InsertMenuItem failed\n");
ok (!GetMenuStringA( hmenu, 0, NULL, 0, MF_BYPOSITION),
"GetMenuString on ownerdraw entry succeeded.\n");
- SetLastError(0xdeadbeef);
ret = GetMenuStringW( hmenu, 0, NULL, 0, MF_BYPOSITION);
- if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
- win_skip("GetMenuStringW is not implemented\n");
- else
- ok (!ret, "GetMenuStringW on ownerdraw entry succeeded.\n");
+ ok (!ret, "GetMenuStringW on ownerdraw entry succeeded.\n");
DestroyMenu( hmenu );
}
Only the low word of the dwTypeData is used.
Use a magic bitmap here (Word 95 uses this to create its MDI menu buttons) */
TMII_INSMI( MIIM_TYPE, MFT_BITMAP | MFT_RIGHTJUSTIFY, -1, -1, 0, 0, 0, -1,
- (HMENU)MAKELONG(HBMMENU_MBAR_CLOSE, 0x1234), -1, 0, OK );
+ (HMENU)MAKELPARAM(HBMMENU_MBAR_CLOSE, 0x1234), -1, 0, OK );
TMII_GMII ( MIIM_TYPE, 80,
MFT_BITMAP | MFT_RIGHTJUSTIFY, 0, 0, 0, 0, 0, 0, HBMMENU_MBAR_CLOSE, 0, HBMMENU_MBAR_CLOSE,
NULL, OK, OK );
Only the low word of the dwTypeData is used.
Use a magic bitmap here (Word 95 uses this to create its MDI menu buttons) */
TMII_INSMI( MIIM_TYPE, MFT_BITMAP | MFT_RIGHTJUSTIFY, -1, -1, 0, 0, 0, -1,
- (HMENU)MAKELONG(HBMMENU_MBAR_CLOSE, 0x1234), -1, 0, OK );
+ (HMENU)MAKELPARAM(HBMMENU_MBAR_CLOSE, 0x1234), -1, 0, OK );
TMII_GMII ( MIIM_TYPE, 80,
MFT_BITMAP | MFT_RIGHTJUSTIFY, 0, 0, 0, 0, 0, 0, HBMMENU_MBAR_CLOSE, 0, HBMMENU_MBAR_CLOSE,
NULL, OK, OK );
{ INPUT_KEYBOARD, {{0}}, {VK_F10, 0}, TRUE, FALSE },
{ INPUT_KEYBOARD, {{0}}, {VK_F10, 0}, FALSE, FALSE },
- { INPUT_MOUSE, {{1, 2}, {0}}, {0}, TRUE, TRUE }, /* test 20 */
+ { INPUT_MOUSE, {{1, 2}, {0}}, {0}, TRUE, FALSE }, /* test 20 */
{ INPUT_MOUSE, {{1, 1}, {0}}, {0}, FALSE, FALSE },
- { INPUT_MOUSE, {{1, 0}, {0}}, {0}, TRUE, TRUE },
+ { INPUT_MOUSE, {{1, 0}, {0}}, {0}, TRUE, FALSE },
{ INPUT_MOUSE, {{1, 1}, {0}}, {0}, FALSE, FALSE },
- { INPUT_MOUSE, {{1, 0}, {2, 2}, {0}}, {0}, TRUE, TRUE },
+ { INPUT_MOUSE, {{1, 0}, {2, 2}, {0}}, {0}, TRUE, FALSE },
{ INPUT_MOUSE, {{2, 1}, {0}}, {0}, FALSE, FALSE },
- { INPUT_MOUSE, {{1, 0}, {2, 0}, {0}}, {0}, TRUE, TRUE },
+ { INPUT_MOUSE, {{1, 0}, {2, 0}, {0}}, {0}, TRUE, FALSE },
{ INPUT_MOUSE, {{3, 0}, {0}}, {0}, FALSE, FALSE },
- { INPUT_MOUSE, {{1, 0}, {2, 0}, {0}}, {0}, TRUE, TRUE },
- { INPUT_MOUSE, {{3, 1}, {0}}, {0}, TRUE, TRUE },
+ { INPUT_MOUSE, {{1, 0}, {2, 0}, {0}}, {0}, TRUE, FALSE },
+ { INPUT_MOUSE, {{3, 1}, {0}}, {0}, TRUE, FALSE },
{ INPUT_MOUSE, {{1, 1}, {0}}, {0}, FALSE, FALSE },
{ -1 }
};
i[0].type = i[1].type = INPUT_KEYBOARD;
i[0].u.ki.wVk = i[1].u.ki.wVk = wVk;
i[1].u.ki.dwFlags = KEYEVENTF_KEYUP;
- pSendInput(2, (INPUT *) i, sizeof(INPUT));
+ SendInput(2, (INPUT *) i, sizeof(INPUT));
}
static BOOL click_menu(HANDLE hWnd, struct menu_item_pair_s *mi)
i[0].u.mi.dwFlags |= MOUSEEVENTF_MOVE;
i[1].u.mi.dwFlags |= MOUSEEVENTF_LEFTDOWN;
i[2].u.mi.dwFlags |= MOUSEEVENTF_LEFTUP;
- ret = pSendInput(3, (INPUT *) i, sizeof(INPUT));
+ ret = SendInput(3, (INPUT *) i, sizeof(INPUT));
/* hack to prevent mouse message buildup in Wine */
while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
for (i = 0; menu_tests[i].type != -1; i++)
{
BOOL ret = TRUE;
- int elapsed = 0;
+ int elapsed;
got_input = i && menu_tests[i-1].bMenuVisible;
send_key(menu_tests[i].wVk[j]);
else
for (j = 0; menu_tests[i].menu_item_pairs[j].uMenu != 0; j++)
- if (!(ret = click_menu(hWnd, &menu_tests[i].menu_item_pairs[j]))) break;
+ {
+ /* Maybe clicking too fast before menu is initialized. Sleep 100 ms and retry */
+ elapsed = 0;
+ while (!(ret = click_menu(hWnd, &menu_tests[i].menu_item_pairs[j])))
+ {
+ if (elapsed > 1000) break;
+ elapsed += 100;
+ Sleep(100);
+ }
+ }
if (!ret)
{
PostMessageA( hWnd, WM_CANCELMODE, 0, 0 );
return 0;
}
+
+ elapsed = 0;
while (menu_tests[i].bMenuVisible != bMenuVisible)
{
if (elapsed > 200)
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam)
{
+ MENUBARINFO mbi;
+ HMENU hmenu;
+ UINT state;
+ BOOL br;
+
switch (msg) {
case WM_ENTERMENULOOP:
bMenuVisible = TRUE;
return( DefWindowProcA( hWnd, msg, wParam, lParam ) );
}
- if(pGetMenuBarInfo)
- {
- MENUBARINFO mbi;
- HMENU hmenu;
- UINT state;
- BOOL br;
-
- mbi.cbSize = sizeof(MENUBARINFO);
-
- /* get info for the menu */
- br = pGetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi);
- ok(br, "msg %x: GetMenuBarInfo failed\n", msg);
- hmenu = GetMenu(hWnd);
- ok(!mbi.hwndMenu, "msg %x: GetMenuBarInfo.hwndMenu wrong: %p expected NULL\n",
- msg, mbi.hwndMenu);
- ok(mbi.hMenu == hmenu, "msg %x: GetMenuBarInfo got wrong menu: %p expected %p\n",
- msg, mbi.hMenu, hmenu);
- ok(!bMenuVisible == !mbi.fBarFocused, "msg %x: GetMenuBarInfo.fBarFocused (%d) is wrong\n",
- msg, mbi.fBarFocused != 0);
- ok(!bMenuVisible == !mbi.fFocused, "msg %x: GetMenuBarInfo.fFocused (%d) is wrong\n",
- msg, mbi.fFocused != 0);
-
- /* get info for the menu's first item */
- br = pGetMenuBarInfo(hWnd, OBJID_MENU, 1, &mbi);
- ok(br, "msg %x: GetMenuBarInfo failed\n", msg);
- state = GetMenuState(hmenu, 0, MF_BYPOSITION);
- if (pGetMenuInfo) /* Skip on NT */
- {
- /* Native returns handle to destroyed window */
- todo_wine_if (msg==WM_UNINITMENUPOPUP && popmenu==1)
- ok(!mbi.hwndMenu == !popmenu,
- "msg %x: GetMenuBarInfo.hwndMenu wrong: %p expected %sNULL\n",
- msg, mbi.hwndMenu, popmenu ? "not " : "");
- }
- ok(mbi.hMenu == hmenu, "msg %x: GetMenuBarInfo got wrong menu: %p expected %p\n",
- msg, mbi.hMenu, hmenu);
- ok(!bMenuVisible == !mbi.fBarFocused, "nsg %x: GetMenuBarInfo.fBarFocused (%d) is wrong\n",
- msg, mbi.fBarFocused != 0);
- ok(!(bMenuVisible && (state & MF_HILITE)) == !mbi.fFocused,
- "msg %x: GetMenuBarInfo.fFocused (%d) is wrong\n", msg, mbi.fFocused != 0);
- }
+ mbi.cbSize = sizeof(MENUBARINFO);
+
+ /* get info for the menu */
+ br = GetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi);
+ ok(br, "msg %x: GetMenuBarInfo failed\n", msg);
+ hmenu = GetMenu(hWnd);
+ ok(!mbi.hwndMenu, "msg %x: GetMenuBarInfo.hwndMenu wrong: %p expected NULL\n",
+ msg, mbi.hwndMenu);
+ ok(mbi.hMenu == hmenu, "msg %x: GetMenuBarInfo got wrong menu: %p expected %p\n",
+ msg, mbi.hMenu, hmenu);
+ ok(!bMenuVisible == !mbi.fBarFocused, "msg %x: GetMenuBarInfo.fBarFocused (%d) is wrong\n",
+ msg, mbi.fBarFocused != 0);
+ ok(!bMenuVisible == !mbi.fFocused, "msg %x: GetMenuBarInfo.fFocused (%d) is wrong\n",
+ msg, mbi.fFocused != 0);
+
+ /* get info for the menu's first item */
+ br = GetMenuBarInfo(hWnd, OBJID_MENU, 1, &mbi);
+ ok(br, "msg %x: GetMenuBarInfo failed\n", msg);
+ state = GetMenuState(hmenu, 0, MF_BYPOSITION);
+ /* Native returns handle to destroyed window */
+ todo_wine_if (msg==WM_UNINITMENUPOPUP && popmenu==1)
+ ok(!mbi.hwndMenu == !popmenu,
+ "msg %x: GetMenuBarInfo.hwndMenu wrong: %p expected %sNULL\n",
+ msg, mbi.hwndMenu, popmenu ? "not " : "");
+ ok(mbi.hMenu == hmenu, "msg %x: GetMenuBarInfo got wrong menu: %p expected %p\n",
+ msg, mbi.hMenu, hmenu);
+ ok(!bMenuVisible == !mbi.fBarFocused, "nsg %x: GetMenuBarInfo.fBarFocused (%d) is wrong\n",
+ msg, mbi.fBarFocused != 0);
+ ok(!(bMenuVisible && (state & MF_HILITE)) == !mbi.fFocused,
+ "msg %x: GetMenuBarInfo.fFocused (%d) is wrong\n", msg, mbi.fFocused != 0);
if (msg == WM_EXITMENULOOP)
bMenuVisible = FALSE;
ATOM aclass;
POINT orig_pos;
- if (!pSendInput)
- {
- win_skip("SendInput is not available\n");
- return;
- }
-
wclass.lpszClassName = "MenuTestClass";
wclass.style = CS_HREDRAW | CS_VREDRAW;
wclass.lpfnWndProc = WndProc;
ok(ret, "AppendMenu failed\n");
count = GetMenuItemCount(hmenu);
- ok(count == sizeof(menu_data)/sizeof(menu_data[0]),
- "expected %u menu items, got %u\n",
- (UINT)(sizeof(menu_data)/sizeof(menu_data[0])), count);
+ ok(count == ARRAY_SIZE(menu_data), "expected %u menu items, got %u\n",
+ (UINT) ARRAY_SIZE(menu_data), count);
for (i = 0; i < count; i++)
{
};
HMENU hmenu;
-#define create_menu(a) create_menu_from_data((a), sizeof(a)/sizeof((a)[0]))
-#define create_menuitem(a) create_menuitem_from_data((a), sizeof(a)/sizeof((a)[0]))
-#define compare_menu(h, a) compare_menu_data((h), (a), sizeof(a)/sizeof((a)[0]))
+#define create_menu(a) create_menu_from_data((a), ARRAY_SIZE(a))
+#define create_menuitem(a) create_menuitem_from_data((a), ARRAY_SIZE(a))
+#define compare_menu(h, a) compare_menu_data((h), (a), ARRAY_SIZE(a))
hmenu = create_menu(in1);
compare_menu(hmenu, out1);
BOOL ret;
DWORD gle;
- if (!pGetMenuInfo)
- {
- win_skip("GetMenuInfo is not available\n");
- return;
- }
-
/* create a menu */
hmenu = CreateMenu();
assert( hmenu);
/* test some parameter errors */
SetLastError(0xdeadbeef);
- ret = pGetMenuInfo( hmenu, NULL);
+ ret = GetMenuInfo( hmenu, NULL);
gle= GetLastError();
ok( !ret, "GetMenuInfo() should have failed\n");
ok( gle == ERROR_INVALID_PARAMETER ||
"GetMenuInfo() error got %u expected %u\n", gle, ERROR_INVALID_PARAMETER);
SetLastError(0xdeadbeef);
mi.cbSize = 0;
- ret = pGetMenuInfo( hmenu, &mi);
+ ret = GetMenuInfo( hmenu, &mi);
gle= GetLastError();
ok( !ret, "GetMenuInfo() should have failed\n");
ok( gle == ERROR_INVALID_PARAMETER ||
"GetMenuInfo() error got %u expected %u\n", gle, ERROR_INVALID_PARAMETER);
SetLastError(0xdeadbeef);
mi.cbSize = sizeof( MENUINFO);
- ret = pGetMenuInfo( hmenu, &mi);
+ ret = GetMenuInfo( hmenu, &mi);
gle= GetLastError();
ok( ret, "GetMenuInfo() should have succeeded\n");
ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
SetLastError(0xdeadbeef);
mi.cbSize = 0;
- ret = pGetMenuInfo( NULL, &mi);
+ ret = GetMenuInfo( NULL, &mi);
gle= GetLastError();
ok( !ret, "GetMenuInfo() should have failed\n");
ok( gle == ERROR_INVALID_PARAMETER ||
DWORD gle;
HBRUSH brush;
- if (!pGetMenuInfo || !pSetMenuInfo)
- {
- win_skip("Get/SetMenuInfo are not available\n");
- return;
- }
-
/* create a menu with a submenu */
hmenu = CreateMenu();
hsubmenu = CreateMenu();
ok( ret, "InsertMenuItem failed with error %d\n", GetLastError());
/* test some parameter errors */
SetLastError(0xdeadbeef);
- ret = pSetMenuInfo( hmenu, NULL);
+ ret = SetMenuInfo( hmenu, NULL);
gle= GetLastError();
ok( !ret, "SetMenuInfo() should have failed\n");
ok( gle == ERROR_INVALID_PARAMETER ||
"SetMenuInfo() error got %u expected %u\n", gle, ERROR_INVALID_PARAMETER);
SetLastError(0xdeadbeef);
mi.cbSize = 0;
- ret = pSetMenuInfo( hmenu, &mi);
+ ret = SetMenuInfo( hmenu, &mi);
gle= GetLastError();
ok( !ret, "SetMenuInfo() should have failed\n");
ok( gle == ERROR_INVALID_PARAMETER ||
"SetMenuInfo() error got %u expected %u\n", gle, ERROR_INVALID_PARAMETER);
SetLastError(0xdeadbeef);
mi.cbSize = sizeof( MENUINFO);
- ret = pSetMenuInfo( hmenu, &mi);
+ ret = SetMenuInfo( hmenu, &mi);
gle= GetLastError();
ok( ret, "SetMenuInfo() should have succeeded\n");
ok( gle == 0xdeadbeef, "SetMenuInfo() error got %u\n", gle);
SetLastError(0xdeadbeef);
mi.cbSize = 0;
- ret = pSetMenuInfo( NULL, &mi);
+ ret = SetMenuInfo( NULL, &mi);
gle= GetLastError();
ok( !ret, "SetMenuInfo() should have failed\n");
ok( gle == ERROR_INVALID_PARAMETER ||
SetLastError(0xdeadbeef);
mi.cbSize = sizeof( MENUINFO);
mi.fMask = MIM_STYLE;
- ret = pGetMenuInfo( hmenu, &mi);
+ ret = GetMenuInfo( hmenu, &mi);
gle= GetLastError();
ok( ret, "GetMenuInfo() should have succeeded\n");
ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
SetLastError(0xdeadbeef);
mi.cbSize = sizeof( MENUINFO);
mi.fMask = MIM_STYLE;
- ret = pGetMenuInfo( hsubmenu, &mi);
+ ret = GetMenuInfo( hsubmenu, &mi);
gle= GetLastError();
ok( ret, "GetMenuInfo() should have succeeded\n");
ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
mi.cbSize = sizeof( MENUINFO);
mi.fMask = MIM_STYLE | MIM_APPLYTOSUBMENUS;
mi.dwStyle = MNS_CHECKORBMP;
- ret = pSetMenuInfo( hmenu, &mi);
+ ret = SetMenuInfo( hmenu, &mi);
gle= GetLastError();
ok( ret, "SetMenuInfo() should have succeeded\n");
ok( gle == 0xdeadbeef, "SetMenuInfo() error got %u\n", gle);
SetLastError(0xdeadbeef);
mi.cbSize = sizeof( MENUINFO);
mi.fMask = MIM_STYLE;
- ret = pGetMenuInfo( hmenu, &mi);
+ ret = GetMenuInfo( hmenu, &mi);
gle= GetLastError();
ok( ret, "GetMenuInfo() should have succeeded\n");
ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
SetLastError(0xdeadbeef);
mi.cbSize = sizeof( MENUINFO);
mi.fMask = MIM_STYLE;
- ret = pGetMenuInfo( hsubmenu, &mi);
+ ret = GetMenuInfo( hsubmenu, &mi);
gle= GetLastError();
ok( ret, "GetMenuInfo() should have succeeded\n");
ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
mi.cbSize = sizeof( MENUINFO);
mi.fMask = MIM_STYLE ;
mi.dwStyle = MNS_NOCHECK;
- ret = pSetMenuInfo( hmenu, &mi);
+ ret = SetMenuInfo( hmenu, &mi);
gle= GetLastError();
ok( ret, "SetMenuInfo() should have succeeded\n");
ok( gle == 0xdeadbeef, "SetMenuInfo() error got %u\n", gle);
SetLastError(0xdeadbeef);
mi.cbSize = sizeof( MENUINFO);
mi.fMask = MIM_STYLE;
- ret = pGetMenuInfo( hmenu, &mi);
+ ret = GetMenuInfo( hmenu, &mi);
gle= GetLastError();
ok( ret, "GetMenuInfo() should have succeeded\n");
ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
SetLastError(0xdeadbeef);
mi.cbSize = sizeof( MENUINFO);
mi.fMask = MIM_STYLE;
- ret = pGetMenuInfo( hsubmenu, &mi);
+ ret = GetMenuInfo( hsubmenu, &mi);
gle= GetLastError();
ok( ret, "GetMenuInfo() should have succeeded\n");
ok( gle == 0xdeadbeef, "GetMenuInfo() error got %u\n", gle);
/* test background brush */
mi.cbSize = sizeof(mi);
mi.fMask = MIM_BACKGROUND;
- ret = pGetMenuInfo( hmenu, &mi );
+ ret = GetMenuInfo( hmenu, &mi );
ok( ret, "GetMenuInfo() should have succeeded\n" );
ok( mi.hbrBack == NULL, "got %p\n", mi.hbrBack );
brush = CreateSolidBrush( RGB(0xff, 0, 0) );
mi.hbrBack = brush;
- ret = pSetMenuInfo( hmenu, &mi );
+ ret = SetMenuInfo( hmenu, &mi );
ok( ret, "SetMenuInfo() should have succeeded\n" );
mi.hbrBack = NULL;
- ret = pGetMenuInfo( hmenu, &mi );
+ ret = GetMenuInfo( hmenu, &mi );
ok( ret, "GetMenuInfo() should have succeeded\n" );
ok( mi.hbrBack == brush, "got %p original %p\n", mi.hbrBack, brush );
mi.hbrBack = NULL;
- ret = pSetMenuInfo( hmenu, &mi );
+ ret = SetMenuInfo( hmenu, &mi );
ok( ret, "SetMenuInfo() should have succeeded\n" );
- ret = pGetMenuInfo( hmenu, &mi );
+ ret = GetMenuInfo( hmenu, &mi );
ok( ret, "GetMenuInfo() should have succeeded\n" );
ok( mi.hbrBack == NULL, "got %p\n", mi.hbrBack );
DeleteObject( brush );
ok( hbm1 && hbm2 && hbm3, "Creating bitmaps failed\n");
menu = CreatePopupMenu();
ok( menu != NULL, "CreatePopupMenu() failed\n");
- if( pGetMenuInfo) {
- mi.fMask = MIM_STYLE;
- ret = pGetMenuInfo( menu, &mi);
- ok( ret, "GetMenuInfo failed: %d\n", GetLastError());
- ok( menu != NULL, "GetMenuInfo() failed\n");
- ok( 0 == mi.dwStyle, "menuinfo style is %x\n", mi.dwStyle);
- }
+
+ mi.fMask = MIM_STYLE;
+ ret = GetMenuInfo( menu, &mi);
+ ok( ret, "GetMenuInfo failed: %d\n", GetLastError());
+ ok( menu != NULL, "GetMenuInfo() failed\n");
+ ok( 0 == mi.dwStyle, "menuinfo style is %x\n", mi.dwStyle);
+
/* test 1 */
mii.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_ID;
mii.wID = 1;
START_TEST(menu)
{
- init_function_pointers();
register_menu_check_class();
- /* Wine defines MENUITEMINFO for W2K and above. NT4 and below can't
- * handle that.
- */
- if (correct_behavior())
- {
- test_menu_add_string();
- test_menu_iteminfo();
- test_menu_search_bycommand();
- test_CheckMenuRadioItem();
- test_menu_resource_layout();
- test_InsertMenu();
- test_menualign();
- test_system_menu();
- }
+ test_menu_add_string();
+ test_menu_iteminfo();
+ test_menu_search_bycommand();
+ test_CheckMenuRadioItem();
+ test_menu_resource_layout();
+ test_InsertMenu();
+ test_menualign();
+ test_system_menu();
test_menu_locked_by_window();
test_subpopup_locked_by_menu();
test_menu_ownerdraw();
test_getmenubarinfo();
+ test_GetMenuItemRect();
test_menu_bmp_and_string();
test_menu_getmenuinfo();
test_menu_setmenuinfo();
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
+#include "winreg.h"
+#include <stdio.h>
static HMODULE hdll;
static LONG (WINAPI *pChangeDisplaySettingsExA)(LPCSTR, LPDEVMODEA, HWND, DWORD, LPVOID);
return TRUE;
}
+static int adapter_count = 0;
+static int monitor_count = 0;
+
+static void test_enumdisplaydevices_adapter(int index, const DISPLAY_DEVICEA *device, DWORD flags)
+{
+ char video_name[32];
+ char video_value[128];
+ char buffer[128];
+ int number;
+ int vendor_id;
+ int device_id;
+ int subsys_id;
+ int revision_id;
+ size_t length;
+ HKEY hkey;
+ HDC hdc;
+ DWORD size;
+ LSTATUS ls;
+
+ adapter_count++;
+
+ /* DeviceName */
+ ok(sscanf(device->DeviceName, "\\\\.\\DISPLAY%d", &number) == 1, "#%d: wrong DeviceName %s\n", index,
+ device->DeviceName);
+
+ /* DeviceKey */
+ /* win7 is the only OS version where \Device\Video? value in HLKM\HARDWARE\DEVICEMAP\VIDEO are not in order with adapter index. */
+ if (GetVersion() != 0x1db10106 || !strcmp(winetest_platform, "wine"))
+ {
+ sprintf(video_name, "\\Device\\Video%d", index);
+ ls = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkey);
+ ok(!ls, "#%d: failed to open registry, error: %#x\n", index, ls);
+ if (!ls)
+ {
+ memset(video_value, 0, sizeof(video_value));
+ size = sizeof(video_value);
+ ls = RegQueryValueExA(hkey, video_name, NULL, NULL, (unsigned char *)video_value, &size);
+ ok(!ls, "#%d: failed to get registry value, error: %#x\n", index, ls);
+ RegCloseKey(hkey);
+ ok(!strcmp(video_value, device->DeviceKey), "#%d: wrong DeviceKey: %s\n", index, device->DeviceKey);
+ }
+ }
+ else
+ ok(sscanf(device->DeviceKey, "\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\%[^\\]\\%04d", buffer, &number) == 2,
+ "#%d: wrong DeviceKey %s\n", index, device->DeviceKey);
+
+ /* DeviceString */
+ length = strlen(device->DeviceString);
+ ok(broken(length == 0) || /* XP on Testbot will return an empty string, whereas XP on real machine doesn't. Probably a bug in virtual adapter driver */
+ length > 0, "#%d: expect DeviceString not empty\n", index);
+
+ /* StateFlags */
+ if (index == 0)
+ ok(device->StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE, "#%d: adapter should be primary\n", index);
+ else
+ ok(!(device->StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE), "#%d: adapter should not be primary\n", index);
+
+ if (device->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
+ {
+ /* Test creating DC */
+ hdc = CreateDCA(device->DeviceName, NULL, NULL, NULL);
+ ok(hdc != NULL, "#%d: failed to CreateDC(\"%s\") err=%d\n", index, device->DeviceName, GetLastError());
+ DeleteDC(hdc);
+ }
+
+ /* DeviceID */
+ /* DeviceID should equal to the first string of HardwareID value data in PCI GPU instance. You can verify this
+ * by changing the data and rerun EnumDisplayDevices. But it's difficult to find corresponding PCI device on
+ * userland. So here we check the expected format instead. */
+ if (flags & EDD_GET_DEVICE_INTERFACE_NAME)
+ ok(strlen(device->DeviceID) == 0 || /* vista+ */
+ sscanf(device->DeviceID, "PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
+ &vendor_id, &device_id, &subsys_id, &revision_id) == 4, /* XP/2003 ignores EDD_GET_DEVICE_INTERFACE_NAME */
+ "#%d: got %s\n", index, device->DeviceID);
+ else
+ {
+ ok(broken(strlen(device->DeviceID) == 0) || /* XP on Testbot returns an empty string, whereas real machine doesn't */
+ sscanf(device->DeviceID, "PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", &vendor_id, &device_id, &subsys_id,
+ &revision_id) == 4, "#%d: wrong DeviceID %s\n", index, device->DeviceID);
+ }
+}
+
+static void test_enumdisplaydevices_monitor(int adapter_index, int monitor_index, const char *adapter_name,
+ const DISPLAY_DEVICEA *device, DWORD flags)
+{
+ static const char device_id_prefix[] = "MONITOR\\Default_Monitor\\{4d36e96e-e325-11ce-bfc1-08002be10318}\\";
+ static const char device_key_prefix[] = "\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class"
+ "\\{4d36e96e-e325-11ce-bfc1-08002be10318}\\";
+ char monitor_name[32];
+ char buffer[128];
+ int number;
+
+ monitor_count++;
+
+ /* DeviceName */
+ lstrcpyA(monitor_name, adapter_name);
+ sprintf(monitor_name + strlen(monitor_name), "\\Monitor%d", monitor_index);
+ ok(!strcmp(monitor_name, device->DeviceName), "#%d: expect %s, got %s\n", monitor_index, monitor_name, device->DeviceName);
+
+ /* DeviceString */
+ ok(strlen(device->DeviceString) > 0, "#%d: expect DeviceString not empty\n", monitor_index);
+
+ /* StateFlags */
+ if (adapter_index == 0 && monitor_index == 0)
+ ok(device->StateFlags & DISPLAY_DEVICE_ATTACHED, "#%d expect to have a primary monitor attached\n", monitor_index);
+ else
+ ok(device->StateFlags <= (DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE), "#%d wrong state %#x\n", monitor_index,
+ device->StateFlags);
+
+ /* DeviceID */
+ lstrcpynA(buffer, device->DeviceID, sizeof(device_id_prefix));
+ if (flags & EDD_GET_DEVICE_INTERFACE_NAME)
+ { /* HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\Default_Monitor\4&2abfaa30&0&UID0 GUID_DEVINTERFACE_MONITOR
+ * ^ ^ ^
+ * Expect format \\?\DISPLAY#Default_Monitor#4&2abfaa30&0&UID0#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7} */
+ ok(strlen(device->DeviceID) == 0 || /* vista ~ win7 */
+ sscanf(device->DeviceID, "\\\\?\\DISPLAY#Default_Monitor#%[^#]#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}", buffer) == 1 || /* win8+ */
+ (!lstrcmpiA(buffer, device_id_prefix) &&
+ sscanf(device->DeviceID + sizeof(device_id_prefix) - 1, "%04d", &number) == 1), /* XP/2003 ignores EDD_GET_DEVICE_INTERFACE_NAME */
+ "#%d: wrong DeviceID : %s\n", monitor_index, device->DeviceID);
+ }
+ else
+ {
+ /* Expect HarewareID value data + Driver value data in HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\Default_Monitor\{Instance} */
+ /* But we don't know which monitor instance this belongs to, so check format instead */
+ ok(!lstrcmpiA(buffer, device_id_prefix), "#%d wrong DeviceID : %s\n", monitor_index, device->DeviceID);
+ ok(sscanf(device->DeviceID + sizeof(device_id_prefix) - 1, "%04d", &number) == 1,
+ "#%d wrong DeviceID : %s\n", monitor_index, device->DeviceID);
+ }
+
+ /* DeviceKey */
+ lstrcpynA(buffer, device->DeviceKey, sizeof(device_key_prefix));
+ ok(!lstrcmpiA(buffer, device_key_prefix), "#%d: wrong DeviceKey : %s\n", monitor_index, device->DeviceKey);
+ ok(sscanf(device->DeviceKey + sizeof(device_key_prefix) - 1, "%04d", &number) == 1,
+ "#%d wrong DeviceKey : %s\n", monitor_index, device->DeviceKey);
+}
+
static void test_enumdisplaydevices(void)
{
+ static const DWORD flags[] = {0, EDD_GET_DEVICE_INTERFACE_NAME};
DISPLAY_DEVICEA dd;
char primary_device_name[32];
char primary_monitor_device_name[32];
- DWORD primary_num = -1, num = 0;
+ char adapter_name[32];
+ int number;
+ int flag_index;
+ int adapter_index;
+ int monitor_index;
BOOL ret;
if (!pEnumDisplayDevicesA)
return;
}
+ /* Doesn't accept \\.\DISPLAY */
dd.cb = sizeof(dd);
- for (num = 0;; num++)
- {
- HDC dc;
- ret = pEnumDisplayDevicesA(NULL, num, &dd, 0);
- if(!ret) break;
+ ret = pEnumDisplayDevicesA("\\\\.\\DISPLAY", 0, &dd, 0);
+ ok(!ret, "Expect failure\n");
- if(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
- {
- strcpy(primary_device_name, dd.DeviceName);
- primary_num = num;
- }
- if(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
+ /* Enumeration */
+ for (flag_index = 0; flag_index < ARRAY_SIZE(flags); flag_index++)
+ for (adapter_index = 0; pEnumDisplayDevicesA(NULL, adapter_index, &dd, flags[flag_index]); adapter_index++)
{
- /* test creating DC */
- dc = CreateDCA(dd.DeviceName, NULL, NULL, NULL);
- ok(dc != NULL, "Failed to CreateDC(\"%s\") err=%d\n", dd.DeviceName, GetLastError());
- DeleteDC(dc);
+ lstrcpyA(adapter_name, dd.DeviceName);
+
+ if (sscanf(adapter_name, "\\\\.\\DISPLAYV%d", &number) == 1)
+ {
+ skip("Skipping software devices %s:%s\n", adapter_name, dd.DeviceString);
+ continue;
+ }
+
+ test_enumdisplaydevices_adapter(adapter_index, &dd, flags[flag_index]);
+
+ for (monitor_index = 0; pEnumDisplayDevicesA(adapter_name, monitor_index, &dd, flags[flag_index]);
+ monitor_index++)
+ test_enumdisplaydevices_monitor(adapter_index, monitor_index, adapter_name, &dd, flags[flag_index]);
}
- }
- if (primary_num == -1 || !pEnumDisplayMonitors || !pGetMonitorInfoA)
+ ok(adapter_count > 0, "Expect at least one adapter found\n");
+ /* XP on Testbot doesn't report a monitor, whereas XP on real machine does */
+ ok(broken(monitor_count == 0) || monitor_count > 0, "Expect at least one monitor found\n");
+
+ if (!pEnumDisplayMonitors || !pGetMonitorInfoA)
{
win_skip("EnumDisplayMonitors or GetMonitorInfoA are not available\n");
return;
}
+ ret = pEnumDisplayDevicesA(NULL, 0, &dd, 0);
+ ok(ret, "Expect success\n");
+ lstrcpyA(primary_device_name, dd.DeviceName);
+
primary_monitor_device_name[0] = 0;
ret = pEnumDisplayMonitors(NULL, NULL, monitor_enum_proc, (LPARAM)primary_monitor_device_name);
ok(ret, "EnumDisplayMonitors failed\n");
ok(!strcmp(primary_monitor_device_name, primary_device_name),
"monitor device name %s, device name %s\n", primary_monitor_device_name,
primary_device_name);
-
- dd.cb = sizeof(dd);
- for (num = 0;; num++)
- {
- ret = pEnumDisplayDevicesA(primary_device_name, num, &dd, 0);
- if (!ret) break;
-
- dd.DeviceID[63] = 0;
- ok(!strcasecmp(dd.DeviceID, "Monitor\\Default_Monitor\\{4D36E96E-E325-11CE-BFC1-08002BE10318}\\"),
- "DeviceID \"%s\" does not start with \"Monitor\\Default_Monitor\\...\" prefix\n", dd.DeviceID);
- }
}
struct vid_mode
{0, 0, 0, 0, DM_DISPLAYFREQUENCY, 0}
*/
};
-#define vid_modes_cnt (sizeof(vid_modes_test) / sizeof(vid_modes_test[0]))
static void test_ChangeDisplaySettingsEx(void)
{
memset(&dm, 0, sizeof(dm));
dm.dmSize = sizeof(dm);
- for (i = 0; i < vid_modes_cnt; i++)
+ for (i = 0; i < ARRAY_SIZE(vid_modes_test); i++)
{
dm.dmPelsWidth = vid_modes_test[i].w;
dm.dmPelsHeight = vid_modes_test[i].h;
/* tests for cbSize in MONITORINFO */
monitor = pMonitorFromWindow( 0, MONITOR_DEFAULTTOPRIMARY );
- for (i = 0; i < (sizeof(testdatami) / sizeof(testdatami[0])); i++)
+ for (i = 0; i < ARRAY_SIZE(testdatami); i++)
{
memset( &mi, 0, sizeof(mi) );
mi.cbSize = testdatami[i].cbSize;
}
/* tests for cbSize in MONITORINFOEXA */
- for (i = 0; i < (sizeof(testdatamiexa) / sizeof(testdatamiexa[0])); i++)
+ for (i = 0; i < ARRAY_SIZE(testdatamiexa); i++)
{
memset( &miexa, 0, sizeof(miexa) );
miexa.cbSize = testdatamiexa[i].cbSize;
}
/* tests for cbSize in MONITORINFOEXW */
- for (i = 0; i < (sizeof(testdatamiexw) / sizeof(testdatamiexw[0])); i++)
+ for (i = 0; i < ARRAY_SIZE(testdatamiexw); i++)
{
memset( &miexw, 0, sizeof(miexw) );
miexw.cbSize = testdatamiexw[i].cbSize;
paths = modes = 100;
ret = pGetDisplayConfigBufferSizes(0, &paths, &modes);
ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_NOT_SUPPORTED, "got %d\n", ret);
- ok(modes == 0 && paths == 0, "got %u, %u\n", modes, paths);
+ ok((modes == 0 || modes == 100) && paths == 0, "got %u, %u\n", modes, paths);
}
START_TEST(monitor)
{ WM_GETTITLEBARINFOEX, sent|optional },
{ WM_NCPAINT, sent|beginpaint|optional },
{ WM_ERASEBKGND, sent|beginpaint|optional },
+ { WM_SYNCPAINT, sent|optional },
{ 0 }
};
/* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */
{ 0 }
};
/* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
-static const struct message WmShowMaxPopupResizedSeq_todo[] = {
- { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
- { WM_GETMINMAXINFO, sent },
- { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED },
- { WM_NCCALCSIZE, sent|wparam, TRUE },
- { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
- { HCBT_ACTIVATE, hook },
- { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
- { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
- { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
- { WM_NCPAINT, sent|wparam|optional, 1 },
- { WM_ERASEBKGND, sent|optional },
- { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
- { WM_ACTIVATEAPP, sent|wparam, 1 },
- { WM_NCACTIVATE, sent },
- { WM_ACTIVATE, sent|wparam, 1 },
- { HCBT_SETFOCUS, hook },
- { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
- { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
- { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
- { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
- { WM_GETTEXT, sent|optional },
- { WM_NCPAINT, sent|wparam|optional, 1 },
- { WM_ERASEBKGND, sent|optional },
- { WM_WINDOWPOSCHANGED, sent },
- /* WinNT4.0 sends WM_MOVE */
- { WM_MOVE, sent|defwinproc|optional },
- { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED },
- { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
- { 0 }
-};
static const struct message WmShowMaxPopupResizedSeq[] = {
{ HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
{ WM_GETMINMAXINFO, sent },
{ EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
{ WM_SETFOCUS, sent|wparam|defwinproc, 0 },
{ WM_GETTEXT, sent|optional },
- { WM_NCPAINT, sent|optional }, /* We'll check WM_NCPAINT behaviour in another test */
+ { WM_NCPAINT, sent|wparam|optional, 1 },
{ WM_ERASEBKGND, sent|optional },
{ WM_WINDOWPOSCHANGED, sent },
/* WinNT4.0 sends WM_MOVE */
{ WM_ERASEBKGND, sent|defwinproc|optional },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+ { WM_SIZE, sent|defwinproc|optional },
{ 0 }
};
/* CreateWindow(WS_VISIBLE) for popup window */
{ WM_MDIACTIVATE, sent|defwinproc|optional },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
+ { WM_SIZE, sent|defwinproc|optional },
{ 0 }
};
/* WM_MDIMAXIMIZE for an MDI child window with invisible parent */
ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
ShowWindow(mdi_child2, SW_MINIMIZE);
- ok_sequence(WmMinimizeMDIchildVisibleSeq, "ShowWindow(SW_MINIMIZE):MDI child", TRUE);
+ ok_sequence(WmMinimizeMDIchildVisibleSeq, "ShowWindow(SW_MINIMIZE):MDI child", FALSE);
ok(GetActiveWindow() == mdi_frame, "wrong active window %p\n", GetActiveWindow());
ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
DestroyWindow(hwnd);
flush_sequence();
- /* Test again, this time the NC_PAINT message */
- hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
- 100, 100, 200, 200, 0, 0, 0, NULL);
- ok (hwnd != 0, "Failed to create popup window\n");
- SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE);
- flush_sequence();
- ShowWindow(hwnd, SW_SHOWMAXIMIZED);
- ok_sequence(WmShowMaxPopupResizedSeq_todo,
- "ShowWindow(SW_SHOWMAXIMIZED):invisible maximized and resized popup TODO", TRUE);
- DestroyWindow(hwnd);
- flush_sequence();
-
/* Test 2:
* 1. Create invisible maximized popup window.
* 2. Show it maximized.
flush_sequence();
}
+static void test_recursive_activation(void)
+{
+ static const struct message seq[] =
+ {
+ { HCBT_ACTIVATE, hook },
+ { WM_NCACTIVATE, sent|wparam, TRUE },
+ { WM_ACTIVATE, sent|wparam, WA_ACTIVE },
+ { HCBT_ACTIVATE, hook },
+ { WM_NCACTIVATE, sent|wparam, FALSE },
+ { WM_ACTIVATE, sent|wparam, WA_INACTIVE },
+ { WM_SETFOCUS, sent|optional },
+ { 0 }
+ };
+ HWND hwnd, recursive;
+
+ hwnd = CreateWindowExA(0, "SimpleWindowClass", NULL, WS_OVERLAPPED|WS_VISIBLE,
+ 100, 100, 200, 200, 0, 0, 0, NULL);
+ ok(hwnd != 0, "Failed to create simple window\n");
+
+ recursive = CreateWindowExA(0, "RecursiveActivationClass", NULL, WS_OVERLAPPED|WS_VISIBLE,
+ 10, 10, 50, 50, hwnd, 0, 0, NULL);
+ ok(recursive != 0, "Failed to create recursive activation window\n");
+ SetActiveWindow(hwnd);
+
+ flush_sequence();
+ SetActiveWindow(recursive);
+ ok_sequence(seq, "Recursive Activation", FALSE);
+
+ DestroyWindow(recursive);
+ DestroyWindow(hwnd);
+ flush_sequence();
+}
+
static void test_sys_menu(void)
{
HWND hwnd;
DBT_DEVICETYPESPECIFIC,
DBT_CUSTOMEVENT};
- for (i = 0; i < sizeof(wparams)/sizeof(wparams[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(wparams); i++)
{
SetLastError(0xdeadbeef);
ret = PostMessageA(hwnd, WM_DEVICECHANGE, wparams[i], 0);
ShowWindow(hwnd, SW_MINIMIZE);
flush_events();
- ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", TRUE);
+ ok_sequence(WmShowMinOverlappedSeq, "ShowWindow(SW_SHOWMINIMIZED):overlapped", FALSE);
flush_sequence();
if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MINIMIZE)
hwnd = CreateWindowExA(0, "TestWindowClass", "Test Popup", WS_POPUP | WS_VISIBLE,
-10, -10, 10000, 10000, NULL, 0, 0, NULL );
ok (hwnd != 0, "Failed to create popup window\n");
- ok_sequence(WmShowPopupExtremeLocationSeq, "RedrawWindow:show_popup_extreme_location", TRUE);
+ ok_sequence(WmShowPopupExtremeLocationSeq, "RedrawWindow:show_popup_extreme_location", FALSE);
DestroyWindow(hwnd);
hfont2 = CreateFontIndirectA(&logfont);
ok(hfont2 != NULL, "Failed to create Tahoma font\n");
- for (i = 0; i < sizeof(button)/sizeof(button[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(button); i++)
{
MSG msg;
DWORD style, state;
DestroyWindow(parent);
}
+static void test_button_bm_get_set_image(void)
+{
+ HWND hwnd;
+ HDC hdc;
+ HBITMAP hbmp1x1;
+ HBITMAP hbmp2x2;
+ HBITMAP hmask2x2;
+ ICONINFO icon_info2x2;
+ HICON hicon2x2;
+ HBITMAP hbmp;
+ HICON hicon;
+ ICONINFO icon_info;
+ BITMAP bm;
+ DWORD default_style = BS_PUSHBUTTON | WS_TABSTOP | WS_POPUP | WS_VISIBLE;
+ LRESULT ret;
+
+ hdc = GetDC(0);
+ hbmp1x1 = CreateCompatibleBitmap(hdc, 1, 1);
+ hbmp2x2 = CreateCompatibleBitmap(hdc, 2, 2);
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp1x1, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp2x2, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+
+ hmask2x2 = CreateCompatibleBitmap(hdc, 2, 2);
+ ZeroMemory(&icon_info2x2, sizeof(icon_info2x2));
+ icon_info2x2.fIcon = TRUE;
+ icon_info2x2.hbmMask = hmask2x2;
+ icon_info2x2.hbmColor = hbmp2x2;
+ hicon2x2 = CreateIconIndirect(&icon_info2x2);
+
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon2x2, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+
+ /* Set bitmap with BS_BITMAP */
+ hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0);
+ ok(hbmp != 0, "Expect hbmp not 0\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(hbmp, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 1 && bm.bmHeight == 1, "Expect bitmap size: %d,%d, got: %d,%d\n", 1, 1,
+ bm.bmWidth, bm.bmHeight);
+ DestroyWindow(hwnd);
+
+ /* Set bitmap without BS_BITMAP */
+ hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ ok(ret == 0, "Expect ret to be 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0);
+ ok(hbmp == NULL, "Expect hbmp to be NULL\n");
+ DestroyWindow(hwnd);
+
+ /* Set icon with BS_ICON */
+ hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2);
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0);
+ ok(hicon != NULL, "Expect hicon not NULL\n");
+ ZeroMemory(&icon_info, sizeof(icon_info));
+ ok(GetIconInfo(hicon, &icon_info), "Expect GetIconInfo() success\n");
+ ZeroMemory(&bm, sizeof(bm));
+ ok(GetObjectW(icon_info.hbmColor, sizeof(bm), &bm), "Expect GetObjectW() success\n");
+ ok(bm.bmWidth == 2 && bm.bmHeight == 2, "Expect bitmap size: %d,%d, got: %d,%d\n", 2, 2,
+ bm.bmWidth, bm.bmHeight);
+ DeleteObject(icon_info.hbmColor);
+ DeleteObject(icon_info.hbmMask);
+ DestroyWindow(hwnd);
+
+ /* Set icon without BS_ICON */
+ hwnd = CreateWindowA("Button", "test", default_style, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd not NULL\n");
+ ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2);
+ ok(ret == 0, "Expect ret to be 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0);
+ ok(hicon == NULL, "Expect hicon to be NULL\n");
+ DestroyWindow(hwnd);
+
+ /* Set icon with BS_BITMAP */
+ hwnd = CreateWindowA("Button", "test", default_style | BS_BITMAP, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon2x2);
+ ok(ret == 0, "Expect ret to be 0\n");
+ hicon = (HICON)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_ICON, 0);
+ ok(hicon == NULL, "Expect hicon to be NULL\n");
+ DestroyWindow(hwnd);
+
+ /* Set bitmap with BS_ICON */
+ hwnd = CreateWindowA("Button", "test", default_style | BS_ICON, 0, 0, 100, 100, 0, 0, 0, 0);
+ ok(hwnd != NULL, "Expect hwnd to be not NULL\n");
+ ret = SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp1x1);
+ ok(ret == 0, "Expect ret to be 0\n");
+ hbmp = (HBITMAP)SendMessageA(hwnd, BM_GETIMAGE, (WPARAM)IMAGE_BITMAP, 0);
+ ok(hbmp == NULL, "Expect hbmp to be NULL\n");
+ DestroyWindow(hwnd);
+
+ DestroyIcon(hicon2x2);
+ DeleteObject(hmask2x2);
+ DeleteObject(hbmp2x2);
+ DeleteObject(hbmp1x1);
+ ReleaseDC(0, hdc);
+}
+
#define ID_RADIO1 501
#define ID_RADIO2 502
#define ID_RADIO3 503
subclass_static();
- for (i = 0; i < sizeof(static_ctrl)/sizeof(static_ctrl[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(static_ctrl); i++)
{
hwnd = CreateWindowExA(0, "my_static_class", "test", static_ctrl[i].style | WS_POPUP,
0, 0, 50, 14, 0, 0, 0, NULL);
HeapFree( GetProcessHeap(), 0, data );
}
-static void check_update_rgn( HWND hwnd, HRGN hrgn )
+#define check_update_rgn( hwnd, hrgn ) check_update_rgn_( __LINE__, hwnd, hrgn )
+static void check_update_rgn_( int line, HWND hwnd, HRGN hrgn )
{
INT ret;
RECT r1, r2;
ok( ret != ERROR, "GetUpdateRgn failed\n" );
if (ret == NULLREGION)
{
- ok( !hrgn, "Update region shouldn't be empty\n" );
+ ok_(__FILE__,line)( !hrgn, "Update region shouldn't be empty\n" );
}
else
{
if (CombineRgn( tmp, hrgn, update, RGN_XOR ) != NULLREGION)
{
- ok( 0, "Regions are different\n" );
+ ok_(__FILE__,line)( 0, "Regions are different\n" );
if (winetest_debug > 0)
{
printf( "Update region: " );
}
GetRgnBox( update, &r1 );
GetUpdateRect( hwnd, &r2, FALSE );
- ok( EqualRect( &r1, &r2 ), "Rectangles are different: %s / %s\n", wine_dbgstr_rect( &r1 ),
- wine_dbgstr_rect( &r2 ));
+ ok_(__FILE__,line)( EqualRect( &r1, &r2 ), "Rectangles are different: %s / %s\n",
+ wine_dbgstr_rect( &r1 ), wine_dbgstr_rect( &r2 ));
DeleteObject( tmp );
DeleteObject( update );
/* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
* all windows and sends WM_ERASEBKGND and WM_NCPAINT.
*/
- trace("testing InvalidateRect(0, NULL, FALSE)\n");
SetRectEmpty( &rect );
- ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) should fail\n");
+ ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) failed\n");
+ check_update_rgn( hwnd, hrgn );
+ ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
+ flush_events();
+ ok_sequence( WmPaint, "Paint", FALSE );
+ RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
+ check_update_rgn( hwnd, 0 );
+
+ SetRectEmpty( &rect );
+ ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ),
+ "RedrawWindow failed\n");
+ check_update_rgn( hwnd, 0 );
+
+ SetRectEmpty( &rect );
+ ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_VALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ),
+ "RedrawWindow failed\n");
+ check_update_rgn( hwnd, 0 );
+
+ GetWindowRect( hwnd, &rect );
+ ok(RedrawWindow(0, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ),
+ "RedrawWindow failed\n");
+ check_update_rgn( hwnd, 0 );
+
+ flush_events();
+ ok(RedrawWindow(0, &rect, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ),
+ "RedrawWindow failed\n");
+ check_update_rgn( hwnd, hrgn );
+ ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
+ flush_events();
+ ok_sequence( WmPaint, "Paint", FALSE );
+ RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
+ check_update_rgn( hwnd, 0 );
+
+ ok(RedrawWindow(GetDesktopWindow(), &rect, 0,
+ RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ),
+ "RedrawWindow failed\n");
+ ret = GetUpdateRgn( hwnd, hrgn2, FALSE );
+ ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */
+ "region should be null (%d)\n", ret );
+ if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
+ RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
+ flush_events();
+
+ ok(RedrawWindow(GetDesktopWindow(), NULL, 0,
+ RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ),
+ "RedrawWindow failed\n");
+ ret = GetUpdateRgn( hwnd, hrgn2, FALSE );
+ ok( ret == NULLREGION || broken(ret == SIMPLEREGION), /* <= win7 */
+ "region should be null (%d)\n", ret );
+ if (ret == SIMPLEREGION) ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
+ RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
+ flush_events();
+
+ SetRectRgn( hrgn2, rect.left, rect.top, rect.right, rect.bottom );
+ ok(RedrawWindow(0, NULL, hrgn2, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW ),
+ "RedrawWindow failed\n");
+ check_update_rgn( hwnd, hrgn );
+ ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
+ flush_events();
+ ok_sequence( WmPaint, "Paint", FALSE );
+ RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
+ check_update_rgn( hwnd, 0 );
+
+ ok(RedrawWindow(0, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW ),
+ "RedrawWindow failed\n");
+ check_update_rgn( hwnd, 0 );
+
+ ok(RedrawWindow(0, NULL, 0, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW ),
+ "RedrawWindow failed\n");
check_update_rgn( hwnd, hrgn );
ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
flush_events();
/* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
* all windows and sends WM_ERASEBKGND and WM_NCPAINT.
*/
- trace("testing ValidateRect(0, NULL)\n");
SetRectEmpty( &rect );
if (ValidateRect(0, &rect) && /* not supported on Win9x */
GetUpdateRect(hwnd, NULL, FALSE)) /* or >= Win 8 */
check_update_rgn( hwnd, 0 );
}
- trace("testing InvalidateRgn(0, NULL, FALSE)\n");
SetLastError(0xdeadbeef);
ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n");
ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || GetLastError() == 0xdeadbeef,
flush_events();
ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
- trace("testing ValidateRgn(0, NULL)\n");
SetLastError(0xdeadbeef);
ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n");
ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
flush_events();
ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
- trace("testing UpdateWindow(NULL)\n");
SetLastError(0xdeadbeef);
ok(!UpdateWindow(NULL), "UpdateWindow(NULL) should fail\n");
ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
return ret;
}
+static LRESULT WINAPI recursive_activation_wndprocA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static LONG defwndproc_counter = 0;
+ struct recvd_message msg;
+ LRESULT ret;
+
+ switch (message)
+ {
+ /* log only specific messages we are interested in */
+ case WM_NCACTIVATE:
+ case WM_ACTIVATE:
+ case WM_SETFOCUS:
+ case WM_KILLFOCUS:
+ break;
+ default:
+ return DefWindowProcA(hwnd, message, wParam, lParam);
+ }
+
+ msg.hwnd = hwnd;
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ msg.descr = "recursive_activation";
+ add_message(&msg);
+
+ /* recursively activate ourselves by first losing activation and changing it back */
+ if (message == WM_ACTIVATE && LOWORD(wParam) != WA_INACTIVE)
+ {
+ SetActiveWindow((HWND)lParam);
+ SetActiveWindow(hwnd);
+ return 0;
+ }
+
+ defwndproc_counter++;
+ ret = DefWindowProcA(hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
static LRESULT WINAPI PaintLoopProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
cls.lpszClassName = "ShowWindowClass";
if(!RegisterClassA(&cls)) return FALSE;
+ cls.lpfnWndProc = recursive_activation_wndprocA;
+ cls.lpszClassName = "RecursiveActivationClass";
+ if(!RegisterClassA(&cls)) return FALSE;
+
cls.lpfnWndProc = PopupMsgCheckProcA;
cls.lpszClassName = "TestPopupClass";
if(!RegisterClassA(&cls)) return FALSE;
{
if (!lstrcmpiA(buf, "TestWindowClass") ||
!lstrcmpiA(buf, "ShowWindowClass") ||
+ !lstrcmpiA(buf, "RecursiveActivationClass") ||
!lstrcmpiA(buf, "TestParentClass") ||
!lstrcmpiA(buf, "TestPopupClass") ||
!lstrcmpiA(buf, "SimpleWindowClass") ||
win_skip("SetCoalescableTimer not available.\n");
/* Check what happens when we're running out of timers */
- for (i=0; i<sizeof(ids)/sizeof(ids[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(ids); i++)
{
SetLastError(0xdeadbeef);
ids[i] = SetTimer(NULL, 0, USER_TIMER_MAXIMUM, tfunc);
if (!ids[i]) break;
}
- ok(i != sizeof(ids)/sizeof(ids[0]), "all timers were created successfully\n");
+ ok(i != ARRAY_SIZE(ids), "all timers were created successfully\n");
ok(GetLastError()==ERROR_NO_MORE_USER_HANDLES || broken(GetLastError()==0xdeadbeef),
"GetLastError() = %d\n", GetLastError());
while (i > 0) KillTimer(NULL, ids[--i]);
ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
}
- for (i = 0; i < sizeof(WmWinEventsSeq)/sizeof(WmWinEventsSeq[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(WmWinEventsSeq); i++)
pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
qstatus = GetQueueStatus(qs_all_input);
ok(qstatus == 0, "wrong qstatus %08x\n", qstatus);
}
+
+ PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0);
+ ret = PeekMessageA(&msg, (HWND)-1, 0, 0, PM_NOREMOVE);
+ ok(ret == TRUE, "wrong ret %d\n", ret);
+ ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
+ ret = GetMessageA(&msg, (HWND)-1, 0, 0);
+ ok(ret == TRUE, "wrong ret %d\n", ret);
+ ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
+
+ PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0);
+ ret = PeekMessageA(&msg, (HWND)1, 0, 0, PM_NOREMOVE);
+ ok(ret == TRUE, "wrong ret %d\n", ret);
+ ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
+ ret = GetMessageA(&msg, (HWND)1, 0, 0);
+ ok(ret == TRUE, "wrong ret %d\n", ret);
+ ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
+
+ PostThreadMessageA(GetCurrentThreadId(), WM_USER, 0, 0);
+ ret = PeekMessageA(&msg, (HWND)0xffff, 0, 0, PM_NOREMOVE);
+ ok(ret == TRUE, "wrong ret %d\n", ret);
+ ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
+ ret = GetMessageA(&msg, (HWND)0xffff, 0, 0);
+ ok(ret == TRUE, "wrong ret %d\n", ret);
+ ok(msg.message == WM_USER, "wrong message %u\n", msg.message);
+
done:
trace("signalling to exit\n");
SetEvent(info.hevent[EV_STOP]);
ok(EqualRect(&win_rc, &wp.rcNormalPosition), "expected %s got %s\n", wine_dbgstr_rect(&win_rc),
wine_dbgstr_rect(&wp.rcNormalPosition));
- for (i = 0; i < sizeof(sw)/sizeof(sw[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(sw); i++)
{
static const char * const sw_cmd_name[13] =
{
{ WM_QUERYNEWPALETTE, sent|parent|optional }, /* TODO: this message should not be sent */
{ WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
{ WM_WINDOWPOSCHANGING, sent|parent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+ { WM_WINDOWPOSCHANGED, sent|parent|wparam|optional, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+ { WM_WINDOWPOSCHANGED, sent|parent|wparam|optional, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
{ WM_ACTIVATEAPP, sent|parent|wparam, 1 },
{ WM_NCACTIVATE, sent|parent },
{ WM_ACTIVATE, sent|parent|wparam, 1 },
{ 0 }
};
+/* DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0) to minimized visible window */
+static const struct message WmRestoreMinimizedOverlappedSeq[] =
+{
+ { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_RESTORE, 0 },
+ { HCBT_MINMAX, hook },
+ { WM_QUERYOPEN, sent },
+ { WM_GETTEXT, sent|optional },
+ { WM_NCACTIVATE, sent|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_WINDOWPOSCHANGED, sent|optional },
+ { WM_WINDOWPOSCHANGING, sent|optional },
+ { WM_GETMINMAXINFO, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_NCPAINT, sent|optional },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { WM_WINDOWPOSCHANGED, sent|optional },
+ { HCBT_ACTIVATE, hook },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
+ { WM_ACTIVATEAPP, sent|wparam, TRUE },
+ { WM_NCACTIVATE, sent|wparam, TRUE },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ACTIVATE, sent|wparam, TRUE },
+ { HCBT_SETFOCUS, hook },
+ { WM_SETFOCUS, sent|defwinproc },
+ { WM_NCPAINT, sent },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent },
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_FRAMECHANGED|SWP_STATECHANGED },
+ { WM_MOVE, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|optional },
+ { WM_NCPAINT, sent|optional },
+ { WM_ERASEBKGND, sent|optional },
+ { WM_ACTIVATE, sent|wparam, TRUE },
+ { WM_SYNCPAINT, sent|optional },
+ { WM_PAINT, sent },
+ { 0 }
+};
+
struct rbuttonup_thread_data
{
HWND hwnd;
flush_events();
buffA[0] = 0;
- GetWindowTextA(hwnd, buffA, sizeof(buffA)/sizeof(*buffA));
+ GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA));
ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA);
/* Zero high word of the lParam */
res = DefWindowProcA(hwnd, WM_SETTEXT, 0, 0x1234);
ok(res == 0, "WM_SETTEXT was expected to fail, %ld\n", res);
- GetWindowTextA(hwnd, buffA, sizeof(buffA)/sizeof(*buffA));
+ GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA));
ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA);
res = DefWindowProcW(hwnd, WM_SETTEXT, 0, 0x1234);
ok(res == 0, "WM_SETTEXT was expected to fail, %ld\n", res);
- GetWindowTextA(hwnd, buffA, sizeof(buffA)/sizeof(*buffA));
+ GetWindowTextA(hwnd, buffA, ARRAY_SIZE(buffA));
ok(!strcmp(buffA, "test_defwndproc"), "unexpected window text, %s\n", buffA);
+ ShowWindow(hwnd, SW_MINIMIZE);
+ flush_events();
+ flush_sequence();
+
+ DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
+ flush_events();
+ ok_sequence(WmRestoreMinimizedOverlappedSeq, "DefWindowProcA(SC_RESTORE):overlapped", TRUE);
+ flush_sequence();
+
GetCursorPos(&pos);
GetWindowRect(hwnd, &rect);
x = (rect.left+rect.right) / 2;
DestroyWindow( hwnd);
}
+static void test_desktop_winproc(void)
+{
+ HINSTANCE instance = GetModuleHandleA(NULL);
+ RECT rect, default_rect;
+ WNDPROC desktop_proc;
+ char buffer[256];
+ WNDCLASSA cls;
+ LRESULT res;
+ HWND hwnd;
+ BOOL ret;
+
+ ret = GetClassInfoA(instance, (const CHAR *)MAKEINTATOM(32769), &cls);
+ ok(ret, "Failed to get desktop class.\n");
+ desktop_proc = cls.lpfnWndProc;
+
+ memset(&cls, 0, sizeof(cls));
+ cls.lpfnWndProc = desktop_proc;
+ cls.hInstance = instance;
+ cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
+ cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+ cls.lpszClassName = "TestDesktopClass";
+ ret = !!RegisterClassA(&cls);
+ ok(ret, "Failed to register class.\n");
+
+ hwnd = CreateWindowExA(0, cls.lpszClassName, "test_desktop_wndproc",
+ WS_VISIBLE | WS_CAPTION | WS_OVERLAPPEDWINDOW, 0, 0, 500, 100, 0, 0, 0, NULL);
+ if (!hwnd) /* win2003 */
+ {
+ skip("Failed to create window with desktop window procedure.\n");
+ goto out_unregister;
+ }
+
+ memset(&cls, 0, sizeof(cls));
+ ret = GetClassInfoA(instance, "TestDesktopClass", &cls);
+ ok(ret, "Failed to get class info.\n");
+ ok(cls.lpfnWndProc == desktop_proc, "Got %p, expected %p.\n", cls.lpfnWndProc, desktop_proc);
+
+ GetWindowTextA(hwnd, buffer, ARRAY_SIZE(buffer));
+ todo_wine ok(!strcmp(buffer, "test_desktop_wndproc"), "Got unexpected window text: %s.\n", buffer);
+
+ res = CallWindowProcA(desktop_proc, hwnd, WM_SETTEXT, 0, (LPARAM)"test");
+ ok(res == TRUE, "Failed to set text, %ld.\n", res);
+ GetWindowTextA(hwnd, buffer, ARRAY_SIZE(buffer));
+ ok(!strcmp(buffer, "test"), "Got unexpected window text: %s.\n", buffer);
+
+ SetRect(&default_rect, 0, 0, 100, 100);
+ res = DefWindowProcW(hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&default_rect);
+ ok(!res, "Got unexpected result %ld.\n", res);
+
+ SetRect(&rect, 0, 0, 100, 100);
+ res = CallWindowProcA(desktop_proc, hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect);
+ ok(!res, "Got unexpected result %ld.\n", res);
+ todo_wine ok(EqualRect(&rect, &default_rect), "rect Got %s, expected %s.\n",
+ wine_dbgstr_rect(&rect), wine_dbgstr_rect(&default_rect));
+
+ DestroyWindow(hwnd);
+
+out_unregister:
+ UnregisterClassA("TestDesktopClass", instance);
+}
+
#define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
static void clear_clipboard_(int line, HWND hWnd)
{
PostMessageA(hwnd, WM_USER+1, 0x1234, 0x5678);
PostMessageA(0, WM_USER+2, 0x5678, 0x1234);
- for (i = 0; i < sizeof(data)/sizeof(data[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(data); i++)
{
memset(&msg, 0xab, sizeof(msg));
ret = PeekMessageA(&msg, data[i].hwnd, 0, 0, PM_NOREMOVE);
oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)broadcast_test_proc);
SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
- for (i = 0; i < sizeof(messages)/sizeof(messages[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(messages); i++)
{
BOOL ret;
MSG msg;
thread = CreateThread( NULL, 0, wait_idle_thread, NULL, 0, &id );
- for (i = 0; i < sizeof(wait_idle_expect)/sizeof(wait_idle_expect[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(wait_idle_expect); i++)
{
ResetEvent( start_event );
ResetEvent( end_event );
-#ifndef __REACTOS__
- sprintf( path, "%s msg %u", argv0, i );
-#else
+#ifdef __REACTOS__
sprintf( path, "%s msg_queue %u", argv0, i );
+#else
+ sprintf( path, "%s msg %u", argv0, i );
#endif
ret = CreateProcessA( NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &pi );
ok( ret, "CreateProcess '%s' failed err %u.\n", path, GetLastError() );
SetParent(child, parent2);
flush_events();
- ok_sequence(WmSetParentSeq_1, "SetParent() visible WS_CHILD", TRUE);
+ ok_sequence(WmSetParentSeq_1, "SetParent() visible WS_CHILD", FALSE);
ok(GetWindowLongA(child, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
ok(!IsWindowVisible(child), "IsWindowVisible() should return FALSE\n");
SetLastError(0xdeadbeef);
ret = UnregisterHotKey(NULL, 0);
- ok(ret == FALSE, "expected FALSE, got %i\n", ret);
- ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef),
- "unexpected error %d\n", GetLastError());
-
if (ret == TRUE)
{
skip("hotkeys not supported\n");
return;
}
+ ok(ret == FALSE, "expected FALSE, got %i\n", ret);
+ ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef),
+ "unexpected error %d\n", GetLastError());
+
test_window = CreateWindowExA(0, "HotkeyWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 200, 200, 0, 0, 0, NULL);
DestroyWindow(hwnd);
}
+static const struct message WmRestoreMinimizedSeq[] =
+{
+ { HCBT_ACTIVATE, hook },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+ { WM_ACTIVATEAPP, sent|wparam, 1 },
+ { WM_NCACTIVATE, sent|wparam, 0x200001 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ACTIVATE, sent|wparam, 0x200001 }, /* Note that activate messages are after WM_WINDOWPOSCHANGED and before WM_SYSCOMMAND */
+ { HCBT_KEYSKIPPED, hook|optional },
+ { WM_SYSKEYUP, sent|optional },
+ { WM_SYSCOMMAND, sent|wparam, SC_RESTORE },
+ { HCBT_SYSCOMMAND, hook|wparam, SC_RESTORE },
+ { HCBT_SYSCOMMAND, hook|wparam|optional, SC_RESTORE },
+ { HCBT_MINMAX, hook },
+ { HCBT_MINMAX, hook|optional },
+ { WM_QUERYOPEN, sent|defwinproc },
+ { WM_QUERYOPEN, sent|optional },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_GETMINMAXINFO, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },
+ { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_ERASEBKGND, sent|defwinproc },
+ { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_MOVE, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 },
+ { WM_NCPAINT, sent|wparam|defwinproc|optional, 1 },
+ { WM_ERASEBKGND, sent|defwinproc|optional },
+ { HCBT_SETFOCUS, hook },
+ { WM_SETFOCUS, sent|defwinproc },
+ { WM_ACTIVATE, sent|wparam|defwinproc, 1 },
+ { WM_PAINT, sent| optional },
+ { WM_SETFOCUS, sent|defwinproc|optional },
+ { HCBT_KEYSKIPPED, hook|optional },
+ { WM_KEYUP, sent|optional },
+ { HCBT_KEYSKIPPED, hook|optional },
+ { WM_SYSKEYUP, sent|optional },
+ { HCBT_KEYSKIPPED, hook|optional },
+ { WM_KEYUP, sent|optional },
+ { WM_PAINT, sent| optional },
+ { 0 }
+};
+
+static void test_restore_messages(void)
+{
+ INPUT ip = {0};
+ HWND hwnd;
+ INT i;
+
+ hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100,
+ 100, 200, 200, 0, 0, 0, NULL);
+ ok (hwnd != 0, "Failed to create overlapped window\n");
+ SetForegroundWindow(hwnd);
+ ShowWindow(hwnd, SW_MINIMIZE);
+ flush_events();
+ flush_sequence();
+
+ for (i = 0; i < 5; i++)
+ {
+ /* Send Alt+Tab to restore test window from minimized state */
+ ip.type = INPUT_KEYBOARD;
+ ip.ki.wVk = VK_MENU;
+ SendInput(1, &ip, sizeof(INPUT));
+ ip.ki.wVk = VK_TAB;
+ SendInput(1, &ip, sizeof(INPUT));
+ ip.ki.wVk = VK_MENU;
+ ip.ki.dwFlags = KEYEVENTF_KEYUP;
+ SendInput(1, &ip, sizeof(INPUT));
+ ip.ki.wVk = VK_TAB;
+ ip.ki.dwFlags = KEYEVENTF_KEYUP;
+ SendInput(1, &ip, sizeof(INPUT));
+ flush_events();
+ if (!IsIconic(hwnd))
+ break;
+ }
+
+ if (IsIconic(hwnd))
+ {
+ skip("Alt+Tab failed to bring up test window.\n");
+ goto done;
+ }
+ ok_sequence(WmRestoreMinimizedSeq, "Restore minimized window", TRUE);
+
+done:
+ DestroyWindow(hwnd);
+}
+
+static void test_invalid_window(void)
+{
+ MSG msg;
+ BOOL ret;
+
+ SetLastError(0xdeadbeef);
+ ret = GetMessageA(&msg, (HWND)0xdeadbeef, 0, 0);
+ ok(ret == -1, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = PeekMessageA(&msg, (HWND)0xdeadbeef, 0, 0, PM_REMOVE);
+ ok(!ret, "wrong ret %d\n", ret);
+ ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError());
+}
+
static void init_funcs(void)
{
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
test_messages();
test_setwindowpos();
test_showwindow();
+ test_recursive_activation();
invisible_parent_tests();
test_mdi_messages();
test_button_messages();
+ test_button_bm_get_set_image();
test_autoradio_BM_CLICK();
test_autoradio_kbd_move();
test_static_messages();
test_quit_message();
test_notify_message();
test_SetActiveWindow();
+ test_restore_messages();
+ test_invalid_window();
if (!pTrackMouseEvent)
win_skip("TrackMouseEvent is not available\n");
test_menu_messages();
test_paintingloop();
test_defwinproc();
+ test_desktop_winproc();
test_clipboard_viewers();
test_keyflags();
test_hotkey();
test_dbcs_wm_char();
test_unicode_wm_char();
test_defwinproc();
+ test_desktop_winproc();
cleanup_tests();
}
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
flush_events();
+ test_restore_messages();
+ test_invalid_window();
+
test_DoubleSetCapture();
/* keep it the last test, under Windows it tends to break the tests
test_ShowWindow();
test_setwindowpos();
test_showwindow();
+ test_recursive_activation();
test_SetWindowRgn();
invisible_parent_tests();
cleanup_tests();
{
init_tests();
test_button_messages();
+ test_button_bm_get_set_image();
test_autoradio_BM_CLICK();
test_autoradio_kbd_move();
test_static_messages();
--- /dev/null
+/* Unit test suite for rawinput.
+ *
+ * Copyright 2019 Remi Bernon for CodeWeavers
+ *
+ * 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 <stdio.h>
+
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "wine/test.h"
+
+static void test_RegisterRawInputDevices(void)
+{
+ HWND hwnd;
+ RAWINPUTDEVICE raw_devices[1];
+ BOOL res;
+
+ raw_devices[0].usUsagePage = 0x01;
+ raw_devices[0].usUsage = 0x05;
+
+ hwnd = CreateWindowExA(WS_EX_TOPMOST, "static", "dinput", WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
+ ok(hwnd != NULL, "CreateWindowExA failed\n");
+
+
+ res = RegisterRawInputDevices(NULL, 0, 0);
+ ok(res == FALSE, "RegisterRawInputDevices succeeded\n");
+
+
+ raw_devices[0].dwFlags = 0;
+ raw_devices[0].hwndTarget = 0;
+
+ SetLastError(0xdeadbeef);
+ res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), 0);
+ ok(res == FALSE, "RegisterRawInputDevices succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "RegisterRawInputDevices returned %08x\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
+ ok(res == TRUE, "RegisterRawInputDevices failed\n");
+ ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08x\n", GetLastError());
+
+
+ /* RIDEV_REMOVE requires hwndTarget == NULL */
+ raw_devices[0].dwFlags = RIDEV_REMOVE;
+ raw_devices[0].hwndTarget = hwnd;
+
+ SetLastError(0xdeadbeef);
+ res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
+ ok(res == FALSE, "RegisterRawInputDevices succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "RegisterRawInputDevices returned %08x\n", GetLastError());
+
+ raw_devices[0].hwndTarget = 0;
+
+ SetLastError(0xdeadbeef);
+ res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
+ ok(res == TRUE, "RegisterRawInputDevices failed\n");
+ ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08x\n", GetLastError());
+
+
+ /* RIDEV_INPUTSINK requires hwndTarget != NULL */
+ raw_devices[0].dwFlags = RIDEV_INPUTSINK;
+ raw_devices[0].hwndTarget = 0;
+
+ SetLastError(0xdeadbeef);
+ res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
+ todo_wine
+ ok(res == FALSE, "RegisterRawInputDevices failed\n");
+ todo_wine
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "RegisterRawInputDevices returned %08x\n", GetLastError());
+
+ raw_devices[0].hwndTarget = hwnd;
+
+ SetLastError(0xdeadbeef);
+ res = RegisterRawInputDevices(raw_devices, ARRAY_SIZE(raw_devices), sizeof(RAWINPUTDEVICE));
+ ok(res == TRUE, "RegisterRawInputDevices succeeded\n");
+ ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08x\n", GetLastError());
+
+ DestroyWindow(hwnd);
+}
+
+START_TEST(rawinput)
+{
+ test_RegisterRawInputDevices();
+}
win_skip( "LoadStringW does not return a pointer to the resource\n" );
return;
}
- length2 = LoadStringW(hInst, 2, returnedstringw, sizeof(returnedstringw) /sizeof(WCHAR)); /* get resource string */
+ length2 = LoadStringW(hInst, 2, returnedstringw, ARRAY_SIZE(returnedstringw)); /* get resource string */
ok(length2 > 0, "LoadStringW failed to load resource 2, ret %d, err %d\n", length2, GetLastError());
ok(length1 == length2, "LoadStringW returned different values dependent on buflen. ret1 %d, ret2 %d\n",
length1, length2);
int ret, ret2;
assert (sizeof str < sizeof buf);
- for (i = 0; i < sizeof tests / sizeof tests[0]; i++) {
+ for (i = 0; i < ARRAY_SIZE(tests); i++) {
const unsigned int bufsiz = tests[i].bufsiz;
const unsigned int expected = tests[i].expected;
const int len = LoadStringA (hInst, 0, buf, bufsiz);
CONTROL "oddlengthtext", -1, "TESTCONTROL", WS_CHILD|WS_VISIBLE|WS_BORDER|WS_TABSTOP, 10,60,100,50 { 1,2,3,4,5 }
}
+GETDLGITEM_TEST_DIALOG DIALOGEX 6, 15, 207, 111
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Test Dialog"
+FONT 8, "MS Shell Dlg"
+{
+ LTEXT "Text1",-1,10,10,100,50
+ LTEXT "Text2",-2,10,10,100,50
+}
+
/* @makedep: test_mono.bmp */
100 BITMAP test_mono.bmp
ok( ret, "The scrollbar should be enabled.\n" );
ok( IsWindowEnabled( hScroll ), "The scrollbar window should be enabled.\n" );
+ SetLastError( 0xdeadbeef );
+ ret = EnableScrollBar( mainwnd, SB_CTL, ESB_ENABLE_BOTH );
+ ok( !ret, "EnableScrollBar should fail.\n" );
+ todo_wine
+ ok( GetLastError() == ERROR_INVALID_PARAMETER
+ || broken(GetLastError() == 0xdeadbeef), /* winxp */
+ "GetLastError() = %u\n", GetLastError() );
+
/* disable window, try to re-enable */
ret = EnableWindow( hScroll, FALSE );
ok( !ret, "got %d\n", ret );
ret = GetScrollPos( hScroll, SB_CTL);
ok( ret == 30, "The position should not be equal to zero\n");
+ SetLastError( 0xdeadbeef );
+ ret = SetScrollPos( mainwnd, SB_CTL, 30, TRUE );
+ ok( !ret, "The position should not be set.\n" );
+ ok( GetLastError() == 0xdeadbeef, "GetLastError() = %u\n", GetLastError() );
+
+ SetLastError( 0xdeadbeef );
+ ret = GetScrollPos( mainwnd, SB_CTL );
+ ok( !ret, "The position should be equal to zero\n");
+ ok( GetLastError() == 0xdeadbeef, "GetLastError() = %u\n", GetLastError() );
+
DestroyWindow(hScroll);
DestroyWindow(mainwnd);
}
ret = ShowScrollBar( NULL, SB_CTL, TRUE );
ok( !ret, "The ShowScrollBar() should failed.\n" );
+ ret = ShowScrollBar( mainwnd, SB_CTL, TRUE );
+ ok( ret, "The ShowScrollBar() should not fail.\n" );
+
DestroyWindow(hScroll);
DestroyWindow(mainwnd);
}
wc.lpfnWndProc = scroll_init_proc;
RegisterClassExA(&wc);
- for(i = 0; i < sizeof style / sizeof style[0]; i++)
+ for(i = 0; i < ARRAY_SIZE(style); i++)
{
/* need not to destroy these windows due creation abort */
CreateWindowExA(0, cls_name, NULL, style[i],
DestroyWindow(mainwnd);
}
+static WNDPROC scrollbar_wndproc;
+
+static SCROLLINFO set_scrollinfo;
+
+static LRESULT CALLBACK subclass_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (msg == WM_CREATE && ((CREATESTRUCTA*)lparam)->lpCreateParams)
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+
+ if (msg == SBM_SETSCROLLINFO)
+ set_scrollinfo = *(SCROLLINFO*)lparam;
+
+ return CallWindowProcA(scrollbar_wndproc, hwnd, msg, wparam, lparam);
+}
+
+static void test_subclass(void)
+{
+ SCROLLBARINFO scroll_info;
+ WNDCLASSEXA class_info;
+ WNDCLASSA wc;
+ LRESULT res;
+ HWND hwnd;
+ BOOL r;
+
+ r = GetClassInfoExA(GetModuleHandleA(NULL), "SCROLLBAR", &class_info);
+ ok(r, "GetClassInfoEx failed: %u\n", GetLastError());
+ scrollbar_wndproc = class_info.lpfnWndProc;
+
+ memset(&wc, 0, sizeof(wc));
+ wc.cbWndExtra = class_info.cbWndExtra + 3; /* more space than needed works */
+ wc.hInstance = GetModuleHandleA(NULL);
+ wc.lpszClassName = "MyTestSubclass";
+ wc.lpfnWndProc = subclass_proc;
+ r = RegisterClassA(&wc);
+ ok(r, "RegisterClass failed: %u\n", GetLastError());
+
+ hwnd = CreateWindowExA( 0, "MyTestSubclass", "Scroll", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0 );
+ ok(hwnd != NULL, "Failed to create window: %u\n", GetLastError());
+
+ r = SetScrollRange(hwnd, SB_CTL, 0, 100, TRUE);
+ ok(r, "SetScrollRange failed: %u\n", GetLastError());
+
+ res = SetScrollPos(hwnd, SB_CTL, 2, FALSE);
+ ok(!res, "SetScrollPos returned %lu\n", res);
+
+ memset(&set_scrollinfo, 0xcc, sizeof(set_scrollinfo));
+ res = SetScrollPos(hwnd, SB_CTL, 1, FALSE);
+ ok(res == 2, "SetScrollPos returned %lu\n", res);
+ ok(set_scrollinfo.cbSize == sizeof(SCROLLINFO), "cbSize = %u\n", set_scrollinfo.cbSize);
+ todo_wine
+ ok(set_scrollinfo.fMask == (0x1000 | SIF_POS), "fMask = %x\n", set_scrollinfo.fMask);
+ ok(set_scrollinfo.nPos == 1, "nPos = %x\n", set_scrollinfo.nPos);
+
+ memset(&scroll_info, 0xcc, sizeof(scroll_info));
+ scroll_info.cbSize = sizeof(scroll_info);
+ res = SendMessageA(hwnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)&scroll_info);
+ ok(res == 1, "SBM_GETSCROLLBARINFO returned %lu\n", res);
+
+ DestroyWindow(hwnd);
+
+ /* if we skip calling wndproc for WM_CREATE, window is not considered a scrollbar */
+ hwnd = CreateWindowExA( 0, "MyTestSubclass", "Scroll", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, GetModuleHandleA(NULL), (void *)1 );
+ ok(hwnd != NULL, "Failed to create window: %u\n", GetLastError());
+
+ memset(&scroll_info, 0xcc, sizeof(scroll_info));
+ scroll_info.cbSize = sizeof(scroll_info);
+ res = SendMessageA(hwnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)&scroll_info);
+ ok(!res, "SBM_GETSCROLLBARINFO returned %lu\n", res);
+
+ DestroyWindow(hwnd);
+
+ /* not enough space in extra data */
+ wc.cbWndExtra = class_info.cbWndExtra - 1;
+ wc.lpszClassName = "MyTestSubclass2";
+ r = RegisterClassA(&wc);
+ ok(r, "RegisterClass failed: %u\n", GetLastError());
+
+ hwnd = CreateWindowExA( 0, "MyTestSubclass2", "Scroll", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0 );
+ ok(hwnd != NULL, "Failed to create window: %u\n", GetLastError());
+
+ memset(&scroll_info, 0xcc, sizeof(scroll_info));
+ scroll_info.cbSize = sizeof(scroll_info);
+ res = SendMessageA(hwnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)&scroll_info);
+ ok(!res, "SBM_GETSCROLLBARINFO returned %lu\n", res);
+
+ memset(&set_scrollinfo, 0xcc, sizeof(set_scrollinfo));
+ res = SetScrollPos(hwnd, SB_CTL, 1, FALSE);
+ ok(res == 0, "SetScrollPos returned %lu\n", res);
+ ok(set_scrollinfo.cbSize == sizeof(SCROLLINFO), "cbSize = %u\n", set_scrollinfo.cbSize);
+ todo_wine
+ ok(set_scrollinfo.fMask == (0x1000 | SIF_POS), "fMask = %x\n", set_scrollinfo.fMask);
+ ok(set_scrollinfo.nPos == 1, "nPos = %x\n", set_scrollinfo.nPos);
+
+ DestroyWindow(hwnd);
+}
+
START_TEST ( scroll )
{
WNDCLASSA wc;
test_GetScrollBarInfo();
scrollbar_test_track();
test_SetScrollInfo();
+ test_subclass();
/* Some test results vary depending of theming being active or not */
hUxtheme = LoadLibraryA("uxtheme.dll");
static LONG (WINAPI *pChangeDisplaySettingsExA)(LPCSTR, LPDEVMODEA, HWND, DWORD, LPVOID);
static BOOL (WINAPI *pIsProcessDPIAware)(void);
static BOOL (WINAPI *pSetProcessDPIAware)(void);
+static BOOL (WINAPI *pSetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
+static BOOL (WINAPI *pGetProcessDpiAwarenessInternal)(HANDLE,DPI_AWARENESS*);
+static BOOL (WINAPI *pSetProcessDpiAwarenessInternal)(DPI_AWARENESS);
+static UINT (WINAPI *pGetDpiForSystem)(void);
+static UINT (WINAPI *pGetDpiForWindow)(HWND);
+static BOOL (WINAPI *pGetDpiForMonitorInternal)(HMONITOR,UINT,UINT*,UINT*);
+static DPI_AWARENESS_CONTEXT (WINAPI *pGetThreadDpiAwarenessContext)(void);
+static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
+static DPI_AWARENESS_CONTEXT (WINAPI *pGetWindowDpiAwarenessContext)(HWND);
+static DPI_AWARENESS (WINAPI *pGetAwarenessFromDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
+static BOOL (WINAPI *pIsValidDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
+static INT (WINAPI *pGetSystemMetricsForDpi)(INT,UINT);
+static BOOL (WINAPI *pSystemParametersInfoForDpi)(UINT,UINT,void*,UINT,UINT);
+static BOOL (WINAPI *pAdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
+static BOOL (WINAPI *pLogicalToPhysicalPointForPerMonitorDPI)(HWND,POINT*);
+static BOOL (WINAPI *pPhysicalToLogicalPointForPerMonitorDPI)(HWND,POINT*);
static LONG (WINAPI *pGetAutoRotationState)(PAR_STATE);
static BOOL strict;
static int dpi, real_dpi;
-static BOOL iswin9x;
-static HDC hdc;
#define eq(received, expected, label, type) \
ok((received) == (expected), "%s: got " type " instead of " type "\n", (label),(received),(expected))
{
DWORD dpi;
+ if (pSetThreadDpiAwarenessContext)
+ {
+ DPI_AWARENESS_CONTEXT context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
+ dpi = pGetDpiForSystem();
+ pSetThreadDpiAwarenessContext( context );
+ return dpi;
+ }
if (get_reg_dword(HKEY_CURRENT_USER, "Control Panel\\Desktop", "LogPixels", &dpi))
return dpi;
if (get_reg_dword(HKEY_CURRENT_CONFIG, "Software\\Fonts", "LogPixels", &dpi))
BOOL rc;
INT mi[3];
static int aw_turn = 0;
- static BOOL w_implemented = TRUE;
char buf[20];
int i;
aw_turn++;
rc = FALSE;
- if ((aw_turn % 2!=0) && (w_implemented))
- {
- /* call unicode on odd (non even) calls */
- SetLastError(0xdeadbeef);
+ SetLastError(0xdeadbeef);
+ if (aw_turn % 2) /* call unicode on odd (non even) calls */
rc=SystemParametersInfoW( SPI_SETMOUSE, 0, curr_val, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
- if (rc == FALSE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
- {
- w_implemented = FALSE;
- trace("SystemParametersInfoW not supported on this platform\n");
- }
- }
-
- if ((aw_turn % 2==0) || (!w_implemented))
- {
- /* call ascii version on even calls or if unicode is not available */
+ else
rc=SystemParametersInfoA( SPI_SETMOUSE, 0, curr_val, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
- }
if (!test_error_msg(rc,"SPI_SETMOUSE")) return FALSE;
ok(rc, "SystemParametersInfo: rc=%d err=%d\n", rc, GetLastError());
"incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
}
- if (w_implemented)
- {
- rc=SystemParametersInfoW( SPI_GETMOUSE, 0, mi, 0 );
- ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
- for (i = 0; i < 3; i++)
- {
- ok(mi[i] == curr_val[i],
- "incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
- }
+ rc=SystemParametersInfoW( SPI_GETMOUSE, 0, mi, 0 );
+ ok(rc, "SystemParametersInfoW: rc=%d err=%d\n", rc, GetLastError());
+ for (i = 0; i < 3; i++)
+ {
+ ok(mi[i] == curr_val[i],
+ "incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
}
if (0)
POINT proj_change7[] = { {6, 6}, {14, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
POINT proj_change8[] = { {6, 6}, {28, 6}, {32, 6}, {40, 40}, {44, 40}, {400, 400} };
- int nchange = sizeof( req_change ) / sizeof( POINT );
+ int nchange = ARRAY_SIZE(req_change);
trace("testing SPI_{GET,SET}MOUSE\n");
SetLastError(0xdeadbeef);
if ( old_border == 7 || old_border == 20 )
old_border = 1;
- /* The SPI_SETBORDER seems to be buggy on Win9x/ME (looks like you need to
- * do it twice to make the intended change). So skip parts of the tests on
- * those platforms */
- if( !iswin9x) {
- /* win2k3 fails if you set the same border twice, or if size is 0 */
- if (!test_setborder(2, 1, dpi)) return;
- test_setborder(1, 1, dpi);
- test_setborder(3, 1, dpi);
- }
+ /* win2k3 fails if you set the same border twice, or if size is 0 */
+ if (!test_setborder(2, 1, dpi)) return;
+ test_setborder(1, 1, dpi);
+ test_setborder(3, 1, dpi);
if (!test_setborder(1, 0, dpi)) return;
test_setborder(0, 0, dpi);
test_setborder(3, 0, dpi);
if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDSPEED"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
char buf[10];
if (!test_error_msg(rc,"SPI_{GET,SET}SCREENSAVETIMEOUT"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
char buf[10];
if (!test_error_msg(rc,"SPI_{GET,SET}SCREENSAVEACTIVE"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDDELAY"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT delay;
char buf[10];
if (!test_error_msg(rc,"SPI_{GET,SET}ICONTITLEWRAP"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
UINT regval;
if( regval != vals[i])
regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1,
SPI_SETICONTITLEWRAP_VALNAME, dpi);
- ok( regval == vals[i] || broken(regval == -1), /* win9x */
- "wrong value in registry %d, expected %d\n", regval, vals[i] );
+ ok( regval == vals[i], "wrong value in registry %d, expected %d\n", regval, vals[i] );
rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &v, 0 );
ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
if (!test_error_msg(rc,"SPI_{GET,SET}MENUDROPALIGNMENT"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
trace("testing SPI_{GET,SET}DOUBLECLKWIDTH\n");
old_width = GetSystemMetrics( SM_CXDOUBLECLK );
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
char buf[10];
trace("testing SPI_{GET,SET}DOUBLECLKHEIGHT\n");
old_height = GetSystemMetrics( SM_CYDOUBLECLK );
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
char buf[10];
trace("testing SPI_{GET,SET}MOUSEBUTTONSWAP\n");
old_b = GetSystemMetrics( SM_SWAPBUTTON );
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
SetLastError(0xdeadbeef);
rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, vals[i], 0,
if (!test_error_msg(rc,"SPI_{GET,SET}DRAGFULLWINDOWS"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
ok(rc, "***warning*** failed to restore the original value: rc=%d err=%d\n", rc, GetLastError());
}
-#define test_reg_metric( KEY, VAL, val) \
-{ INT regval;\
+#define test_reg_metric( KEY, VAL, val) do { \
+ INT regval;\
regval = metricfromreg( KEY, VAL, dpi);\
ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
-}
-
-#define test_reg_metric2( KEY1, KEY2, VAL, val) \
-{ INT regval;\
+} while(0)
+
+#define test_reg_metric2( KEY1, KEY2, VAL, val) do { \
+ INT regval;\
regval = metricfromreg( KEY1, VAL, dpi);\
if( regval != val) regval = metricfromreg( KEY2, VAL, dpi);\
ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
-}
+} while(0)
-#define test_reg_font( KEY, VAL, LF) \
-{ LOGFONTA lfreg;\
+#define test_reg_font( KEY, VAL, LF) do { \
+ LOGFONTA lfreg;\
lffromreg( KEY, VAL, &lfreg);\
ok( (lfreg.lfHeight < 0 ? (LF).lfHeight == MulDiv( lfreg.lfHeight, dpi, real_dpi ) : \
MulDiv( -(LF).lfHeight , 72, dpi) == lfreg.lfHeight )&&\
(LF).lfWeight == lfreg.lfWeight &&\
!strcmp( (LF).lfFaceName, lfreg.lfFaceName)\
, "wrong value \"%s\" in registry %d, %d\n", VAL, (LF).lfHeight, lfreg.lfHeight);\
-}
+} while(0)
-#define TEST_NONCLIENTMETRICS_REG( ncm) \
+#define TEST_NONCLIENTMETRICS_REG( ncm) do { \
/*FIXME: test_reg_metric2( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, (ncm).iBorderWidth);*/\
test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLWIDTH_VALNAME, (ncm).iScrollWidth);\
test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLHEIGHT_VALNAME, (ncm).iScrollHeight);\
test_reg_font( SPI_METRIC_REGKEY, SPI_CAPTIONFONT_VALNAME, (ncm).lfCaptionFont);\
test_reg_font( SPI_METRIC_REGKEY, SPI_SMCAPTIONFONT_VALNAME, (ncm).lfSmCaptionFont);\
test_reg_font( SPI_METRIC_REGKEY, SPI_STATUSFONT_VALNAME, (ncm).lfStatusFont);\
-test_reg_font( SPI_METRIC_REGKEY, SPI_MESSAGEFONT_VALNAME, (ncm).lfMessageFont);
+test_reg_font( SPI_METRIC_REGKEY, SPI_MESSAGEFONT_VALNAME, (ncm).lfMessageFont); } while(0)
/* get text metric height value for the specified logfont */
static int get_tmheight( LOGFONTA *plf, int flag)
{
TEXTMETRICA tm;
+ HDC hdc = GetDC(0);
HFONT hfont = CreateFontIndirectA( plf);
hfont = SelectObject( hdc, hfont);
GetTextMetricsA( hdc, &tm);
hfont = SelectObject( hdc, hfont);
+ ReleaseDC( 0, hdc );
+ return tm.tmHeight + (flag ? tm.tmExternalLeading : 0);
+}
+
+static int get_tmheightW( LOGFONTW *plf, int flag)
+{
+ TEXTMETRICW tm;
+ HDC hdc = GetDC(0);
+ HFONT hfont = CreateFontIndirectW( plf);
+ hfont = SelectObject( hdc, hfont);
+ GetTextMetricsW( hdc, &tm);
+ hfont = SelectObject( hdc, hfont);
+ ReleaseDC( 0, hdc );
return tm.tmHeight + (flag ? tm.tmExternalLeading : 0);
}
Ncmorig.iSmCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, dpi);
Ncmorig.iMenuHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, dpi);
/* test registry entries */
- TEST_NONCLIENTMETRICS_REG( Ncmorig)
- Ncmorig.lfCaptionFont.lfHeight = MulDiv( Ncmorig.lfCaptionFont.lfHeight, real_dpi, dpi );
+ TEST_NONCLIENTMETRICS_REG( Ncmorig);
/* make small changes */
Ncmnew = Ncmstart;
rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmcur, FALSE );
ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
/* test registry entries */
- TEST_NONCLIENTMETRICS_REG( Ncmcur)
+ TEST_NONCLIENTMETRICS_REG( Ncmcur );
/* test the system metrics with these settings */
test_GetSystemMetrics();
/* now for something invalid: increase the {menu|caption|smcaption} fonts
ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
/* raw values are in registry */
- TEST_NONCLIENTMETRICS_REG( Ncmnew)
+ TEST_NONCLIENTMETRICS_REG( Ncmnew );
/* get them back */
rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSA), &Ncmcur, FALSE );
ok(rc, "SystemParametersInfoA: rc=%d err=%d\n", rc, GetLastError());
return;
/* check some registry values */
regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
- ok( regval==im_orig.iHorzSpacing || broken(regval == -1), /* nt4 */
+ ok( regval==im_orig.iHorzSpacing,
"wrong value in registry %d, expected %d\n", regval, im_orig.iHorzSpacing);
regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
- ok( regval==im_orig.iVertSpacing || broken(regval == -1), /* nt4 */
+ ok( regval==im_orig.iVertSpacing,
"wrong value in registry %d, expected %d\n", regval, im_orig.iVertSpacing);
regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
if( regval != im_orig.iTitleWrap)
trace("testing SPI_{GET,SET}SHOWSOUNDS\n");
SetLastError(0xdeadbeef);
rc=SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &old_b, 0 );
- /* SPI_{GET,SET}SHOWSOUNDS is completely broken on Win9x */
if (!test_error_msg(rc,"SPI_{GET,SET}SHOWSOUNDS"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
if (!test_error_msg(rc,"SPI_{GET,SET}KEYBOARDPREF"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
BOOL v;
if (!test_error_msg(rc,"SPI_{GET,SET}SCREENREADER"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
BOOL v;
unsigned int i;
trace("testing SPI_{GET,SET}FONTSMOOTHING\n");
- if( iswin9x) return; /* 95/98/ME don't seem to implement this fully */
SetLastError(0xdeadbeef);
rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &old_b, 0 );
if (!test_error_msg(rc,"SPI_{GET,SET}FONTSMOOTHING"))
SystemParametersInfoA( SPI_GETFONTSMOOTHINGCONTRAST, 0, &old_contrast, 0 );
SystemParametersInfoA( SPI_GETFONTSMOOTHINGORIENTATION, 0, &old_orient, 0 );
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
if (!test_error_msg(rc,"SPI_{GET,SET}LOWPOWERACTIVE"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
v = 0xdeadbeef;
rc=SystemParametersInfoA( SPI_GETLOWPOWERACTIVE, 0, &v, 0 );
ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
- ok(v == vals[i] ||
- broken(v == (0xdead0000 | vals[i])) || /* win98 only sets the low word */
- v == 0, /* win2k3 */
+ ok(v == vals[i] || v == 0, /* win2k3 */
"SPI_GETLOWPOWERACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
}
if (!test_error_msg(rc,"SPI_{GET,SET}POWEROFFACTIVE"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
v = 0xdeadbeef;
rc=SystemParametersInfoA( SPI_GETPOWEROFFACTIVE, 0, &v, 0 );
ok(rc, "%d: rc=%d err=%d\n", i, rc, GetLastError());
- ok(v == vals[i] ||
- broken(v == (0xdead0000 | vals[i])) || /* win98 only sets the low word */
- v == 0, /* win2k3 */
+ ok(v == vals[i] || v == 0, /* win2k3 */
"SPI_GETPOWEROFFACTIVE: got %d instead of 0 or %d\n", v, vals[i]);
}
if (!test_error_msg(rc,"SPI_GETSNAPTODEFBUTTON"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
trace("testing SPI_{GET,SET}MOUSEHOVERWIDTH\n");
SetLastError(0xdeadbeef);
rc=SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &old_width, 0 );
- /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
- * what MSDN states (Verified on Win98SE)
- */
if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERWIDTH"))
return;
-
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
char buf[10];
trace("testing SPI_{GET,SET}MOUSEHOVERHEIGHT\n");
SetLastError(0xdeadbeef);
rc=SystemParametersInfoA( SPI_GETMOUSEHOVERHEIGHT, 0, &old_height, 0 );
- /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
- * what MSDN states (Verified on Win98SE)
- */
if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERHEIGHT"))
return;
-
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
char buf[10];
trace("testing SPI_{GET,SET}MOUSEHOVERTIME\n");
SetLastError(0xdeadbeef);
rc=SystemParametersInfoA( SPI_GETMOUSEHOVERTIME, 0, &old_time, 0 );
- /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite
- * what MSDN states (Verified on Win98SE)
- */
if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEHOVERTIME"))
return;
-
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
char buf[10];
if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLLINES"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
char buf[10];
if (!test_error_msg(rc,"SPI_{GET,SET}MENUSHOWDELAY"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
char buf[10];
if (!test_error_msg(rc,"SPI_{GET,SET}WHEELSCROLLCHARS"))
return;
- for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+ for (i=0;i<ARRAY_SIZE(vals);i++)
{
UINT v;
char buf[10];
trace("testing SPI_{GET,SET}DESKWALLPAPER\n");
SetLastError(0xdeadbeef);
rc=SystemParametersInfoA(SPI_GETDESKWALLPAPER, 260, oldval, 0);
- /* SPI_{GET,SET}DESKWALLPAPER is completely broken on Win9x and
- * unimplemented on NT4
- */
if (!test_error_msg(rc,"SPI_{GET,SET}DESKWALLPAPER"))
return;
displaychange_sem = CreateSemaphoreW(NULL, 0, 1, NULL);
- for(i = 0; i < sizeof(test_bpps)/sizeof(test_bpps[0]); i++) {
+ for(i = 0; i < ARRAY_SIZE(test_bpps); i++) {
last_bpp = -1;
memset(&mode, 0, sizeof(mode));
ncm.cbSize = sizeof(ncm); /* Vista added padding */
SetLastError(0xdeadbeef);
+ ncm.iPaddedBorderWidth = 0xcccc;
rc = SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
ok(rc || broken(!rc) /* before Vista */, "SystemParametersInfoA failed\n");
+ if (rc) ok( ncm.iPaddedBorderWidth == 0, "wrong iPaddedBorderWidth %u\n", ncm.iPaddedBorderWidth );
minim.cbSize = sizeof( minim);
ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, iPaddedBorderWidth);
DeleteDC(hdc);
}
+static void compare_font( const LOGFONTW *lf1, const LOGFONTW *lf2, int dpi, int custom_dpi, int line )
+{
+ ok_(__FILE__,line)( lf1->lfHeight == MulDiv( lf2->lfHeight, dpi, custom_dpi ),
+ "wrong lfHeight %d vs %d\n", lf1->lfHeight, lf2->lfHeight );
+ ok_(__FILE__,line)( abs( lf1->lfWidth - MulDiv( lf2->lfWidth, dpi, custom_dpi )) <= 1,
+ "wrong lfWidth %d vs %d\n", lf1->lfWidth, lf2->lfWidth );
+ ok_(__FILE__,line)( !memcmp( &lf1->lfEscapement, &lf2->lfEscapement,
+ offsetof( LOGFONTW, lfFaceName ) - offsetof( LOGFONTW, lfEscapement )),
+ "font differs\n" );
+ ok_(__FILE__,line)( !lstrcmpW( lf1->lfFaceName, lf2->lfFaceName ), "wrong face name %s vs %s\n",
+ wine_dbgstr_w( lf1->lfFaceName ), wine_dbgstr_w( lf2->lfFaceName ));
+}
+
+static void test_metrics_for_dpi( int custom_dpi )
+{
+ int i, val;
+ NONCLIENTMETRICSW ncm1, ncm2;
+ ICONMETRICSW im1, im2;
+ LOGFONTW lf1, lf2;
+ BOOL ret;
+
+ if (!pSystemParametersInfoForDpi)
+ {
+ win_skip( "custom dpi metrics not supported\n" );
+ return;
+ }
+
+ ncm1.cbSize = sizeof(ncm1);
+ ret = SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof(ncm1), &ncm1, FALSE );
+ ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() );
+ ncm2.cbSize = sizeof(ncm2);
+ ret = pSystemParametersInfoForDpi( SPI_GETNONCLIENTMETRICS, sizeof(ncm2), &ncm2, FALSE, custom_dpi );
+ ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() );
+
+ for (i = 0; i < 92; i++)
+ {
+ int ret1 = GetSystemMetrics( i );
+ int ret2 = pGetSystemMetricsForDpi( i, custom_dpi );
+ switch (i)
+ {
+ case SM_CXVSCROLL:
+ case SM_CYHSCROLL:
+ case SM_CYVTHUMB:
+ case SM_CXHTHUMB:
+ case SM_CXICON:
+ case SM_CYICON:
+ case SM_CYVSCROLL:
+ case SM_CXHSCROLL:
+ case SM_CYSIZE:
+ case SM_CXICONSPACING:
+ case SM_CYICONSPACING:
+ case SM_CXSMSIZE:
+ case SM_CYSMSIZE:
+ case SM_CYMENUSIZE:
+ ok( ret1 == MulDiv( ret2, dpi, custom_dpi ), "%u: wrong value %u vs %u\n", i, ret1, ret2 );
+ break;
+ case SM_CXSIZE:
+ ok( ret1 == ncm1.iCaptionWidth && ret2 == ncm2.iCaptionWidth,
+ "%u: wrong value %u vs %u caption %u vs %u\n",
+ i, ret1, ret2, ncm1.iCaptionWidth, ncm2.iCaptionWidth );
+ break;
+ case SM_CXCURSOR:
+ case SM_CYCURSOR:
+ val = MulDiv( 32, custom_dpi, USER_DEFAULT_SCREEN_DPI );
+ if (val < 48) val = 32;
+ else if (val < 64) val = 48;
+ else val = 64;
+ ok( val == ret2, "%u: wrong value %u vs %u\n", i, ret1, ret2 );
+ break;
+ case SM_CYCAPTION:
+ case SM_CYSMCAPTION:
+ case SM_CYMENU:
+ ok( ret1 - 1 == MulDiv( ret2 - 1, dpi, custom_dpi ), "%u: wrong value %u vs %u\n", i, ret1, ret2 );
+ break;
+ case SM_CXMENUSIZE:
+ ok( ret1 / 8 == MulDiv( ret2, dpi, custom_dpi ) / 8, "%u: wrong value %u vs %u\n", i, ret1, ret2 );
+ break;
+ case SM_CXFRAME:
+ case SM_CYFRAME:
+ ok( ret1 == ncm1.iBorderWidth + 3 && ret2 == ncm2.iBorderWidth + 3,
+ "%u: wrong value %u vs %u borders %u+%u vs %u+%u\n", i, ret1, ret2,
+ ncm1.iBorderWidth, ncm1.iPaddedBorderWidth, ncm2.iBorderWidth, ncm2.iPaddedBorderWidth );
+ break;
+ case SM_CXSMICON:
+ case SM_CYSMICON:
+ ok( ret1 == (MulDiv( 16, dpi, USER_DEFAULT_SCREEN_DPI ) & ~1) &&
+ ret2 == (MulDiv( 16, custom_dpi, USER_DEFAULT_SCREEN_DPI ) & ~1),
+ "%u: wrong value %u vs %u\n", i, ret1, ret2 );
+ break;
+ case SM_CXMENUCHECK:
+ case SM_CYMENUCHECK:
+ ok( ret1 == ((get_tmheightW( &ncm1.lfMenuFont, 1 ) - 1) | 1) &&
+ ret2 == ((get_tmheightW( &ncm2.lfMenuFont, 1 ) - 1) | 1),
+ "%u: wrong value %u vs %u font %u vs %u\n", i, ret1, ret2,
+ get_tmheightW( &ncm1.lfMenuFont, 1 ), get_tmheightW( &ncm2.lfMenuFont, 1 ));
+ break;
+ default:
+ ok( ret1 == ret2, "%u: wrong value %u vs %u\n", i, ret1, ret2 );
+ break;
+ }
+ }
+ im1.cbSize = sizeof(im1);
+ ret = SystemParametersInfoW( SPI_GETICONMETRICS, sizeof(im1), &im1, FALSE );
+ ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() );
+ im2.cbSize = sizeof(im2);
+ ret = pSystemParametersInfoForDpi( SPI_GETICONMETRICS, sizeof(im2), &im2, FALSE, custom_dpi );
+ ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() );
+ ok( im1.iHorzSpacing == MulDiv( im2.iHorzSpacing, dpi, custom_dpi ), "wrong iHorzSpacing %u vs %u\n",
+ im1.iHorzSpacing, im2.iHorzSpacing );
+ ok( im1.iVertSpacing == MulDiv( im2.iVertSpacing, dpi, custom_dpi ), "wrong iVertSpacing %u vs %u\n",
+ im1.iVertSpacing, im2.iVertSpacing );
+ ok( im1.iTitleWrap == im2.iTitleWrap, "wrong iTitleWrap %u vs %u\n",
+ im1.iTitleWrap, im2.iTitleWrap );
+ compare_font( &im1.lfFont, &im2.lfFont, dpi, custom_dpi, __LINE__ );
+
+ ret = SystemParametersInfoW( SPI_GETICONTITLELOGFONT, sizeof(lf1), &lf1, FALSE );
+ ok( ret, "SystemParametersInfoW failed err %u\n", GetLastError() );
+ ret = pSystemParametersInfoForDpi( SPI_GETICONTITLELOGFONT, sizeof(lf2), &lf2, FALSE, custom_dpi );
+ ok( ret, "SystemParametersInfoForDpi failed err %u\n", GetLastError() );
+ compare_font( &lf1, &lf2, dpi, custom_dpi, __LINE__ );
+
+ /* on high-dpi iPaddedBorderWidth is used in addition to iBorderWidth */
+ ok( ncm1.iBorderWidth + ncm1.iPaddedBorderWidth == MulDiv( ncm2.iBorderWidth + ncm2.iPaddedBorderWidth, dpi, custom_dpi ),
+ "wrong iBorderWidth %u+%u vs %u+%u\n",
+ ncm1.iBorderWidth, ncm1.iPaddedBorderWidth, ncm2.iBorderWidth, ncm2.iPaddedBorderWidth );
+ ok( ncm1.iScrollWidth == MulDiv( ncm2.iScrollWidth, dpi, custom_dpi ),
+ "wrong iScrollWidth %u vs %u\n", ncm1.iScrollWidth, ncm2.iScrollWidth );
+ ok( ncm1.iScrollHeight == MulDiv( ncm2.iScrollHeight, dpi, custom_dpi ),
+ "wrong iScrollHeight %u vs %u\n", ncm1.iScrollHeight, ncm2.iScrollHeight );
+ ok( ((ncm1.iCaptionWidth + 1) & ~1) == ((MulDiv( ncm2.iCaptionWidth, dpi, custom_dpi ) + 1) & ~1),
+ "wrong iCaptionWidth %u vs %u\n", ncm1.iCaptionWidth, ncm2.iCaptionWidth );
+ ok( ncm1.iCaptionHeight == MulDiv( ncm2.iCaptionHeight, dpi, custom_dpi ),
+ "wrong iCaptionHeight %u vs %u\n", ncm1.iCaptionHeight, ncm2.iCaptionHeight );
+ compare_font( &ncm1.lfCaptionFont, &ncm2.lfCaptionFont, dpi, custom_dpi, __LINE__ );
+ ok( ncm1.iSmCaptionHeight == MulDiv( ncm2.iSmCaptionHeight, dpi, custom_dpi ),
+ "wrong iSmCaptionHeight %u vs %u\n", ncm1.iSmCaptionHeight, ncm2.iSmCaptionHeight );
+ compare_font( &ncm1.lfSmCaptionFont, &ncm2.lfSmCaptionFont, dpi, custom_dpi, __LINE__ );
+ ok( ncm1.iMenuHeight == MulDiv( ncm2.iMenuHeight, dpi, custom_dpi ),
+ "wrong iMenuHeight %u vs %u\n", ncm1.iMenuHeight, ncm2.iMenuHeight );
+ /* iSmCaptionWidth and iMenuWidth apparently need to be multiples of 8 */
+ ok( ncm1.iSmCaptionWidth / 8 == MulDiv( ncm2.iSmCaptionWidth, dpi, custom_dpi ) / 8,
+ "wrong iSmCaptionWidth %u vs %u\n", ncm1.iSmCaptionWidth, ncm2.iSmCaptionWidth );
+ ok( ncm1.iMenuWidth / 8 == MulDiv( ncm2.iMenuWidth, dpi, custom_dpi ) / 8,
+ "wrong iMenuWidth %u vs %u\n", ncm1.iMenuWidth, ncm2.iMenuWidth );
+ compare_font( &ncm1.lfMenuFont, &ncm2.lfMenuFont, dpi, custom_dpi, __LINE__ );
+ compare_font( &ncm1.lfStatusFont, &ncm2.lfStatusFont, dpi, custom_dpi, __LINE__ );
+ compare_font( &ncm1.lfMessageFont, &ncm2.lfMessageFont, dpi, custom_dpi, __LINE__ );
+
+ for (i = 1; i < 120; i++)
+ {
+ if (i == SPI_GETICONTITLELOGFONT || i == SPI_GETNONCLIENTMETRICS || i == SPI_GETICONMETRICS)
+ continue;
+ SetLastError( 0xdeadbeef );
+ ret = pSystemParametersInfoForDpi( i, 0, &val, 0, custom_dpi );
+ ok( !ret, "%u: SystemParametersInfoForDpi succeeded\n", i );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER, "%u: wrong error %u\n", i, GetLastError() );
+ }
+}
+
static void test_EnumDisplaySettings(void)
{
DEVMODEA devmode;
DWORD num;
memset(&devmode, 0, sizeof(devmode));
- /* Win95 doesn't handle ENUM_CURRENT_SETTINGS correctly */
EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &devmode);
hdc = GetDC(0);
val = GetDeviceCaps(hdc, BITSPIXEL);
- ok(devmode.dmBitsPerPel == val ||
- broken(devmode.dmDeviceName[0] == 0), /* Win95 */
+ ok(devmode.dmBitsPerPel == val,
"GetDeviceCaps(BITSPIXEL) returned %d, EnumDisplaySettings returned %d\n",
val, devmode.dmBitsPerPel);
win_skip("COLOR_MENUBAR unsupported\n");
}
+static void test_dpi_stock_objects( HDC hdc )
+{
+ DPI_AWARENESS_CONTEXT context;
+ HGDIOBJ obj[STOCK_LAST + 1], obj2[STOCK_LAST + 1];
+ LOGFONTW lf, lf2;
+ UINT i, dpi;
+
+ context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
+ dpi = GetDeviceCaps( hdc, LOGPIXELSX );
+ ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
+ ok( !pIsProcessDPIAware(), "not aware\n" );
+ for (i = 0; i <= STOCK_LAST; i++) obj[i] = GetStockObject( i );
+
+ pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
+ dpi = GetDeviceCaps( hdc, LOGPIXELSX );
+ ok( dpi == real_dpi, "wrong dpi %u\n", dpi );
+ ok( pIsProcessDPIAware(), "not aware\n" );
+ for (i = 0; i <= STOCK_LAST; i++) obj2[i] = GetStockObject( i );
+
+ for (i = 0; i <= STOCK_LAST; i++)
+ {
+ switch (i)
+ {
+ case OEM_FIXED_FONT:
+ case SYSTEM_FIXED_FONT:
+ ok( obj[i] != obj2[i], "%u: same object\n", i );
+ break;
+ case SYSTEM_FONT:
+ case DEFAULT_GUI_FONT:
+ ok( obj[i] != obj2[i], "%u: same object\n", i );
+ GetObjectW( obj[i], sizeof(lf), &lf );
+ GetObjectW( obj2[i], sizeof(lf2), &lf2 );
+ ok( lf.lfHeight == MulDiv( lf2.lfHeight, USER_DEFAULT_SCREEN_DPI, real_dpi ),
+ "%u: wrong height %d / %d\n", i, lf.lfHeight, lf2.lfHeight );
+ break;
+ default:
+ ok( obj[i] == obj2[i], "%u: different object\n", i );
+ break;
+ }
+ }
+
+ pSetThreadDpiAwarenessContext( context );
+}
+
+static void scale_point_dpi( POINT *pt, UINT src_dpi, UINT target_dpi )
+{
+ pt->x = MulDiv( pt->x, target_dpi, src_dpi );
+ pt->y = MulDiv( pt->y, target_dpi, src_dpi );
+}
+
+static void scale_rect_dpi( RECT *rect, UINT src_dpi, UINT target_dpi )
+{
+ rect->left = MulDiv( rect->left, target_dpi, src_dpi );
+ rect->top = MulDiv( rect->top, target_dpi, src_dpi );
+ rect->right = MulDiv( rect->right, target_dpi, src_dpi );
+ rect->bottom = MulDiv( rect->bottom, target_dpi, src_dpi );
+}
+
+static void scale_point_dpi_aware( POINT *pt, DPI_AWARENESS from, DPI_AWARENESS to )
+{
+ if (from == DPI_AWARENESS_UNAWARE && to != DPI_AWARENESS_UNAWARE)
+ scale_point_dpi( pt, USER_DEFAULT_SCREEN_DPI, real_dpi );
+ else if (from != DPI_AWARENESS_UNAWARE && to == DPI_AWARENESS_UNAWARE)
+ scale_point_dpi( pt, real_dpi, USER_DEFAULT_SCREEN_DPI );
+}
+
+static void scale_rect_dpi_aware( RECT *rect, DPI_AWARENESS from, DPI_AWARENESS to )
+{
+ if (from == DPI_AWARENESS_UNAWARE && to != DPI_AWARENESS_UNAWARE)
+ scale_rect_dpi( rect, USER_DEFAULT_SCREEN_DPI, real_dpi );
+ else if (from != DPI_AWARENESS_UNAWARE && to == DPI_AWARENESS_UNAWARE)
+ scale_rect_dpi( rect, real_dpi, USER_DEFAULT_SCREEN_DPI );
+}
+
+static void test_dpi_mapping(void)
+{
+ HWND hwnd, child;
+ HDC hdc;
+ UINT win_dpi, units;
+ POINT point;
+ BOOL ret;
+ HRGN rgn, update;
+ RECT rect, orig, client, desktop, expect;
+ ULONG_PTR i, j, k;
+ WINDOWPLACEMENT wpl_orig, wpl;
+ HMONITOR monitor;
+ MONITORINFO mon_info;
+ DPI_AWARENESS_CONTEXT context;
+
+ if (!pLogicalToPhysicalPointForPerMonitorDPI)
+ {
+ win_skip( "LogicalToPhysicalPointForPerMonitorDPI not supported\n" );
+ return;
+ }
+ context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
+ GetWindowRect( GetDesktopWindow(), &desktop );
+ for (i = DPI_AWARENESS_UNAWARE; i <= DPI_AWARENESS_PER_MONITOR_AWARE; i++)
+ {
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i );
+ /* test desktop rect */
+ GetWindowRect( GetDesktopWindow(), &rect );
+ expect = desktop;
+ if (i == DPI_AWARENESS_UNAWARE) scale_rect_dpi( &expect, real_dpi, USER_DEFAULT_SCREEN_DPI );
+ ok( EqualRect( &expect, &rect ), "%lu: wrong desktop rect %s expected %s\n",
+ i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ SetRect( &rect, 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ));
+ ok( EqualRect( &expect, &rect ), "%lu: wrong desktop rect %s expected %s\n",
+ i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ SetRect( &rect, 0, 0, GetSystemMetrics( SM_CXVIRTUALSCREEN ), GetSystemMetrics( SM_CYVIRTUALSCREEN ));
+ ok( EqualRect( &expect, &rect ), "%lu: wrong virt desktop rect %s expected %s\n",
+ i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ SetRect( &rect, 0, 0, 1, 1 );
+ monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY );
+ ok( monitor != 0, "failed to get monitor\n" );
+ mon_info.cbSize = sizeof(mon_info);
+ ok( GetMonitorInfoW( monitor, &mon_info ), "GetMonitorInfoExW failed\n" );
+ ok( EqualRect( &expect, &mon_info.rcMonitor ), "%lu: wrong monitor rect %s expected %s\n",
+ i, wine_dbgstr_rect(&mon_info.rcMonitor), wine_dbgstr_rect(&expect) );
+ hdc = CreateDCA( "display", NULL, NULL, NULL );
+ SetRect( &rect, 0, 0, GetDeviceCaps( hdc, HORZRES ), GetDeviceCaps( hdc, VERTRES ));
+ ok( EqualRect( &expect, &rect ), "%lu: wrong caps desktop rect %s expected %s\n",
+ i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ SetRect( &rect, 0, 0, GetDeviceCaps( hdc, DESKTOPHORZRES ), GetDeviceCaps( hdc, DESKTOPVERTRES ));
+ ok( EqualRect( &desktop, &rect ), "%lu: wrong caps virt desktop rect %s expected %s\n",
+ i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&desktop) );
+ DeleteDC( hdc );
+ /* test message window rect */
+ hwnd = CreateWindowA( "SysParamsTestClass", "test", WS_CHILD,
+ 10, 10, 20, 20, HWND_MESSAGE, 0, GetModuleHandleA(0), NULL );
+ GetWindowRect( GetAncestor( hwnd, GA_PARENT ), &rect );
+ SetRect( &expect, 0, 0, 100, 100 );
+ if (i == DPI_AWARENESS_UNAWARE) scale_rect_dpi( &expect, real_dpi, USER_DEFAULT_SCREEN_DPI );
+ ok( EqualRect( &expect, &rect ), "%lu: wrong message rect %s expected %s\n",
+ i, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ DestroyWindow( hwnd );
+ }
+ for (i = DPI_AWARENESS_UNAWARE; i <= DPI_AWARENESS_PER_MONITOR_AWARE; i++)
+ {
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i );
+ hwnd = CreateWindowA( "SysParamsTestClass", "test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ 193, 177, 295, 303, 0, 0, GetModuleHandleA(0), NULL );
+ ok( hwnd != 0, "creating window failed err %u\n", GetLastError());
+ child = CreateWindowA( "SysParamsTestClass", "child", WS_CHILD | WS_VISIBLE,
+ 50, 60, 70, 80, hwnd, 0, GetModuleHandleA(0), NULL );
+ ok( child != 0, "creating child failed err %u\n", GetLastError());
+ GetWindowRect( hwnd, &orig );
+ SetRect( &rect, 0, 0, 0, 0 );
+ pAdjustWindowRectExForDpi( &rect, WS_OVERLAPPEDWINDOW, FALSE, 0, pGetDpiForWindow( hwnd ));
+ SetRect( &client, orig.left - rect.left, orig.top - rect.top,
+ orig.right - rect.right, orig.bottom - rect.bottom );
+ ShowWindow( hwnd, SW_MINIMIZE );
+ ShowWindow( hwnd, SW_RESTORE );
+ GetWindowPlacement( hwnd, &wpl_orig );
+ units = GetDialogBaseUnits();
+
+ for (j = DPI_AWARENESS_UNAWARE; j <= DPI_AWARENESS_PER_MONITOR_AWARE; j++)
+ {
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
+ /* test window rect */
+ GetWindowRect( hwnd, &rect );
+ expect = orig;
+ scale_rect_dpi_aware( &expect, i, j );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong window rect %s expected %s\n",
+ i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ /* test client rect */
+ GetClientRect( hwnd, &rect );
+ expect = client;
+ OffsetRect( &expect, -expect.left, -expect.top );
+ scale_rect_dpi_aware( &expect, i, j );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong client rect %s expected %s\n",
+ i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ /* test window placement */
+ GetWindowPlacement( hwnd, &wpl );
+ point = wpl_orig.ptMinPosition;
+ if (point.x != -1 || point.y != -1) scale_point_dpi_aware( &point, i, j );
+ ok( wpl.ptMinPosition.x == point.x && wpl.ptMinPosition.y == point.y,
+ "%lu/%lu: wrong placement min pos %d,%d expected %d,%d\n", i, j,
+ wpl.ptMinPosition.x, wpl.ptMinPosition.y, point.x, point.y );
+ point = wpl_orig.ptMaxPosition;
+ if (point.x != -1 || point.y != -1) scale_point_dpi_aware( &point, i, j );
+ ok( wpl.ptMaxPosition.x == point.x && wpl.ptMaxPosition.y == point.y,
+ "%lu/%lu: wrong placement max pos %d,%d expected %d,%d\n", i, j,
+ wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, point.x, point.y );
+ expect = wpl_orig.rcNormalPosition;
+ scale_rect_dpi_aware( &expect, i, j );
+ ok( EqualRect( &wpl.rcNormalPosition, &expect ),
+ "%lu/%lu: wrong placement rect %s expect %s\n", i, j,
+ wine_dbgstr_rect(&wpl.rcNormalPosition), wine_dbgstr_rect(&expect));
+ /* test DC rect */
+ hdc = GetDC( hwnd );
+ GetClipBox( hdc, &rect );
+ SetRect( &expect, 0, 0, client.right - client.left, client.bottom - client.top );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong clip box %s expected %s\n",
+ i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ /* test DC resolution */
+ SetRect( &rect, 0, 0, GetDeviceCaps( hdc, HORZRES ), GetDeviceCaps( hdc, VERTRES ));
+ expect = desktop;
+ if (j == DPI_AWARENESS_UNAWARE) scale_rect_dpi( &expect, real_dpi, USER_DEFAULT_SCREEN_DPI );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong DC resolution %s expected %s\n",
+ i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ SetRect( &rect, 0, 0, GetDeviceCaps( hdc, DESKTOPHORZRES ), GetDeviceCaps( hdc, DESKTOPVERTRES ));
+ ok( EqualRect( &desktop, &rect ), "%lu/%lu: wrong desktop resolution %s expected %s\n",
+ i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&desktop) );
+ ReleaseDC( hwnd, hdc );
+ /* test DC win rect */
+ hdc = GetWindowDC( hwnd );
+ GetClipBox( hdc, &rect );
+ SetRect( &expect, 0, 0, 295, 303 );
+ todo_wine
+ ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong clip box win DC %s expected %s\n",
+ i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ ReleaseDC( hwnd, hdc );
+ /* test window invalidation */
+ UpdateWindow( hwnd );
+ update = CreateRectRgn( 0, 0, 0, 0 );
+ ret = GetUpdateRgn( hwnd, update, FALSE );
+ ok( ret == NULLREGION, "update region not empty\n" );
+ rgn = CreateRectRgn( 20, 20, 25, 25 );
+ for (k = DPI_AWARENESS_UNAWARE; k <= DPI_AWARENESS_PER_MONITOR_AWARE; k++)
+ {
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~k );
+ RedrawWindow( hwnd, 0, rgn, RDW_INVALIDATE );
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
+ GetUpdateRgn( hwnd, update, FALSE );
+ GetRgnBox( update, &rect );
+ SetRect( &expect, 20, 20, 25, 25 );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update region %s expected %s\n",
+ i, j, k, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ GetUpdateRect( hwnd, &rect, FALSE );
+ scale_rect_dpi_aware( &expect, i, j );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update rect %s expected %s\n",
+ i, j, k, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ UpdateWindow( hwnd );
+ }
+ for (k = DPI_AWARENESS_UNAWARE; k <= DPI_AWARENESS_PER_MONITOR_AWARE; k++)
+ {
+ RedrawWindow( hwnd, 0, rgn, RDW_INVALIDATE );
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~k );
+ GetUpdateRgn( hwnd, update, FALSE );
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
+ GetRgnBox( update, &rect );
+ SetRect( &expect, 20, 20, 25, 25 );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update region %s expected %s\n",
+ i, j, k, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ GetUpdateRect( hwnd, &rect, FALSE );
+ scale_rect_dpi_aware( &expect, i, j );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu/%lu: wrong update rect %s expected %s\n",
+ i, j, k, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ UpdateWindow( hwnd );
+ }
+ /* test desktop window invalidation */
+ pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
+ GetClientRect( hwnd, &rect );
+ InflateRect( &rect, -50, -50 );
+ expect = rect;
+ MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
+ RedrawWindow( 0, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN );
+ GetUpdateRgn( hwnd, update, TRUE );
+ GetRgnBox( update, &rect );
+ if (i == DPI_AWARENESS_UNAWARE) scale_rect_dpi( &expect, real_dpi, USER_DEFAULT_SCREEN_DPI );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong update region %s expected %s\n",
+ i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ GetUpdateRect( hwnd, &rect, FALSE );
+ scale_rect_dpi_aware( &expect, i, j );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong update rect %s expected %s\n",
+ i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ UpdateWindow( hwnd );
+ DeleteObject( update );
+ /* test dialog units */
+ ret = GetDialogBaseUnits();
+ point.x = LOWORD( units );
+ point.y = HIWORD( units );
+ scale_point_dpi_aware( &point, i, j );
+ ok( LOWORD(ret) == point.x && HIWORD(ret) == point.y, "%lu/%lu: wrong units %d,%d / %d,%d\n",
+ i, j, LOWORD(ret), HIWORD(ret), point.x, point.y );
+ /* test window points mapping */
+ SetRect( &rect, 0, 0, 100, 100 );
+ rect.right = rect.left + 100;
+ rect.bottom = rect.top + 100;
+ MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
+ expect = client;
+ scale_rect_dpi_aware( &expect, i, j );
+ expect.right = expect.left + 100;
+ expect.bottom = expect.top + 100;
+ ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong MapWindowPoints rect %s expected %s\n",
+ i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ SetRect( &rect, 50, 60, 70, 80 );
+ scale_rect_dpi_aware( &rect, i, j );
+ SetRect( &expect, 40, 30, 60, 80 );
+ OffsetRect( &expect, -rect.left, -rect.top );
+ SetRect( &rect, 40, 30, 60, 80 );
+ MapWindowPoints( hwnd, child, (POINT *)&rect, 2 );
+ ok( EqualRect( &expect, &rect ), "%lu/%lu: wrong MapWindowPoints child rect %s expected %s\n",
+ i, j, wine_dbgstr_rect(&rect), wine_dbgstr_rect(&expect) );
+ /* test logical<->physical coords mapping */
+ win_dpi = pGetDpiForWindow( hwnd );
+ if (i == DPI_AWARENESS_UNAWARE)
+ ok( win_dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", win_dpi );
+ else if (i == DPI_AWARENESS_SYSTEM_AWARE)
+ ok( win_dpi == real_dpi, "wrong dpi %u / %u\n", win_dpi, real_dpi );
+ point.x = 373;
+ point.y = 377;
+ ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
+ ok( ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI failed\n", i, j );
+ ok( point.x == MulDiv( 373, real_dpi, win_dpi ) &&
+ point.y == MulDiv( 377, real_dpi, win_dpi ),
+ "%lu/%lu: wrong pos %d,%d dpi %u\n", i, j, point.x, point.y, win_dpi );
+ point.x = 405;
+ point.y = 423;
+ ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
+ ok( ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI failed\n", i, j );
+ ok( point.x == MulDiv( 405, win_dpi, real_dpi ) &&
+ point.y == MulDiv( 423, win_dpi, real_dpi ),
+ "%lu/%lu: wrong pos %d,%d dpi %u\n", i, j, point.x, point.y, win_dpi );
+ /* point outside the window fails, but note that Windows (wrongly) checks against the
+ * window rect transformed relative to the thread's awareness */
+ GetWindowRect( hwnd, &rect );
+ point.x = rect.left - 1;
+ point.y = rect.top;
+ ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
+ ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
+ point.x++;
+ point.y--;
+ ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
+ ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
+ point.y++;
+ ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
+ ok( ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI failed\n", i, j );
+ point.x = rect.right;
+ point.y = rect.bottom + 1;
+ ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
+ ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
+ point.x++;
+ point.y--;
+ ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
+ ok( !ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI succeeded\n", i, j );
+ point.x--;
+ ret = pLogicalToPhysicalPointForPerMonitorDPI( hwnd, &point );
+ ok( ret, "%lu/%lu: LogicalToPhysicalPointForPerMonitorDPI failed\n", i, j );
+ /* get physical window rect */
+ pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
+ GetWindowRect( hwnd, &rect );
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
+ point.x = rect.left - 1;
+ point.y = rect.top;
+ ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
+ ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
+ point.x++;
+ point.y--;
+ ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
+ ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
+ point.y++;
+ ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
+ ok( ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI failed\n", i, j );
+ point.x = rect.right;
+ point.y = rect.bottom + 1;
+ ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
+ ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
+ point.x++;
+ point.y--;
+ ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
+ ok( !ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI succeeded\n", i, j );
+ point.x--;
+ ret = pPhysicalToLogicalPointForPerMonitorDPI( hwnd, &point );
+ ok( ret, "%lu/%lu: PhysicalToLogicalPointForPerMonitorDPI failed\n", i, j );
+ }
+ DestroyWindow( hwnd );
+ }
+ pSetThreadDpiAwarenessContext( context );
+}
+
static void test_dpi_aware(void)
{
BOOL ret;
dpi = real_dpi;
test_GetSystemMetrics();
+ test_metrics_for_dpi( 96 );
+ test_metrics_for_dpi( 192 );
+}
+
+static void test_dpi_context(void)
+{
+ DPI_AWARENESS awareness;
+ DPI_AWARENESS_CONTEXT context;
+ ULONG_PTR i, flags;
+ BOOL ret;
+ UINT dpi;
+ HDC hdc = GetDC( 0 );
+
+ context = pGetThreadDpiAwarenessContext();
+ /* Windows 10 >= 1709 adds extra 0x6000 flags */
+ flags = (ULONG_PTR)context & 0x6000;
+ todo_wine
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x10 | flags), "wrong context %p\n", context );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ todo_wine
+ ok( awareness == DPI_AWARENESS_UNAWARE, "wrong awareness %u\n", awareness );
+ todo_wine
+ ok( !pIsProcessDPIAware(), "already aware\n" );
+ dpi = pGetDpiForSystem();
+ todo_wine_if (real_dpi != USER_DEFAULT_SCREEN_DPI)
+ ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
+ dpi = GetDeviceCaps( hdc, LOGPIXELSX );
+ todo_wine_if (real_dpi != USER_DEFAULT_SCREEN_DPI)
+ ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
+ SetLastError( 0xdeadbeef );
+ ret = pSetProcessDpiAwarenessContext( NULL );
+ ok( !ret, "got %d\n", ret );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
+ SetLastError( 0xdeadbeef );
+ ret = pSetProcessDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)-6 );
+ ok( !ret, "got %d\n", ret );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
+ ret = pSetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
+ todo_wine
+ ok( ret, "got %d\n", ret );
+ ok( pIsProcessDPIAware(), "not aware\n" );
+ real_dpi = pGetDpiForSystem();
+ SetLastError( 0xdeadbeef );
+ ret = pSetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
+ ok( !ret, "got %d\n", ret );
+ ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
+ SetLastError( 0xdeadbeef );
+ ret = pSetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
+ ok( !ret, "got %d\n", ret );
+ ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
+
+ ret = pSetProcessDpiAwarenessInternal( DPI_AWARENESS_INVALID );
+ ok( !ret, "got %d\n", ret );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
+ ret = pSetProcessDpiAwarenessInternal( DPI_AWARENESS_UNAWARE );
+ ok( !ret, "got %d\n", ret );
+ ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
+ ret = pGetProcessDpiAwarenessInternal( 0, &awareness );
+ ok( ret, "got %d\n", ret );
+ todo_wine
+ ok( awareness == DPI_AWARENESS_SYSTEM_AWARE, "wrong value %d\n", awareness );
+ ret = pGetProcessDpiAwarenessInternal( GetCurrentProcess(), &awareness );
+ ok( ret, "got %d\n", ret );
+ todo_wine
+ ok( awareness == DPI_AWARENESS_SYSTEM_AWARE, "wrong value %d\n", awareness );
+ ret = pGetProcessDpiAwarenessInternal( (HANDLE)0xdeadbeef, &awareness );
+ ok( ret, "got %d\n", ret );
+ ok( awareness == DPI_AWARENESS_UNAWARE, "wrong value %d\n", awareness );
+
+ ret = pIsProcessDPIAware();
+ ok(ret, "got %d\n", ret);
+ context = pGetThreadDpiAwarenessContext();
+ todo_wine
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ todo_wine
+ ok( awareness == DPI_AWARENESS_SYSTEM_AWARE, "wrong awareness %u\n", awareness );
+ SetLastError( 0xdeadbeef );
+ context = pSetThreadDpiAwarenessContext( 0 );
+ ok( !context, "got %p\n", context );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
+ SetLastError( 0xdeadbeef );
+ context = pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)-6 );
+ ok( !context, "got %p\n", context );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
+ context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
+ todo_wine
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x80000011 | flags), "wrong context %p\n", context );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ todo_wine
+ ok( awareness == DPI_AWARENESS_SYSTEM_AWARE, "wrong awareness %u\n", awareness );
+ dpi = pGetDpiForSystem();
+ ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
+ dpi = GetDeviceCaps( hdc, LOGPIXELSX );
+ ok( dpi == USER_DEFAULT_SCREEN_DPI, "wrong dpi %u\n", dpi );
+ ok( !pIsProcessDPIAware(), "still aware\n" );
+ context = pGetThreadDpiAwarenessContext();
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x10 | flags), "wrong context %p\n", context );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == DPI_AWARENESS_UNAWARE, "wrong awareness %u\n", awareness );
+ context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x10 | flags), "wrong context %p\n", context );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == DPI_AWARENESS_UNAWARE, "wrong awareness %u\n", awareness );
+ dpi = pGetDpiForSystem();
+ ok( dpi == real_dpi, "wrong dpi %u/%u\n", dpi, real_dpi );
+ dpi = GetDeviceCaps( hdc, LOGPIXELSX );
+ ok( dpi == real_dpi, "wrong dpi %u\n", dpi );
+ context = pGetThreadDpiAwarenessContext();
+ ok( context == (DPI_AWARENESS_CONTEXT)0x12, "wrong context %p\n", context );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "wrong awareness %u\n", awareness );
+ context = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE );
+ ok( context == (DPI_AWARENESS_CONTEXT)0x12, "wrong context %p\n", context );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "wrong awareness %u\n", awareness );
+ dpi = pGetDpiForSystem();
+ ok( dpi == real_dpi, "wrong dpi %u/%u\n", dpi, real_dpi );
+ dpi = GetDeviceCaps( hdc, LOGPIXELSX );
+ ok( dpi == real_dpi, "wrong dpi %u\n", dpi );
+ ok( pIsProcessDPIAware(), "not aware\n" );
+ context = pGetThreadDpiAwarenessContext();
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
+ context = pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)(0x80000010 | flags) );
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
+ context = pGetThreadDpiAwarenessContext();
+ todo_wine
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
+ context = pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)(0x80000011 | flags) );
+ todo_wine
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x80000011 | flags), "wrong context %p\n", context );
+ context = pGetThreadDpiAwarenessContext();
+ todo_wine
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
+ context = pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)0x12 );
+ todo_wine
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x80000011 | flags), "wrong context %p\n", context );
+ context = pSetThreadDpiAwarenessContext( context );
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x12), "wrong context %p\n", context );
+ context = pGetThreadDpiAwarenessContext();
+ todo_wine
+ ok( context == (DPI_AWARENESS_CONTEXT)(0x11 | flags), "wrong context %p\n", context );
+ for (i = 0; i < 0x100; i++)
+ {
+ awareness = pGetAwarenessFromDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)i );
+ switch (i)
+ {
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ ok( awareness == (i & ~0x10), "%lx: wrong value %u\n", i, awareness );
+ ok( pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)i ), "%lx: not valid\n", i );
+ break;
+ default:
+ ok( awareness == DPI_AWARENESS_INVALID, "%lx: wrong value %u\n", i, awareness );
+ ok( !pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)i ), "%lx: valid\n", i );
+ break;
+ }
+ awareness = pGetAwarenessFromDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)(i | 0x80000000) );
+ switch (i)
+ {
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ ok( awareness == (i & ~0x10), "%lx: wrong value %u\n", i | 0x80000000, awareness );
+ ok( pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)(i | 0x80000000) ),
+ "%lx: not valid\n", i | 0x80000000 );
+ break;
+ default:
+ ok( awareness == DPI_AWARENESS_INVALID, "%lx: wrong value %u\n", i | 0x80000000, awareness );
+ ok( !pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)(i | 0x80000000) ),
+ "%lx: valid\n", i | 0x80000000 );
+ break;
+ }
+ awareness = pGetAwarenessFromDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i );
+ switch (~i)
+ {
+ case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE:
+ case (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE:
+ case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE:
+ ok( awareness == i, "%lx: wrong value %u\n", ~i, awareness );
+ ok( pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i ), "%lx: not valid\n", ~i );
+ break;
+ case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2:
+ if (pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i ))
+ ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "%lx: wrong value %u\n", ~i, awareness );
+ else
+ ok( awareness == DPI_AWARENESS_INVALID, "%lx: wrong value %u\n", ~i, awareness );
+ break;
+ case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED:
+ if (pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i ))
+ ok( awareness == DPI_AWARENESS_UNAWARE, "%lx: wrong value %u\n", ~i, awareness );
+ else
+ ok( awareness == DPI_AWARENESS_INVALID, "%lx: wrong value %u\n", ~i, awareness );
+ break;
+ default:
+ ok( awareness == DPI_AWARENESS_INVALID, "%lx: wrong value %u\n", ~i, awareness );
+ ok( !pIsValidDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i ), "%lx: valid\n", ~i );
+ break;
+ }
+ }
+ if (real_dpi != USER_DEFAULT_SCREEN_DPI) test_dpi_stock_objects( hdc );
+ ReleaseDC( 0, hdc );
+}
+
+static LRESULT CALLBACK dpi_winproc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
+{
+ DPI_AWARENESS_CONTEXT ctx = pGetWindowDpiAwarenessContext( hwnd );
+ DPI_AWARENESS_CONTEXT ctx2 = pGetThreadDpiAwarenessContext();
+ DWORD pos, pos2;
+
+ ok( pGetAwarenessFromDpiAwarenessContext( ctx ) == pGetAwarenessFromDpiAwarenessContext( ctx2 ),
+ "msg %04x wrong awareness %p / %p\n", msg, ctx, ctx2 );
+ pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
+ pos = GetMessagePos();
+ pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
+ pos2 = GetMessagePos();
+ ok( pos == pos2, "wrong pos %08x / %08x\n", pos, pos2 );
+ pSetThreadDpiAwarenessContext( ctx2 );
+ return DefWindowProcA( hwnd, msg, wp, lp );
+}
+
+static void test_dpi_window(void)
+{
+ DPI_AWARENESS_CONTEXT context, orig;
+ DPI_AWARENESS awareness;
+ ULONG_PTR i, j;
+ UINT dpi;
+ HWND hwnd, child, ret;
+ MSG msg = { 0, WM_USER + 1, 0, 0 };
+
+ if (!pGetWindowDpiAwarenessContext)
+ {
+ win_skip( "GetWindowDpiAwarenessContext not supported\n" );
+ return;
+ }
+ orig = pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
+ for (i = DPI_AWARENESS_UNAWARE; i <= DPI_AWARENESS_PER_MONITOR_AWARE; i++)
+ {
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~i );
+ hwnd = CreateWindowA( "DpiTestClass", "Test",
+ WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
+ ok( hwnd != 0, "failed to create window\n" );
+ context = pGetWindowDpiAwarenessContext( hwnd );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == i, "%lu: wrong awareness %u\n", i, awareness );
+ dpi = pGetDpiForWindow( hwnd );
+ ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
+ "%lu: got %u / %u\n", i, dpi, real_dpi );
+ if (pGetDpiForMonitorInternal)
+ {
+ BOOL res;
+ SetLastError( 0xdeadbeef );
+ res = pGetDpiForMonitorInternal( MonitorFromWindow( hwnd, 0 ), 0, &dpi, NULL );
+ ok( !res, "succeeded\n" );
+ ok( GetLastError() == ERROR_INVALID_ADDRESS, "wrong error %u\n", GetLastError() );
+ SetLastError( 0xdeadbeef );
+ res = pGetDpiForMonitorInternal( MonitorFromWindow( hwnd, 0 ), 3, &dpi, &dpi );
+ ok( !res, "succeeded\n" );
+ ok( GetLastError() == ERROR_BAD_ARGUMENTS, "wrong error %u\n", GetLastError() );
+ SetLastError( 0xdeadbeef );
+ res = pGetDpiForMonitorInternal( MonitorFromWindow( hwnd, 0 ), 3, &dpi, NULL );
+ ok( !res, "succeeded\n" );
+ ok( GetLastError() == ERROR_BAD_ARGUMENTS, "wrong error %u\n", GetLastError() );
+ res = pGetDpiForMonitorInternal( MonitorFromWindow( hwnd, 0 ), 0, &dpi, &dpi );
+ ok( res, "failed err %u\n", GetLastError() );
+ ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
+ "%lu: got %u / %u\n", i, dpi, real_dpi );
+ }
+ msg.hwnd = hwnd;
+ for (j = DPI_AWARENESS_UNAWARE; j <= DPI_AWARENESS_PER_MONITOR_AWARE; j++)
+ {
+ pSetThreadDpiAwarenessContext( (DPI_AWARENESS_CONTEXT)~j );
+ SendMessageA( hwnd, WM_USER, 0, 0 );
+ DispatchMessageA( &msg );
+ CallWindowProcA( dpi_winproc, hwnd, WM_USER + 2, 0, 0 );
+ child = CreateWindowA( "DpiTestClass", "Test",
+ WS_CHILD, 0, 0, 100, 100, hwnd, 0, GetModuleHandleA(0), NULL );
+ context = pGetWindowDpiAwarenessContext( child );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == i, "%lu/%lu: wrong awareness %u\n", i, j, awareness );
+ dpi = pGetDpiForWindow( child );
+ ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
+ "%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
+ ret = SetParent( child, NULL );
+ ok( ret != 0, "SetParent failed err %u\n", GetLastError() );
+ context = pGetWindowDpiAwarenessContext( child );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == i, "%lu/%lu: wrong awareness %u\n", i, j, awareness );
+ dpi = pGetDpiForWindow( child );
+ ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
+ "%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
+ DestroyWindow( child );
+ child = CreateWindowA( "DpiTestClass", "Test",
+ WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
+ context = pGetWindowDpiAwarenessContext( child );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == j, "%lu/%lu: wrong awareness %u\n", i, j, awareness );
+ dpi = pGetDpiForWindow( child );
+ ok( dpi == (j == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
+ "%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
+ ret = SetParent( child, hwnd );
+ ok( ret != 0 || GetLastError() == ERROR_INVALID_STATE,
+ "SetParent failed err %u\n", GetLastError() );
+ context = pGetWindowDpiAwarenessContext( child );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == (ret ? i : j), "%lu/%lu: wrong awareness %u\n", i, j, awareness );
+ dpi = pGetDpiForWindow( child );
+ ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
+ "%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
+ DestroyWindow( child );
+ }
+ DestroyWindow( hwnd );
+ }
+
+ SetLastError( 0xdeadbeef );
+ context = pGetWindowDpiAwarenessContext( (HWND)0xdeadbeef );
+ ok( !context, "got %p\n", context );
+ ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
+ SetLastError( 0xdeadbeef );
+ dpi = pGetDpiForWindow( (HWND)0xdeadbeef );
+ ok( !dpi, "got %u\n", dpi );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_WINDOW_HANDLE,
+ "wrong error %u\n", GetLastError() );
+
+ SetLastError( 0xdeadbeef );
+ context = pGetWindowDpiAwarenessContext( GetDesktopWindow() );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "wrong awareness %u\n", awareness );
+ dpi = pGetDpiForWindow( GetDesktopWindow() );
+ ok( dpi == real_dpi, "got %u / %u\n", dpi, real_dpi );
+
+ pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
+ SetLastError( 0xdeadbeef );
+ context = pGetWindowDpiAwarenessContext( GetDesktopWindow() );
+ awareness = pGetAwarenessFromDpiAwarenessContext( context );
+ ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "wrong awareness %u\n", awareness );
+ dpi = pGetDpiForWindow( GetDesktopWindow() );
+ ok( dpi == real_dpi, "got %u / %u\n", dpi, real_dpi );
+
+ pSetThreadDpiAwarenessContext( orig );
}
static void test_GetAutoRotationState(void)
state = 0;
ret = pGetAutoRotationState(&state);
ok(ret, "Expected GetAutoRotationState to succeed, error %d\n", GetLastError());
- ok((state & AR_NOSENSOR) != 0, "Expected AR_NOSENSOR, got %d\n", state);
}
START_TEST(sysparams)
char** argv;
WNDCLASSA wc;
MSG msg;
+ HDC hdc;
HANDLE hThread;
DWORD dwThreadId;
HANDLE hInstance, hdll;
pChangeDisplaySettingsExA = (void*)GetProcAddress(hdll, "ChangeDisplaySettingsExA");
pIsProcessDPIAware = (void*)GetProcAddress(hdll, "IsProcessDPIAware");
pSetProcessDPIAware = (void*)GetProcAddress(hdll, "SetProcessDPIAware");
+ pGetDpiForSystem = (void*)GetProcAddress(hdll, "GetDpiForSystem");
+ pGetDpiForWindow = (void*)GetProcAddress(hdll, "GetDpiForWindow");
+ pGetDpiForMonitorInternal = (void*)GetProcAddress(hdll, "GetDpiForMonitorInternal");
+ pSetProcessDpiAwarenessContext = (void*)GetProcAddress(hdll, "SetProcessDpiAwarenessContext");
+ pGetProcessDpiAwarenessInternal = (void*)GetProcAddress(hdll, "GetProcessDpiAwarenessInternal");
+ pSetProcessDpiAwarenessInternal = (void*)GetProcAddress(hdll, "SetProcessDpiAwarenessInternal");
+ pGetThreadDpiAwarenessContext = (void*)GetProcAddress(hdll, "GetThreadDpiAwarenessContext");
+ pSetThreadDpiAwarenessContext = (void*)GetProcAddress(hdll, "SetThreadDpiAwarenessContext");
+ pGetWindowDpiAwarenessContext = (void*)GetProcAddress(hdll, "GetWindowDpiAwarenessContext");
+ pGetAwarenessFromDpiAwarenessContext = (void*)GetProcAddress(hdll, "GetAwarenessFromDpiAwarenessContext");
+ pIsValidDpiAwarenessContext = (void*)GetProcAddress(hdll, "IsValidDpiAwarenessContext");
+ pGetSystemMetricsForDpi = (void*)GetProcAddress(hdll, "GetSystemMetricsForDpi");
+ pSystemParametersInfoForDpi = (void*)GetProcAddress(hdll, "SystemParametersInfoForDpi");
+ pAdjustWindowRectExForDpi = (void*)GetProcAddress(hdll, "AdjustWindowRectExForDpi");
+ pLogicalToPhysicalPointForPerMonitorDPI = (void*)GetProcAddress(hdll, "LogicalToPhysicalPointForPerMonitorDPI");
+ pPhysicalToLogicalPointForPerMonitorDPI = (void*)GetProcAddress(hdll, "PhysicalToLogicalPointForPerMonitorDPI");
pGetAutoRotationState = (void*)GetProcAddress(hdll, "GetAutoRotationState");
hInstance = GetModuleHandleA( NULL );
dpi = GetDeviceCaps( hdc, LOGPIXELSY);
real_dpi = get_real_dpi();
trace("dpi %d real_dpi %d\n", dpi, real_dpi);
- iswin9x = GetVersion() & 0x80000000;
+ ReleaseDC( 0, hdc);
/* This test requires interactivity, if we don't have it, give up */
if (!SystemParametersInfoA( SPI_SETBEEP, TRUE, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ) &&
trace("testing GetSystemMetrics with your current desktop settings\n");
test_GetSystemMetrics( );
- trace("testing EnumDisplaySettings vs GetDeviceCaps\n");
+ test_metrics_for_dpi( 192 );
test_EnumDisplaySettings( );
test_GetSysColorBrush( );
test_GetAutoRotationState( );
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
RegisterClassA( &wc );
+ wc.lpszClassName = "DpiTestClass";
+ wc.lpfnWndProc = dpi_winproc;
+ RegisterClassA( &wc );
ghTestWnd = CreateWindowA( "SysParamsTestClass", "Test System Parameters Application",
WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, hInstance, NULL );
TranslateMessage( &msg );
DispatchMessageA( &msg );
}
- ReleaseDC( 0, hdc);
+
+ if (pSetThreadDpiAwarenessContext)
+ {
+ test_dpi_context();
+ test_dpi_mapping();
+ test_dpi_window();
+ }
+ else win_skip( "SetThreadDpiAwarenessContext not supported\n" );
test_dpi_aware();
}
extern void func_msg_layered_window(void);
extern void func_msg_dialog(void);
extern void func_msg_clipboard(void);
+extern void func_rawinput(void);
extern void func_resource(void);
extern void func_scroll(void);
extern void func_static(void);
{ "msg_layered_window", func_msg_layered_window},
{ "msg_dialog", func_msg_dialog},
{ "msg_clipboard", func_msg_clipboard},
+ { "rawinput", func_rawinput },
{ "resource", func_resource },
{ "scroll", func_scroll },
{ "static", func_static },
ok(textheight==0,"Got textheight from DrawTextA\n");
ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
+ /* When offset to top is zero, return 1 */
+ SetRectEmpty(&rect);
+ textheight = DrawTextExW(hdc, textW, -1, &rect, DT_SINGLELINE | DT_CALCRECT | DT_BOTTOM, NULL);
+ ok(textheight == 1, "Expect returned height:1 got:%d\n", textheight);
+
+ SetRect(&rect, 0, 100, 0, 100);
+ textheight = DrawTextExW(hdc, textW, -1, &rect, DT_SINGLELINE | DT_CALCRECT | DT_BOTTOM, NULL);
+ ok(textheight == 1, "Expect returned height:1 got:%d\n", textheight);
+
+ SetRectEmpty(&rect);
+ textheight = DrawTextExW(hdc, textW, -1, &rect, DT_SINGLELINE | DT_CALCRECT | DT_TOP, NULL);
+ /* Set top to text height and bottom zero, so bottom of drawn text to top is zero when DT_VCENTER is used */
+ SetRect(&rect, 0, textheight, 0, 0);
+ textheight = DrawTextExW(hdc, textW, -1, &rect, DT_SINGLELINE | DT_CALCRECT | DT_VCENTER, NULL);
+ ok(textheight == 1, "Expect returned height:1 got:%d\n", textheight);
/* invalid dtp size test */
dtp.cbSize = -1; /* Invalid */
char oem;
WCHAR uni, expect;
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
{
const char *expected = tests[i].ret ? helloWorld : "";
const char *src = tests[i].src ? helloWorld : NULL;
ok(!strcmp(buf, expected), "test %d: got '%s'\n", i, buf);
}
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
{
const char *expected = tests[i].ret ? helloWorld : "";
const WCHAR *src = tests[i].src ? helloWorldW : NULL;
ok(!strcmp(buf, expected), "test %d: got '%s'\n", i, buf);
memset(buf, 0, sizeof(buf));
- ret = CharToOemBuffW(src, dst, sizeof(helloWorldW)/sizeof(WCHAR));
+ ret = CharToOemBuffW(src, dst, ARRAY_SIZE(helloWorldW));
ok(ret == tests[i].ret, "test %d: expected %d, got %d\n", i, tests[i].ret, ret);
ok(!strcmp(buf, expected), "test %d: got '%s'\n", i, buf);
}
- for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
{
const WCHAR *expected = tests[i].ret ? helloWorldW : emptyW;
const char *src = tests[i].src ? helloWorld : NULL;
{{-109, -107, -103, -101}, FALSE},
};
- for (i = 0; i < sizeof(rtest)/sizeof(rtest[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(rtest); i++) {
ret = IsRectEmpty(&rtest[i].rect);
ok(ret == rtest[i].ret, "Test %d: IsRectEmpty returned %s for %s\n", i,
ret ? "TRUE" : "FALSE", wine_dbgstr_rect(&rtest[i].rect));
win_skip( "I64 formats not supported\n" );
return;
}
- for (i = 0; i < sizeof(i64_formats)/sizeof(i64_formats[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(i64_formats); i++)
{
rc = wsprintfA(buf, i64_formats[i].fmt, i64_formats[i].value);
ok(rc == strlen(i64_formats[i].res), "%u: wsprintfA length failure: rc=%d\n", i, rc);
win_skip( "I64 formats not supported\n" );
return;
}
- for (i = 0; i < sizeof(i64_formats)/sizeof(i64_formats[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(i64_formats); i++)
{
- MultiByteToWideChar( CP_ACP, 0, i64_formats[i].fmt, -1, fmt, sizeof(fmt)/sizeof(WCHAR) );
- MultiByteToWideChar( CP_ACP, 0, i64_formats[i].res, -1, res, sizeof(res)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, i64_formats[i].fmt, -1, fmt, ARRAY_SIZE(fmt));
+ MultiByteToWideChar( CP_ACP, 0, i64_formats[i].res, -1, res, ARRAY_SIZE(res));
rc = wsprintfW(buf, fmt, i64_formats[i].value);
ok(rc == lstrlenW(res), "%u: wsprintfW length failure: rc=%d\n", i, rc);
ok(!lstrcmpW(buf, res), "%u: wrong result [%s]\n", i, wine_dbgstr_w(buf));