sync user32 winetest with wine 1.1.28

svn path=/trunk/; revision=42911
This commit is contained in:
Christoph von Wittich 2009-08-24 12:42:47 +00:00
parent 63b3ed6d1e
commit 694741e9f9
7 changed files with 1023 additions and 53 deletions

View file

@ -94,28 +94,29 @@ static void test_setitemheight(DWORD style)
static void test_setfont(DWORD style)
{
HWND hCombo = build_combo(style);
HFONT hFont1 = CreateFont(10, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
HFONT hFont2 = CreateFont(8, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
HWND hCombo;
HFONT hFont1, hFont2;
RECT r;
int i;
if (!is_font_installed("Marlett"))
{
skip("Marlett font not available\n");
return;
}
trace("Style %x\n", style);
hCombo = build_combo(style);
hFont1 = CreateFont(10, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
hFont2 = CreateFont(8, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
GetClientRect(hCombo, &r);
expect_rect(r, 0, 0, 100, 24);
SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r);
MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
todo_wine expect_rect(r, 5, 5, 105, 105);
if (!is_font_installed("Marlett"))
{
skip("Marlett font not available\n");
DestroyWindow(hCombo);
DeleteObject(hFont1);
DeleteObject(hFont2);
return;
}
if (font_height(hFont1) == 10 && font_height(hFont2) == 8)
{
SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont1, FALSE);
@ -140,11 +141,14 @@ static void test_setfont(DWORD style)
todo_wine expect_rect(r, 5, 5, 105, 99);
}
else
skip("Invalid Marlett font heights\n");
{
ok(0, "Expected Marlett font heights 10/8, got %d/%d\n",
font_height(hFont1), font_height(hFont2));
}
for (i = 1; i < 30; i++)
{
HFONT hFont = CreateFont(i, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
HFONT hFont = CreateFont(i, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett");
int height = font_height(hFont);
SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont, FALSE);

View file

@ -956,6 +956,262 @@ static void test_CreateIconFromResource(void)
HeapFree(GetProcessHeap(), 0, hotspot);
}
static HICON create_test_icon(HDC hdc, int width, int height, int bpp,
BOOL maskvalue, UINT32 *color, int colorSize)
{
ICONINFO iconInfo;
BITMAPINFO bitmapInfo;
UINT32 *buffer = NULL;
UINT32 mask = maskvalue ? 0xFFFFFFFF : 0x00000000;
memset(&bitmapInfo, 0, sizeof(bitmapInfo));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = width;
bitmapInfo.bmiHeader.biHeight = height;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = bpp;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = colorSize;
iconInfo.fIcon = TRUE;
iconInfo.xHotspot = 0;
iconInfo.yHotspot = 0;
iconInfo.hbmMask = CreateBitmap( width, height, 1, 1, &mask );
if(!iconInfo.hbmMask) return NULL;
iconInfo.hbmColor = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
if(!iconInfo.hbmColor || !buffer)
{
DeleteObject(iconInfo.hbmMask);
return NULL;
}
memcpy(buffer, color, colorSize);
return CreateIconIndirect(&iconInfo);
}
static BOOL color_match(COLORREF a, COLORREF b)
{
/* 5-bit accuracy is a sufficient test. This will match, so long as
* colors are never truncated to less that 3x5-bit accuracy i.e.
* paletized. */
return (a & 0x00F8F8F8) == (b & 0x00F8F8F8);
}
static void check_alpha_draw(HDC hdc, BOOL drawiconex, BOOL alpha, int bpp, int line)
{
HICON hicon;
UINT32 mask;
UINT32 color[2];
COLORREF modern_expected, legacy_expected, result;
mask = 0x00000000;
color[0] = 0x00A0B0C0;
color[1] = alpha ? 0xFF000000 : 0x00000000;
modern_expected = alpha ? 0x00FFFFFF : 0x00C0B0A0;
legacy_expected = 0x00C0B0A0;
hicon = create_test_icon(hdc, 2, 1, bpp, 0, color, sizeof(color));
if (!hicon) return;
SetPixelV(hdc, 0, 0, 0x00FFFFFF);
if(drawiconex)
DrawIconEx(hdc, 0, 0, hicon, 2, 1, 0, NULL, DI_NORMAL);
else
DrawIcon(hdc, 0, 0, hicon);
result = GetPixel(hdc, 0, 0);
ok (color_match(result, modern_expected) || /* Windows 2000 and up */
broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
"%s. Expected a close match to %06X (modern) or %06X (legacy) with %s. "
"Got %06X from line %d\n",
alpha ? "Alpha blending" : "Not alpha blending", modern_expected, legacy_expected,
drawiconex ? "DrawIconEx" : "DrawIcon", result, line);
}
static void check_DrawIcon(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, COLORREF background,
COLORREF modern_expected, COLORREF legacy_expected, int line)
{
COLORREF result;
HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
if (!hicon) return;
SetPixelV(hdc, 0, 0, background);
DrawIcon(hdc, 0, 0, hicon);
result = GetPixel(hdc, 0, 0);
ok (color_match(result, modern_expected) || /* Windows 2000 and up */
broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
"Overlaying Mask %d on Color %06X with DrawIcon. "
"Expected a close match to %06X (modern), or %06X (legacy). Got %06X from line %d\n",
maskvalue, color, modern_expected, legacy_expected, result, line);
}
static void test_DrawIcon(void)
{
BITMAPINFO bitmapInfo;
HDC hdcDst = NULL;
HBITMAP bmpDst = NULL;
HBITMAP bmpOld = NULL;
UINT32 *bits = 0;
hdcDst = CreateCompatibleDC(0);
ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
if (!hdcDst)
return;
if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
{
skip("Windows will distort DrawIcon colors at 8-bpp and less due to palletizing.\n");
goto cleanup;
}
memset(&bitmapInfo, 0, sizeof(bitmapInfo));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = 1;
bitmapInfo.bmiHeader.biHeight = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
if (!bmpDst || !bits)
goto cleanup;
bmpOld = SelectObject(hdcDst, bmpDst);
/* Mask is only heeded if alpha channel is always zero */
check_DrawIcon(hdcDst, FALSE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
check_DrawIcon(hdcDst, TRUE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x003F4F5F, 0x003F4F5F, __LINE__);
/* Test alpha blending */
/* Windows 2000 and up will alpha blend, earlier Windows versions will not */
check_DrawIcon(hdcDst, FALSE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
check_DrawIcon(hdcDst, FALSE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
check_DrawIcon(hdcDst, TRUE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
/* Test detecting of alpha channel */
/* If a single pixel's alpha channel is non-zero, the icon
will be alpha blended, otherwise it will be draw with
and + xor blts. */
check_alpha_draw(hdcDst, FALSE, FALSE, 32, __LINE__);
check_alpha_draw(hdcDst, FALSE, TRUE, 32, __LINE__);
cleanup:
if(bmpOld)
SelectObject(hdcDst, bmpOld);
if(bmpDst)
DeleteObject(bmpDst);
if(hdcDst)
DeleteDC(hdcDst);
}
static void check_DrawIconEx(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, UINT flags, COLORREF background,
COLORREF modern_expected, COLORREF legacy_expected, int line)
{
COLORREF result;
HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
if (!hicon) return;
SetPixelV(hdc, 0, 0, background);
DrawIconEx(hdc, 0, 0, hicon, 1, 1, 0, NULL, flags);
result = GetPixel(hdc, 0, 0);
ok (color_match(result, modern_expected) || /* Windows 2000 and up */
broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
"Overlaying Mask %d on Color %06X with DrawIconEx flags %08X. "
"Expected a close match to %06X (modern) or %06X (legacy). Got %06X from line %d\n",
maskvalue, color, flags, modern_expected, legacy_expected, result, line);
}
static void test_DrawIconEx(void)
{
BITMAPINFO bitmapInfo;
HDC hdcDst = NULL;
HBITMAP bmpDst = NULL;
HBITMAP bmpOld = NULL;
UINT32 bits = 0;
hdcDst = CreateCompatibleDC(0);
ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
if (!hdcDst)
return;
if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
{
skip("Windows will distort DrawIconEx colors at 8-bpp and less due to palletizing.\n");
goto cleanup;
}
memset(&bitmapInfo, 0, sizeof(bitmapInfo));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = 1;
bitmapInfo.bmiHeader.biHeight = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
if (!bmpDst || !bits)
goto cleanup;
bmpOld = SelectObject(hdcDst, bmpDst);
/* Test null, image only, and mask only drawing */
check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00000000, 0x00000000, __LINE__);
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, __LINE__);
todo_wine
{
check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
}
/* Test normal drawing */
check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
todo_wine check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x003F4F5F, 0x003F4F5F, __LINE__);
check_DrawIconEx(hdcDst, FALSE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
/* Test alpha blending */
/* Windows 2000 and up will alpha blend, earlier Windows versions will not */
check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
check_DrawIconEx(hdcDst, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
check_DrawIconEx(hdcDst, TRUE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
/* Test detecting of alpha channel */
/* If a single pixel's alpha channel is non-zero, the icon
will be alpha blended, otherwise it will be draw with
and + xor blts. */
check_alpha_draw(hdcDst, TRUE, FALSE, 32, __LINE__);
check_alpha_draw(hdcDst, TRUE, TRUE, 32, __LINE__);
cleanup:
if(bmpOld)
SelectObject(hdcDst, bmpOld);
if(bmpDst)
DeleteObject(bmpDst);
if(hdcDst)
DeleteDC(hdcDst);
}
static void test_DestroyCursor(void)
{
static const BYTE bmp_bits[4096];
@ -1063,6 +1319,8 @@ START_TEST(cursoricon)
test_CreateIcon();
test_LoadImage();
test_CreateIconFromResource();
test_DrawIcon();
test_DrawIconEx();
test_DestroyCursor();
do_parent();
test_child_process();

View file

@ -901,23 +901,72 @@ static void test_GetDlgItemText(void)
"string retrieved using GetDlgItemText should have been NULL terminated\n");
}
static INT_PTR CALLBACK DestroyDlgWinProc (HWND hDlg, UINT uiMsg,
WPARAM wParam, LPARAM lParam)
{
if (uiMsg == WM_INITDIALOG)
{
DestroyWindow(hDlg);
return TRUE;
}
return FALSE;
}
static INT_PTR CALLBACK DestroyOnCloseDlgWinProc (HWND hDlg, UINT uiMsg,
WPARAM wParam, LPARAM lParam)
{
switch (uiMsg)
{
case WM_INITDIALOG:
PostMessage(hDlg, WM_CLOSE, 0, 0);
return TRUE;
case WM_CLOSE:
DestroyWindow(hDlg);
return TRUE;
case WM_DESTROY:
PostQuitMessage(0);
return TRUE;
}
return FALSE;
}
static void test_DialogBoxParamA(void)
{
int ret;
INT_PTR ret;
HWND hwnd_invalid = (HWND)0x4444;
SetLastError(0xdeadbeef);
ret = DialogBoxParamA(GetModuleHandle(NULL), "IDD_DIALOG" , hwnd_invalid, 0 , 0);
ok(0 == ret || broken(ret == -1), "DialogBoxParamA returned %d, expected 0\n", ret);
ok(0 == ret || broken(ret == -1), "DialogBoxParamA returned %ld, expected 0\n", ret);
ok(ERROR_INVALID_WINDOW_HANDLE == GetLastError() ||
broken(GetLastError() == 0xdeadbeef),
"got %d, expected ERROR_INVALID_WINDOW_HANDLE\n",GetLastError());
/* Test a dialog which destroys itself on WM_INITDIALOG. */
SetLastError(0xdeadbeef);
ret = DialogBoxParamA(GetModuleHandle(NULL), "IDD_DIALOG", 0, DestroyDlgWinProc, 0);
ok(-1 == ret, "DialogBoxParamA returned %ld, expected -1\n", ret);
ok(ERROR_INVALID_WINDOW_HANDLE == GetLastError() ||
GetLastError() == ERROR_SUCCESS ||
broken(GetLastError() == 0xdeadbeef),
"got %d, expected ERROR_INVALID_WINDOW_HANDLE\n",GetLastError());
/* Test a dialog which destroys itself on WM_CLOSE. */
ret = DialogBoxParamA(GetModuleHandle(NULL), "IDD_DIALOG", 0, DestroyOnCloseDlgWinProc, 0);
ok(0 == ret, "DialogBoxParamA returned %ld, expected 0\n", ret);
SetLastError(0xdeadbeef);
ret = DialogBoxParamA(GetModuleHandle(NULL), "RESOURCE_INVALID" , 0, 0, 0);
ok(-1 == ret, "DialogBoxParamA returned %d, expected -1\n", ret);
ok(-1 == ret, "DialogBoxParamA returned %ld, expected -1\n", ret);
ok(ERROR_RESOURCE_NAME_NOT_FOUND == GetLastError() ||
broken(GetLastError() == 0xdeadbeef),
"got %d, expected ERROR_RESOURCE_NAME_NOT_FOUND\n",GetLastError());
SetLastError(0xdeadbeef);
ret = DefDlgProcA(0, WM_ERASEBKGND, 0, 0);
ok(ret == 0, "DefDlgProcA returned %ld, expected 0\n", ret);
ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE,
"got %d, expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError());
}
static void test_DisabledDialogTest(void)
@ -1020,6 +1069,63 @@ static void test_MessageBoxFontTest(void)
DestroyWindow(hDlg);
}
static void test_SaveRestoreFocus(void)
{
HWND hDlg;
HRSRC hResource;
HANDLE hTemplate;
DLGTEMPLATE* pTemplate;
LONG_PTR foundId;
HWND foundHwnd;
/* create the dialog */
hResource = FindResourceA(g_hinst, "MULTI_EDIT_DIALOG", RT_DIALOG);
hTemplate = LoadResource(g_hinst, hResource);
pTemplate = LockResource(hTemplate);
hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, messageBoxFontDlgWinProc, 0);
ok (hDlg != 0, "Failed to create test dialog.\n");
foundId = GetWindowLongPtr(GetFocus(), GWLP_ID);
ok (foundId == 1000, "First edit box should have gained focus on dialog creation. Expected: %d, Found: %ld\n", 1000, foundId);
/* de- then reactivate the dialog */
SendMessage(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), 0);
SendMessage(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0);
foundId = GetWindowLongPtr(GetFocus(), GWLP_ID);
ok (foundId == 1000, "First edit box should have regained focus after dialog reactivation. Expected: %d, Found: %ld\n", 1000, foundId);
/* select the next tabbable item */
SetFocus(GetNextDlgTabItem(hDlg, GetFocus(), FALSE));
foundId = GetWindowLongPtr(GetFocus(), GWLP_ID);
ok (foundId == 1001, "Second edit box should have gained focus. Expected: %d, Found: %ld\n", 1001, foundId);
/* de- then reactivate the dialog */
SendMessage(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), 0);
SendMessage(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0);
foundId = GetWindowLongPtr(GetFocus(), GWLP_ID);
ok (foundId == 1001, "Second edit box should have gained focus after dialog reactivation. Expected: %d, Found: %ld\n", 1001, foundId);
/* disable the 2nd box */
EnableWindow(GetFocus(), FALSE);
foundHwnd = GetFocus();
ok (foundHwnd == NULL, "Second edit box should have lost focus after being disabled. Expected: %p, Found: %p\n", NULL, foundHwnd);
/* de- then reactivate the dialog */
SendMessage(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), 0);
SendMessage(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0);
foundHwnd = GetFocus();
ok (foundHwnd == NULL, "No controls should have gained focus after dialog reactivation. Expected: %p, Found: %p\n", NULL, foundHwnd);
/* clean up */
DestroyWindow(hDlg);
}
START_TEST(dialog)
{
g_hinst = GetModuleHandleA (0);
@ -1034,4 +1140,5 @@ START_TEST(dialog)
test_DialogBoxParamA();
test_DisabledDialogTest();
test_MessageBoxFontTest();
test_SaveRestoreFocus();
}

View file

@ -44,7 +44,7 @@
*
*/
#define _WIN32_WINNT 0x401
#define _WIN32_WINNT 0x500
#define _WIN32_IE 0x0500
#include <stdarg.h>
@ -60,6 +60,20 @@
static HWND hWndTest;
static LONG timetag = 0x10000000;
static struct {
LONG last_key_down;
LONG last_key_up;
LONG last_syskey_down;
LONG last_syskey_up;
LONG last_char;
LONG last_syschar;
LONG last_hook_down;
LONG last_hook_up;
LONG last_hook_syskey_down;
LONG last_hook_syskey_up;
BOOL expect_alt;
} key_status;
static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
static int (WINAPI *pGetMouseMovePointsEx) (UINT, LPMOUSEMOVEPOINT, LPMOUSEMOVEPOINT, int, DWORD);
@ -824,7 +838,8 @@ static LRESULT CALLBACK WndProc2(HWND hWnd, UINT Msg, WPARAM wParam,
Msg != WM_GETTEXT &&
Msg != WM_GETICON &&
Msg != WM_IME_SELECT &&
Msg != WM_DEVICECHANGE)
Msg != WM_DEVICECHANGE &&
Msg != WM_TIMECHANGE)
{
ok(sent_messages_cnt < MAXKEYMESSAGES, "Too many messages\n");
if (sent_messages_cnt < MAXKEYMESSAGES)
@ -922,6 +937,224 @@ static void test_Input_blackbox(void)
UnhookWindowsHookEx(hook);
}
static void reset_key_status(void)
{
key_status.last_key_down = -1;
key_status.last_key_up = -1;
key_status.last_syskey_down = -1;
key_status.last_syskey_up = -1;
key_status.last_char = -1;
key_status.last_syschar = -1;
key_status.last_hook_down = -1;
key_status.last_hook_up = -1;
key_status.last_hook_syskey_down = -1;
key_status.last_hook_syskey_up = -1;
key_status.expect_alt = FALSE;
}
static void test_unicode_keys(HWND hwnd, HHOOK hook)
{
TEST_INPUT inputs[2];
MSG msg;
/* init input data that never changes */
inputs[1].type = inputs[0].type = INPUT_KEYBOARD;
inputs[1].u.ki.dwExtraInfo = inputs[0].u.ki.dwExtraInfo = 0;
inputs[1].u.ki.time = inputs[0].u.ki.time = 0;
/* pressing & releasing a single unicode character */
inputs[0].u.ki.wVk = 0;
inputs[0].u.ki.wScan = 0x3c0;
inputs[0].u.ki.dwFlags = KEYEVENTF_UNICODE;
reset_key_status();
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);
}
DispatchMessageW(&msg);
}
ok(key_status.last_key_down == VK_PACKET,
"Last keydown msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_key_down);
ok(key_status.last_char == 0x3c0,
"Last char msg wparam should have been 0x3c0 (was: 0x%x)\n", key_status.last_char);
if(hook)
ok(key_status.last_hook_down == 0x3c0,
"Last hookdown msg should have been 0x3c0, was: 0x%x\n", key_status.last_hook_down);
inputs[1].u.ki.wVk = 0;
inputs[1].u.ki.wScan = 0x3c0;
inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
reset_key_status();
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);
}
DispatchMessageW(&msg);
}
ok(key_status.last_key_up == VK_PACKET,
"Last keyup msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_key_up);
if(hook)
ok(key_status.last_hook_up == 0x3c0,
"Last hookup msg should have been 0x3c0, was: 0x%x\n", key_status.last_hook_up);
/* holding alt, pressing & releasing a unicode character, releasing alt */
inputs[0].u.ki.wVk = VK_LMENU;
inputs[0].u.ki.wScan = 0;
inputs[0].u.ki.dwFlags = 0;
inputs[1].u.ki.wVk = 0;
inputs[1].u.ki.wScan = 0x3041;
inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE;
reset_key_status();
key_status.expect_alt = TRUE;
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);
}
DispatchMessageW(&msg);
}
ok(key_status.last_syskey_down == VK_PACKET,
"Last syskeydown msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_syskey_down);
ok(key_status.last_syschar == 0x3041,
"Last syschar msg should have been 0x3041 (was: 0x%x)\n", key_status.last_syschar);
if(hook)
ok(key_status.last_hook_syskey_down == 0x3041,
"Last hooksysdown msg should have been 0x3041, was: 0x%x\n", key_status.last_hook_syskey_down);
inputs[1].u.ki.wVk = 0;
inputs[1].u.ki.wScan = 0x3041;
inputs[1].u.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
inputs[0].u.ki.wVk = VK_LMENU;
inputs[0].u.ki.wScan = 0;
inputs[0].u.ki.dwFlags = KEYEVENTF_KEYUP;
reset_key_status();
key_status.expect_alt = TRUE;
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);
}
DispatchMessageW(&msg);
}
ok(key_status.last_key_up == VK_PACKET,
"Last keyup msg should have been VK_PACKET[0x%04x] (was: 0x%x)\n", VK_PACKET, key_status.last_key_up);
if(hook)
ok(key_status.last_hook_up == 0x3041,
"Last hook up msg should have been 0x3041, was: 0x%x\n", key_status.last_hook_up);
}
static LRESULT CALLBACK unicode_wnd_proc( HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam )
{
switch(msg){
case WM_KEYDOWN:
key_status.last_key_down = wParam;
break;
case WM_SYSKEYDOWN:
key_status.last_syskey_down = wParam;
break;
case WM_KEYUP:
key_status.last_key_up = wParam;
break;
case WM_SYSKEYUP:
key_status.last_syskey_up = wParam;
break;
case WM_CHAR:
key_status.last_char = wParam;
break;
case WM_SYSCHAR:
key_status.last_syschar = wParam;
break;
}
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
static LRESULT CALLBACK llkbd_unicode_hook(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode == HC_ACTION){
LPKBDLLHOOKSTRUCT info = (LPKBDLLHOOKSTRUCT)lParam;
ok(info->vkCode == VK_PACKET || (key_status.expect_alt && info->vkCode == VK_LMENU), "vkCode should have been VK_PACKET[%04x], was: %04x\n", VK_PACKET, info->vkCode);
key_status.expect_alt = FALSE;
switch(wParam){
case WM_KEYDOWN:
key_status.last_hook_down = info->scanCode;
break;
case WM_KEYUP:
key_status.last_hook_up = info->scanCode;
break;
case WM_SYSKEYDOWN:
key_status.last_hook_syskey_down = info->scanCode;
break;
case WM_SYSKEYUP:
key_status.last_hook_syskey_up = info->scanCode;
break;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
static void test_Input_unicode(void)
{
WCHAR classNameW[] = {'I','n','p','u','t','U','n','i','c','o','d','e',
'K','e','y','T','e','s','t','C','l','a','s','s',0};
WCHAR windowNameW[] = {'I','n','p','u','t','U','n','i','c','o','d','e',
'K','e','y','T','e','s','t',0};
MSG msg;
WNDCLASSW wclass;
HANDLE hInstance = GetModuleHandleW(NULL);
HHOOK hook;
wclass.lpszClassName = classNameW;
wclass.style = CS_HREDRAW | CS_VREDRAW;
wclass.lpfnWndProc = unicode_wnd_proc;
wclass.hInstance = hInstance;
wclass.hIcon = LoadIcon(0, IDI_APPLICATION);
wclass.hCursor = LoadCursor( NULL, IDC_ARROW);
wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wclass.lpszMenuName = 0;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
if(!RegisterClassW(&wclass)){
win_skip("Unicode functions not supported\n");
return;
}
/* create the test window that will receive the keystrokes */
hWndTest = CreateWindowW(wclass.lpszClassName, windowNameW,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
NULL, NULL, hInstance, NULL);
assert(hWndTest);
assert(IsWindowUnicode(hWndTest));
hook = SetWindowsHookExW(WH_KEYBOARD_LL, llkbd_unicode_hook, GetModuleHandleW(NULL), 0);
if(!hook)
win_skip("unable to set WH_KEYBOARD_LL hook\n");
ShowWindow(hWndTest, SW_SHOW);
SetWindowPos(hWndTest, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
SetForegroundWindow(hWndTest);
UpdateWindow(hWndTest);
/* flush pending messages */
while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageW(&msg);
SetFocus(hWndTest);
test_unicode_keys(hWndTest, hook);
if(hook)
UnhookWindowsHookEx(hook);
DestroyWindow(hWndTest);
}
static void test_keynames(void)
{
int i, len;
@ -1319,6 +1552,7 @@ START_TEST(input)
{
test_Input_blackbox();
test_Input_whitebox();
test_Input_unicode();
}
else win_skip("SendInput is not available\n");

View file

@ -536,7 +536,7 @@ static void test_mbs_help( int ispop, int hassub, int mnuopt,
mi.cbSize = sizeof(mi);
mi.fMask = MIM_STYLE;
pGetMenuInfo( hmenu, &mi);
mi.dwStyle |= mnuopt == 1 ? MNS_NOCHECK : MNS_CHECKORBMP;
if( mnuopt) mi.dwStyle |= mnuopt == 1 ? MNS_NOCHECK : MNS_CHECKORBMP;
ret = pSetMenuInfo( hmenu, &mi);
ok( ret, "SetMenuInfo failed with error %d\n", GetLastError());
}
@ -2451,6 +2451,48 @@ static HMENU create_menu_from_data(const struct menu_data *item, INT item_count)
return hmenu;
}
/* use InsertMenuItem: does not set the MFT_BITMAP flag,
* and does not accept non-magic bitmaps with invalid
* bitmap handles */
static HMENU create_menuitem_from_data(const struct menu_data *item, INT item_count)
{
HMENU hmenu;
INT i;
BOOL ret;
MENUITEMINFO mii = { sizeof( MENUITEMINFO)};
hmenu = CreateMenu();
assert(hmenu != 0);
for (i = 0; i < item_count; i++)
{
SetLastError(0xdeadbeef);
mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE;
mii.fType = 0;
if( item[i].type & MFT_BITMAP)
{
mii.fMask |= MIIM_BITMAP;
mii.hbmpItem = (HBITMAP)item[i].str;
}
else if( item[i].type & MFT_SEPARATOR)
mii.fType = MFT_SEPARATOR;
else
{
mii.fMask |= MIIM_STRING;
mii.dwTypeData = (LPSTR)item[i].str;
mii.cch = strlen( item[i].str);
}
mii.fState = 0;
if( item[i].type & MF_HELP) mii.fType |= MF_HELP;
mii.wID = item[i].id;
ret = InsertMenuItem( hmenu, -1, TRUE, &mii);
ok(ret, "%d: InsertMenuItem(%04x, %04x, %p) error %u\n",
i, item[i].type, item[i].id, item[i].str, GetLastError());
}
return hmenu;
}
static void compare_menu_data(HMENU hmenu, const struct menu_data *item, INT item_count)
{
INT count, i;
@ -2479,14 +2521,12 @@ static void compare_menu_data(HMENU hmenu, const struct menu_data *item, INT ite
"%u: expected fType %04x, got %04x\n", i, item[i].type, mii.fType);
ok(mii.wID == item[i].id,
"%u: expected wID %04x, got %04x\n", i, item[i].id, mii.wID);
if (item[i].type & (MF_BITMAP | MF_SEPARATOR))
{
if (mii.hbmpItem || !item[i].str)
/* For some reason Windows sets high word to not 0 for
* not "magic" ids.
*/
ok(LOWORD(mii.hbmpItem) == LOWORD(item[i].str),
"%u: expected hbmpItem %p, got %p\n", i, item[i].str, mii.hbmpItem);
}
else
{
ok(mii.cch == strlen(item[i].str),
@ -2499,6 +2539,7 @@ static void compare_menu_data(HMENU hmenu, const struct menu_data *item, INT ite
static void test_InsertMenu(void)
{
HBITMAP hbm = CreateBitmap(1,1,1,1,NULL);
/* Note: XP treats only bitmap handles 1 - 6 as "magic" ones
* regardless of their id.
*/
@ -2514,16 +2555,28 @@ static void test_InsertMenu(void)
{ MF_STRING|MF_HELP, 2, "Help" },
{ MF_BITMAP|MF_HELP, SC_CLOSE, MAKEINTRESOURCE(1) }
};
static const struct menu_data in2[] =
static const struct menu_data out1a[] =
{
{ MF_STRING, 1, "File" },
{ MF_BITMAP|MF_HELP, SC_CLOSE, MAKEINTRESOURCE(100) },
{ MF_STRING|MF_HELP, 2, "Help" },
{ MF_HELP, SC_CLOSE, MAKEINTRESOURCE(1) }
};
const struct menu_data in2[] =
{
{ MF_STRING, 1, "File" },
{ MF_BITMAP|MF_HELP, SC_CLOSE, (char*)hbm },
{ MF_STRING|MF_HELP, 2, "Help" }
};
static const struct menu_data out2[] =
const struct menu_data out2[] =
{
{ MF_STRING, 1, "File" },
{ MF_BITMAP|MF_HELP, SC_CLOSE, MAKEINTRESOURCE(100) },
{ MF_BITMAP|MF_HELP, SC_CLOSE, (char*)hbm },
{ MF_STRING|MF_HELP, 2, "Help" }
};
const struct menu_data out2a[] =
{
{ MF_STRING, 1, "File" },
{ MF_HELP, SC_CLOSE, (char*)hbm },
{ MF_STRING|MF_HELP, 2, "Help" }
};
static const struct menu_data in3[] =
@ -2550,9 +2603,16 @@ static void test_InsertMenu(void)
{ MF_STRING|MF_HELP, 2, "Help" },
{ MF_BITMAP|MF_HELP, 1, MAKEINTRESOURCE(1) }
};
static const struct menu_data out4a[] =
{
{ MF_STRING, 1, "File" },
{ MF_STRING|MF_HELP, 2, "Help" },
{ MF_HELP, 1, MAKEINTRESOURCE(1) }
};
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]))
hmenu = create_menu(in1);
@ -2571,7 +2631,25 @@ static void test_InsertMenu(void)
compare_menu(hmenu, out4);
DestroyMenu(hmenu);
/* now using InsertMenuItemInfo */
hmenu = create_menuitem(in1);
compare_menu(hmenu, out1a);
DestroyMenu(hmenu);
hmenu = create_menuitem(in2);
compare_menu(hmenu, out2a);
DestroyMenu(hmenu);
hmenu = create_menuitem(in3);
compare_menu(hmenu, out3);
DestroyMenu(hmenu);
hmenu = create_menuitem(in4);
compare_menu(hmenu, out4a);
DestroyMenu(hmenu);
#undef create_menu
#undef create_menuitem
#undef compare_menu
}
@ -2932,6 +3010,166 @@ static void test_menu_cancelmode(void)
DestroyWindow( hwnd);
}
/* show menu trees have a maximum depth */
static void test_menu_maxdepth(void)
{
#define NR_MENUS 100
HMENU hmenus[ NR_MENUS];
int i;
DWORD ret;
SetLastError(12345678);
for( i = 0; i < NR_MENUS; i++) {
hmenus[i] = CreatePopupMenu();
if( !hmenus[i]) break;
}
ok( i == NR_MENUS, "could not create more than %d menu's\n", i);
for( i = 1; i < NR_MENUS; i++) {
ret = AppendMenuA( hmenus[i], MF_POPUP, (UINT_PTR)hmenus[i-1],"test");
if( !ret) break;
}
trace("Maximum depth is %d\n", i);
ok( GetLastError() == 12345678, "unexpected error %d\n", GetLastError());
ok( i < NR_MENUS ||
broken( i == NR_MENUS), /* win98, NT */
"no ( or very large) limit on menu depth!\n");
for( i = 0; i < NR_MENUS; i++)
DestroyMenu( hmenus[i]);
}
/* bug #12171 */
static void test_menu_circref(void)
{
HMENU menu1, menu2;
DWORD ret;
menu1 = CreatePopupMenu();
menu2 = CreatePopupMenu();
ok( menu1 && menu2, "error creating menus.\n");
ret = AppendMenuA( menu1, MF_POPUP, (UINT_PTR)menu2, "winetest");
ok( ret, "AppendMenu failed, error is %d\n", GetLastError());
ret = AppendMenuA( menu1, MF_STRING | MF_HILITE, 123, "winetest");
ok( ret, "AppendMenu failed, error is %d\n", GetLastError());
/* app chooses an id that happens to clash with its own hmenu */
ret = AppendMenuA( menu2, MF_STRING, (UINT_PTR)menu2, "winetest");
ok( ret, "AppendMenu failed, error is %d\n", GetLastError());
/* now attempt to change the string of the first item of menu1 */
ret = ModifyMenuA( menu1, (UINT_PTR)menu2, MF_POPUP, (UINT_PTR)menu2, "menu 2");
ok( !ret ||
broken( ret), /* win98, NT */
"ModifyMenu should have failed.\n");
if( !ret) { /* will probably stack fault if the ModifyMenu succeeded */
ret = GetMenuState( menu1, 123, 0);
ok( ret == MF_HILITE, "GetMenuState returned %x\n",ret);
}
DestroyMenu( menu2);
DestroyMenu( menu1);
}
/* test how the menu texts are aligned when the menu items have
* different combinations of text and bitmaps (bug #13350) */
static void test_menualign(void)
{
BYTE bmfill[300];
HMENU menu;
HBITMAP hbm1, hbm2, hbm3;
MENUITEMINFO mii = { sizeof(MENUITEMINFO)};
DWORD ret;
HWND hwnd;
MENUINFO mi = { sizeof( MENUINFO)};
if( !winetest_interactive) {
skip( "interactive alignment tests.\n");
return;
}
hwnd = CreateWindowEx(0,
"STATIC",
"Menu text alignment Test\nPlease make a selection.",
WS_OVERLAPPEDWINDOW,
100, 100,
300, 300,
NULL, NULL, 0, NULL);
ShowWindow( hwnd, SW_SHOW);
/* create bitmaps */
memset( bmfill, 0xcc, sizeof( bmfill));
hbm1 = CreateBitmap( 10,10,1,1,bmfill);
hbm2 = CreateBitmap( 20,20,1,1,bmfill);
hbm3 = CreateBitmap( 50,6,1,1,bmfill);
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( 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;
mii.hbmpItem = hbm1;
mii.dwTypeData = (LPSTR) " OK: menu texts are correctly left-aligned.";
ret = InsertMenuItem( menu, -1, TRUE, &mii);
ok( ret, "InsertMenuItem() failed\n");
mii.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_ID ;
mii.wID = 2;
mii.hbmpItem = hbm2;
mii.dwTypeData = (LPSTR) " FAIL: menu texts are NOT left-aligned.";
ret = InsertMenuItem( menu, -1, TRUE, &mii);
ok( ret, "InsertMenuItem() failed\n");
ret = TrackPopupMenu( menu, TPM_RETURNCMD, 110, 200, 0, hwnd, NULL);
ok( ret != 2, "User indicated that menu text alignment test 1 failed %d\n", ret);
/* test 2*/
mii.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_ID;
mii.wID = 3;
mii.hbmpItem = hbm3;
mii.dwTypeData = NULL;
ret = InsertMenuItem( menu, 0, TRUE, &mii);
ok( ret, "InsertMenuItem() failed\n");
mii.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_ID;
mii.wID = 1;
mii.hbmpItem = hbm1;
/* make the text a bit longer, to keep it readable */
/* this bug is on winXP and reproduced on wine */
mii.dwTypeData = (LPSTR) " OK: menu texts are to the right of the bitmaps........";
ret = SetMenuItemInfo( menu, 1, TRUE, &mii);
ok( ret, "SetMenuItemInfo() failed\n");
mii.wID = 2;
mii.hbmpItem = hbm2;
mii.dwTypeData = (LPSTR) " FAIL: menu texts are below the first bitmap. ";
ret = SetMenuItemInfo( menu, 2, TRUE, &mii);
ok( ret, "SetMenuItemInfo() failed\n");
ret = TrackPopupMenu( menu, TPM_RETURNCMD, 110, 200, 0, hwnd, NULL);
ok( ret != 2, "User indicated that menu text alignment test 2 failed %d\n", ret);
/* test 3 */
mii.fMask = MIIM_TYPE | MIIM_ID;
mii.wID = 3;
mii.fType = MFT_BITMAP;
mii.dwTypeData = (LPSTR) hbm3;
ret = SetMenuItemInfo( menu, 0, TRUE, &mii);
ok( ret, "SetMenuItemInfo() failed\n");
mii.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_ID;
mii.wID = 1;
mii.hbmpItem = NULL;
mii.dwTypeData = (LPSTR) " OK: menu texts are below the bitmap.";
ret = SetMenuItemInfo( menu, 1, TRUE, &mii);
ok( ret, "SetMenuItemInfo() failed\n");
mii.wID = 2;
mii.hbmpItem = NULL;
mii.dwTypeData = (LPSTR) " FAIL: menu texts are NOT below the bitmap.";
ret = SetMenuItemInfo( menu, 2, TRUE, &mii);
ok( ret, "SetMenuItemInfo() failed\n");
ret = TrackPopupMenu( menu, TPM_RETURNCMD, 110, 200, 0, hwnd, NULL);
ok( ret != 2, "User indicated that menu text alignment test 3 failed %d\n", ret);
/* cleanup */
DeleteObject( hbm1);
DeleteObject( hbm2);
DeleteObject( hbm3);
DestroyMenu( menu);
DestroyWindow( hwnd);
}
START_TEST(menu)
{
init_function_pointers();
@ -2947,6 +3185,7 @@ START_TEST(menu)
test_CheckMenuRadioItem();
test_menu_resource_layout();
test_InsertMenu();
test_menualign();
}
register_menu_check_class();
@ -2970,4 +3209,6 @@ START_TEST(menu)
test_menu_hilitemenuitem();
test_menu_trackpopupmenu();
test_menu_cancelmode();
test_menu_maxdepth();
test_menu_circref();
}

View file

@ -581,7 +581,7 @@ static const struct message WmShowMinOverlappedSeq[] = {
{ WM_GETTEXT, sent|defwinproc|optional },
{ WM_WINDOWPOSCHANGED, sent },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED },
{ WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 },
{ WM_NCCALCSIZE, sent|optional },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
@ -1004,7 +1004,7 @@ static const struct message WmShowChildInvisibleParentSeq_1[] = {
{ WM_CHILDACTIVATE, sent|optional },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED },
{ WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
{ EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
/* FIXME: Wine creates an icon/title window while Windows doesn't */
@ -1044,7 +1044,7 @@ static const struct message WmShowChildInvisibleParentSeq_3[] = {
{ WM_CHILDACTIVATE, sent },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED },
{ WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
{ EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
/* FIXME: Wine creates an icon/title window while Windows doesn't */
@ -1065,7 +1065,7 @@ static const struct message WmShowChildInvisibleParentSeq_4[] = {
{ EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED },
{ WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
{ EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
/* FIXME: Wine creates an icon/title window while Windows doesn't */
@ -3186,7 +3186,7 @@ static const struct message WmMinimizeMDIchildVisibleSeq[] = {
{ WM_NCCALCSIZE, sent|wparam, 1 },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOCLIENTSIZE|SWP_STATECHANGED },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED },
{ WM_SIZE, sent|defwinproc|wparam|lparam, SIZE_MINIMIZED, 0 },
{ WM_CHILDACTIVATE, sent|wparam|lparam|defwinproc, 0, 0 },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
{ EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
@ -5209,6 +5209,49 @@ static const struct message WmSetFontButtonSeq[] =
{ WM_CTLCOLORBTN, sent|defwinproc },
{ 0 }
};
static const struct message WmSetStyleButtonSeq[] =
{
{ BM_SETSTYLE, sent },
{ WM_APP, sent|wparam|lparam, 0, 0 },
{ WM_PAINT, sent },
{ WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */
{ WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
{ WM_CTLCOLORBTN, sent|parent },
{ 0 }
};
static const struct message WmSetStyleStaticSeq[] =
{
{ BM_SETSTYLE, sent },
{ WM_APP, sent|wparam|lparam, 0, 0 },
{ WM_PAINT, sent },
{ WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */
{ WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
{ WM_CTLCOLORSTATIC, sent|parent },
{ 0 }
};
static const struct message WmSetStyleUserSeq[] =
{
{ BM_SETSTYLE, sent },
{ WM_APP, sent|wparam|lparam, 0, 0 },
{ WM_PAINT, sent },
{ WM_NCPAINT, sent|defwinproc|optional }, /* FIXME: Wine sends it */
{ WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
{ WM_CTLCOLORBTN, sent|parent },
{ WM_COMMAND, sent|wparam|parent, MAKEWPARAM(ID_BUTTON, BN_PAINT) },
{ 0 }
};
static const struct message WmSetStyleOwnerdrawSeq[] =
{
{ BM_SETSTYLE, sent },
{ WM_APP, sent|wparam|lparam, 0, 0 },
{ WM_PAINT, sent },
{ WM_NCPAINT, sent|optional }, /* FIXME: Wine sends it */
{ WM_ERASEBKGND, sent|defwinproc|optional }, /* Win9x doesn't send it */
{ WM_CTLCOLORBTN, sent|parent },
{ WM_CTLCOLORBTN, sent|parent|optional }, /* Win9x doesn't send it */
{ WM_DRAWITEM, sent|wparam|lparam|parent, ID_BUTTON, 0x000010e4 },
{ 0 }
};
static WNDPROC old_button_proc;
@ -5268,29 +5311,30 @@ static void test_button_messages(void)
DWORD dlg_code;
const struct message *setfocus;
const struct message *killfocus;
const struct message *setstyle;
} button[] = {
{ BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
WmSetFocusButtonSeq, WmKillFocusButtonSeq },
WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleButtonSeq },
{ BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
WmSetFocusButtonSeq, WmKillFocusButtonSeq },
WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleButtonSeq },
{ BS_CHECKBOX, DLGC_BUTTON,
WmSetFocusStaticSeq, WmKillFocusStaticSeq },
WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq },
{ BS_AUTOCHECKBOX, DLGC_BUTTON,
WmSetFocusStaticSeq, WmKillFocusStaticSeq },
WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq },
{ BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
WmSetFocusStaticSeq, WmKillFocusStaticSeq },
WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq },
{ BS_3STATE, DLGC_BUTTON,
WmSetFocusStaticSeq, WmKillFocusStaticSeq },
WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq },
{ BS_AUTO3STATE, DLGC_BUTTON,
WmSetFocusStaticSeq, WmKillFocusStaticSeq },
WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq },
{ BS_GROUPBOX, DLGC_STATIC,
WmSetFocusStaticSeq, WmKillFocusStaticSeq },
WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq },
{ BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
WmSetFocusButtonSeq, WmKillFocusButtonSeq },
WmSetFocusButtonSeq, WmKillFocusButtonSeq, WmSetStyleUserSeq },
{ BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
WmSetFocusStaticSeq, WmKillFocusStaticSeq },
WmSetFocusStaticSeq, WmKillFocusStaticSeq, WmSetStyleStaticSeq },
{ BS_OWNERDRAW, DLGC_BUTTON,
WmSetFocusOwnerdrawSeq, WmKillFocusOwnerdrawSeq }
WmSetFocusOwnerdrawSeq, WmKillFocusOwnerdrawSeq, WmSetStyleOwnerdrawSeq }
};
unsigned int i;
HWND hwnd, parent;
@ -5319,6 +5363,8 @@ static void test_button_messages(void)
MSG msg;
DWORD style;
trace("button style %08x\n", button[i].style);
hwnd = CreateWindowExA(0, "my_button_class", "test", button[i].style | WS_CHILD | BS_NOTIFY,
0, 0, 50, 14, parent, (HMENU)ID_BUTTON, 0, NULL);
ok(hwnd != 0, "Failed to create button window\n");
@ -5327,9 +5373,9 @@ static void test_button_messages(void)
style &= ~(WS_CHILD | BS_NOTIFY);
/* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */
if (button[i].style == BS_USERBUTTON)
todo_wine ok(style == BS_PUSHBUTTON, "expected style BS_PUSHBUTTON got %x\n", style);
ok(style == BS_PUSHBUTTON, "expected style BS_PUSHBUTTON got %x\n", style);
else
ok(style == button[i].style, "expected style %x got %x\n", button[i].style, style);
ok(style == button[i].style, "expected style %x got %x\n", button[i].style, style);
dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
ok(dlg_code == button[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code);
@ -5342,7 +5388,6 @@ static void test_button_messages(void)
log_all_parent_messages++;
trace("button style %08x\n", button[i].style);
ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
SetFocus(hwnd);
SendMessage(hwnd, WM_APP, 0, 0); /* place a separator mark here */
@ -5354,9 +5399,20 @@ static void test_button_messages(void)
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
ok_sequence(button[i].killfocus, "SetFocus(0) on a button", FALSE);
ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
SendMessage(hwnd, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE);
SendMessage(hwnd, WM_APP, 0, 0); /* place a separator mark here */
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
ok_sequence(button[i].setstyle, "BM_SETSTYLE on a button", FALSE);
style = GetWindowLongA(hwnd, GWL_STYLE);
style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY);
/* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */
ok(style == button[i].style, "expected style %x got %x\n", button[i].style, style);
log_all_parent_messages--;
ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
DestroyWindow(hwnd);
}
@ -10198,7 +10254,7 @@ static const struct message WmShowMinimized_1[] = {
{ WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* win2000 doesn't send it */
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|wparam|defwinproc, SIZE_MINIMIZED },
{ WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 },
{ 0 }
};
static const struct message WmMinimize_1[] = {
@ -10208,7 +10264,7 @@ static const struct message WmMinimize_1[] = {
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|wparam|defwinproc, SIZE_MINIMIZED },
{ WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 },
{ 0 }
};
static const struct message WmMinimize_2[] = {
@ -10217,7 +10273,7 @@ static const struct message WmMinimize_2[] = {
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|wparam|defwinproc, SIZE_MINIMIZED },
{ WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 },
{ 0 }
};
static const struct message WmMinimize_3[] = {
@ -10225,7 +10281,7 @@ static const struct message WmMinimize_3[] = {
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|wparam|defwinproc, SIZE_MINIMIZED },
{ WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 },
{ 0 }
};
static const struct message WmShowMinNoActivate[] = {
@ -10233,7 +10289,7 @@ static const struct message WmShowMinNoActivate[] = {
{ WM_WINDOWPOSCHANGING, sent },
{ WM_WINDOWPOSCHANGED, sent },
{ WM_MOVE, sent|defwinproc|optional },
{ WM_SIZE, sent|wparam|defwinproc|optional, SIZE_MINIMIZED },
{ WM_SIZE, sent|wparam|lparam|defwinproc|optional, SIZE_MINIMIZED, 0 },
{ 0 }
};
static const struct message WmMinMax_1[] = {
@ -10259,7 +10315,7 @@ static const struct message WmMinMax_3[] = {
{ WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
{ WM_MOVE, sent|defwinproc|optional },
{ WM_SIZE, sent|wparam|defwinproc|optional, SIZE_MINIMIZED },
{ WM_SIZE, sent|wparam|lparam|defwinproc|optional, SIZE_MINIMIZED, 0 },
{ 0 }
};
static const struct message WmMinMax_4[] = {

View file

@ -4859,6 +4859,75 @@ static void test_Expose(void)
DestroyWindow(mw);
}
static LRESULT CALLBACK TestNCRedraw_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static UINT ncredrawflags;
PAINTSTRUCT ps;
switch(msg)
{
case WM_CREATE:
ncredrawflags = *(UINT *) (((CREATESTRUCT *)lParam)->lpCreateParams);
return 0;
case WM_NCPAINT:
RedrawWindow(hwnd, NULL, NULL, ncredrawflags);
break;
case WM_PAINT:
BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
static void run_NCRedrawLoop(UINT flags)
{
HWND hwnd;
MSG msg;
UINT loopcount = 0;
hwnd = CreateWindowA("TestNCRedrawClass", "MainWindow",
WS_OVERLAPPEDWINDOW, 0, 0, 200, 100,
NULL, NULL, 0, &flags);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
while(PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE) != 0)
{
if (msg.message == WM_PAINT) loopcount++;
if (loopcount >= 100) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT);
}
if (flags == (RDW_INVALIDATE | RDW_FRAME))
todo_wine ok(loopcount < 100, "Detected infinite WM_PAINT loop (%x).\n", flags);
else
ok(loopcount < 100, "Detected infinite WM_PAINT loop (%x).\n", flags);
DestroyWindow(hwnd);
}
static void test_NCRedraw(void)
{
WNDCLASSA wndclass;
wndclass.lpszClassName = "TestNCRedrawClass";
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = TestNCRedraw_WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = 0;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
RegisterClassA(&wndclass);
run_NCRedrawLoop(RDW_INVALIDATE | RDW_FRAME);
run_NCRedrawLoop(RDW_INVALIDATE);
}
static void test_GetWindowModuleFileName(void)
{
HWND hwnd;
@ -5647,6 +5716,7 @@ START_TEST(win)
test_SetMenu(hwndMain);
test_SetFocus(hwndMain);
test_SetActiveWindow(hwndMain);
test_NCRedraw();
test_children_zorder(hwndMain);
test_popup_zorder(hwndMain2, hwndMain);