user32: Add workaround for removed SC_TASKLIST system menu item.
Word 95 assumes that the item exists. Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
8693805431
commit
c82626a4c1
|
@ -4001,7 +4001,12 @@ BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
|
|||
else
|
||||
TRACE("%p %d %04x %04lx %p\n", hMenu, pos, flags, id, str );
|
||||
|
||||
if (!(item = MENU_FindItem( &hMenu, &pos, flags ))) return FALSE;
|
||||
if (!(item = MENU_FindItem( &hMenu, &pos, flags )))
|
||||
{
|
||||
/* workaround for Word 95: pretend that SC_TASKLIST item exists */
|
||||
if (pos == SC_TASKLIST && !(flags & MF_BYPOSITION)) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
MENU_GetMenu(hMenu)->Height = 0; /* force size recalculate */
|
||||
MENU_mnu2mnuii( flags, id, str, &mii);
|
||||
return SetMenuItemInfo_common( item, &mii, TRUE);
|
||||
|
@ -4873,14 +4878,20 @@ static BOOL MENU_NormalizeMenuItemInfoStruct( const MENUITEMINFOW *pmii_in,
|
|||
BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
|
||||
const MENUITEMINFOA *lpmii)
|
||||
{
|
||||
MENUITEM *menuitem;
|
||||
MENUITEMINFOW mii;
|
||||
|
||||
TRACE("hmenu %p, item %u, by pos %d, info %p\n", hmenu, item, bypos, lpmii);
|
||||
|
||||
if (!MENU_NormalizeMenuItemInfoStruct( (const MENUITEMINFOW *)lpmii, &mii )) return FALSE;
|
||||
|
||||
return SetMenuItemInfo_common(MENU_FindItem(&hmenu, &item, bypos? MF_BYPOSITION : 0),
|
||||
&mii, FALSE);
|
||||
if (!(menuitem = MENU_FindItem( &hmenu, &item, bypos? MF_BYPOSITION : 0 )))
|
||||
{
|
||||
/* workaround for Word 95: pretend that SC_TASKLIST item exists */
|
||||
if (item == SC_TASKLIST && !bypos) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
return SetMenuItemInfo_common( menuitem, &mii, FALSE );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -4889,13 +4900,19 @@ BOOL WINAPI SetMenuItemInfoA(HMENU hmenu, UINT item, BOOL bypos,
|
|||
BOOL WINAPI SetMenuItemInfoW(HMENU hmenu, UINT item, BOOL bypos,
|
||||
const MENUITEMINFOW *lpmii)
|
||||
{
|
||||
MENUITEM *menuitem;
|
||||
MENUITEMINFOW mii;
|
||||
|
||||
TRACE("hmenu %p, item %u, by pos %d, info %p\n", hmenu, item, bypos, lpmii);
|
||||
|
||||
if (!MENU_NormalizeMenuItemInfoStruct( lpmii, &mii )) return FALSE;
|
||||
return SetMenuItemInfo_common(MENU_FindItem(&hmenu,
|
||||
&item, bypos? MF_BYPOSITION : 0), &mii, TRUE);
|
||||
if (!(menuitem = MENU_FindItem( &hmenu, &item, bypos? MF_BYPOSITION : 0 )))
|
||||
{
|
||||
/* workaround for Word 95: pretend that SC_TASKLIST item exists */
|
||||
if (item == SC_TASKLIST && !bypos) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
return SetMenuItemInfo_common( menuitem, &mii, TRUE );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
|
|
@ -405,6 +405,191 @@ static void test_getmenubarinfo(void)
|
|||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
static void test_system_menu(void)
|
||||
{
|
||||
WCHAR testW[] = {'t','e','s','t',0};
|
||||
BOOL ret;
|
||||
HMENU menu;
|
||||
HWND hwnd;
|
||||
MENUITEMINFOA info;
|
||||
MENUITEMINFOW infoW;
|
||||
char buffer[80];
|
||||
char found[0x200];
|
||||
int i, res;
|
||||
|
||||
hwnd = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atomMenuCheckClass), NULL,
|
||||
WS_SYSMENU | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
|
||||
menu = GetSystemMenu( hwnd, FALSE );
|
||||
ok( menu != NULL, "no system menu\n" );
|
||||
|
||||
for (i = 0xf000; i < 0xf200; i++)
|
||||
{
|
||||
memset( &info, 0xcc, sizeof(info) );
|
||||
info.cbSize = sizeof(info);
|
||||
info.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID;
|
||||
info.dwTypeData = buffer;
|
||||
info.cch = sizeof( buffer );
|
||||
ret = GetMenuItemInfoA( menu, i, FALSE, &info );
|
||||
if (ret) trace( "found %x: '%s'\n", i, buffer );
|
||||
switch (i)
|
||||
{
|
||||
case SC_RESTORE:
|
||||
case SC_SIZE:
|
||||
case SC_MOVE:
|
||||
case SC_MINIMIZE:
|
||||
case SC_MAXIMIZE:
|
||||
case SC_CLOSE:
|
||||
ok( ret, "%x menu item not found\n", i );
|
||||
break;
|
||||
case SC_SCREENSAVE+1: /* used for the 'About Wine' entry, don't test */
|
||||
break;
|
||||
default:
|
||||
ok( !ret, "%x menu item found\n", i );
|
||||
break;
|
||||
}
|
||||
found[i - 0xf000] = ret;
|
||||
}
|
||||
|
||||
for (i = 0xf000; i < 0xf200; i++)
|
||||
{
|
||||
res = CheckMenuItem( menu, i, 0 );
|
||||
if (res == -1) ok( !found[i - 0xf000], "could not check existent item %x\n", i );
|
||||
else ok( found[i - 0xf000], "could check non-existent item %x\n", i );
|
||||
|
||||
res = EnableMenuItem( menu, i, 0 );
|
||||
if (res == -1) ok( !found[i - 0xf000], "could not enable existent item %x\n", i );
|
||||
else ok( found[i - 0xf000], "could enable non-existent item %x\n", i );
|
||||
|
||||
res = GetMenuState( menu, i, 0 );
|
||||
if (res == -1) ok( !found[i - 0xf000], "could not get state existent item %x\n", i );
|
||||
else ok( found[i - 0xf000], "could get state of non-existent item %x\n", i );
|
||||
|
||||
if (!found[i - 0xf000]) /* don't remove the existing ones */
|
||||
{
|
||||
ret = RemoveMenu( menu, i, 0 );
|
||||
ok( !ret, "could remove non-existent item %x\n", i );
|
||||
}
|
||||
|
||||
ret = ModifyMenuA( menu, i, 0, i, "test" );
|
||||
if (i == SC_TASKLIST) ok( ret, "failed to modify SC_TASKLIST\n" );
|
||||
else if (!ret) ok( !found[i - 0xf000], "could not modify existent item %x\n", i );
|
||||
else ok( found[i - 0xf000], "could modify non-existent item %x\n", i );
|
||||
|
||||
ret = ModifyMenuW( menu, i, 0, i, testW );
|
||||
if (i == SC_TASKLIST) ok( ret, "failed to modify SC_TASKLIST\n" );
|
||||
else if (!ret) ok( !found[i - 0xf000], "could not modify existent item %x\n", i );
|
||||
else ok( found[i - 0xf000], "could modify non-existent item %x\n", i );
|
||||
|
||||
ret = ModifyMenuA( menu, i, MF_BYPOSITION, i, "test" );
|
||||
ok( !ret, "could modify non-existent item %x\n", i );
|
||||
|
||||
strcpy( buffer, "test" );
|
||||
memset( &info, 0xcc, sizeof(info) );
|
||||
info.cbSize = sizeof(info);
|
||||
info.fMask = MIIM_STRING | MIIM_ID;
|
||||
info.wID = i;
|
||||
info.dwTypeData = buffer;
|
||||
info.cch = strlen( buffer );
|
||||
ret = SetMenuItemInfoA( menu, i, FALSE, &info );
|
||||
if (i == SC_TASKLIST) ok( ret, "failed to set SC_TASKLIST\n" );
|
||||
else if (!ret) ok( !found[i - 0xf000], "could not set existent item %x\n", i );
|
||||
else ok( found[i - 0xf000], "could set non-existent item %x\n", i );
|
||||
ret = SetMenuItemInfoA( menu, i, TRUE, &info );
|
||||
ok( !ret, "could modify non-existent item %x\n", i );
|
||||
|
||||
memset( &infoW, 0xcc, sizeof(infoW) );
|
||||
infoW.cbSize = sizeof(infoW);
|
||||
infoW.fMask = MIIM_STRING | MIIM_ID;
|
||||
infoW.wID = i;
|
||||
infoW.dwTypeData = testW;
|
||||
infoW.cch = lstrlenW( testW );
|
||||
ret = SetMenuItemInfoW( menu, i, FALSE, &infoW );
|
||||
if (i == SC_TASKLIST) ok( ret, "failed to set SC_TASKLIST\n" );
|
||||
else if (!ret) ok( !found[i - 0xf000], "could not set existent item %x\n", i );
|
||||
else ok( found[i - 0xf000], "could set non-existent item %x\n", i );
|
||||
ret = SetMenuItemInfoW( menu, i, TRUE, &infoW );
|
||||
ok( !ret, "could modify non-existent item %x\n", i );
|
||||
}
|
||||
|
||||
/* confirm that SC_TASKLIST still does not exist */
|
||||
for (i = 0xf000; i < 0xf200; i++)
|
||||
{
|
||||
memset( &info, 0xcc, sizeof(info) );
|
||||
info.cbSize = sizeof(info);
|
||||
info.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID;
|
||||
info.dwTypeData = buffer;
|
||||
info.cch = sizeof( buffer );
|
||||
ret = GetMenuItemInfoA( menu, i, FALSE, &info );
|
||||
switch (i)
|
||||
{
|
||||
case SC_RESTORE:
|
||||
case SC_SIZE:
|
||||
case SC_MOVE:
|
||||
case SC_MINIMIZE:
|
||||
case SC_MAXIMIZE:
|
||||
case SC_CLOSE:
|
||||
ok( ret, "%x menu item not found\n", i );
|
||||
break;
|
||||
case SC_SCREENSAVE+1: /* used for the 'About Wine' entry, don't test */
|
||||
break;
|
||||
default:
|
||||
ok( !ret, "%x menu item found\n", i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* now a normal (non-system) menu */
|
||||
|
||||
menu = CreateMenu();
|
||||
ok( menu != NULL, "CreateMenu failed with error %d\n", GetLastError() );
|
||||
|
||||
res = CheckMenuItem( menu, SC_TASKLIST, 0 );
|
||||
ok( res == -1, "CheckMenuItem succeeded\n" );
|
||||
res = EnableMenuItem( menu, SC_TASKLIST, 0 );
|
||||
ok( res == -1, "EnableMenuItem succeeded\n" );
|
||||
res = GetMenuState( menu, SC_TASKLIST, 0 );
|
||||
ok( res == -1, "GetMenuState succeeded\n" );
|
||||
ret = RemoveMenu( menu, SC_TASKLIST, 0 );
|
||||
ok( !ret, "RemoveMenu succeeded\n" );
|
||||
ret = ModifyMenuA( menu, SC_TASKLIST, 0, SC_TASKLIST, "test" );
|
||||
ok( ret, "ModifyMenuA failed err %d\n", GetLastError() );
|
||||
ret = ModifyMenuW( menu, SC_TASKLIST, 0, SC_TASKLIST, testW );
|
||||
ok( ret, "ModifyMenuW failed err %d\n", GetLastError() );
|
||||
ret = ModifyMenuA( menu, SC_TASKLIST-1, 0, SC_TASKLIST, "test" );
|
||||
ok( !ret, "ModifyMenu succeeded on SC_TASKLIST-1\n" );
|
||||
strcpy( buffer, "test" );
|
||||
memset( &info, 0xcc, sizeof(info) );
|
||||
info.cbSize = sizeof(info);
|
||||
info.fMask = MIIM_STRING | MIIM_ID;
|
||||
info.wID = SC_TASKLIST;
|
||||
info.dwTypeData = buffer;
|
||||
info.cch = strlen( buffer );
|
||||
ret = SetMenuItemInfoA( menu, SC_TASKLIST, FALSE, &info );
|
||||
ok( ret, "failed to set SC_TASKLIST\n" );
|
||||
ret = SetMenuItemInfoA( menu, SC_TASKLIST+1, FALSE, &info );
|
||||
ok( !ret, "succeeded setting SC_TASKLIST+1\n" );
|
||||
ret = SetMenuItemInfoA( menu, SC_TASKLIST, TRUE, &info );
|
||||
ok( !ret, "succeeded setting by position\n" );
|
||||
|
||||
memset( &infoW, 0xcc, sizeof(infoW) );
|
||||
infoW.cbSize = sizeof(infoW);
|
||||
infoW.fMask = MIIM_STRING | MIIM_ID;
|
||||
infoW.wID = SC_TASKLIST;
|
||||
infoW.dwTypeData = testW;
|
||||
infoW.cch = lstrlenW( testW );
|
||||
ret = SetMenuItemInfoW( menu, SC_TASKLIST, FALSE, &infoW );
|
||||
ok( ret, "failed to set SC_TASKLIST\n" );
|
||||
ret = SetMenuItemInfoW( menu, SC_TASKLIST+1, FALSE, &infoW );
|
||||
ok( !ret, "succeeded setting SC_TASKLIST+1\n" );
|
||||
ret = SetMenuItemInfoW( menu, SC_TASKLIST, TRUE, &infoW );
|
||||
ok( !ret, "succeeded setting by position\n" );
|
||||
|
||||
DestroyMenu( menu );
|
||||
DestroyWindow( hwnd );
|
||||
}
|
||||
|
||||
/* demonstrates that windows locks the menu object so that it is still valid
|
||||
* even after a client calls DestroyMenu on it */
|
||||
static void test_menu_locked_by_window(void)
|
||||
|
@ -4123,6 +4308,7 @@ if (0) /* FIXME: uncomment once Wine is fixed */
|
|||
START_TEST(menu)
|
||||
{
|
||||
init_function_pointers();
|
||||
register_menu_check_class();
|
||||
|
||||
/* Wine defines MENUITEMINFO for W2K and above. NT4 and below can't
|
||||
* handle that.
|
||||
|
@ -4136,10 +4322,9 @@ START_TEST(menu)
|
|||
test_menu_resource_layout();
|
||||
test_InsertMenu();
|
||||
test_menualign();
|
||||
test_system_menu();
|
||||
}
|
||||
|
||||
register_menu_check_class();
|
||||
|
||||
test_menu_locked_by_window();
|
||||
test_subpopup_locked_by_menu();
|
||||
test_menu_ownerdraw();
|
||||
|
|
Loading…
Reference in New Issue