// find sorted position after the last separator int FindSortedPos(HMENU hMenu, const char* text) { int pos = -1, nbItems = GetMenuItemCount(hMenu); #ifdef _WIN32 wchar_t widetext[4096], widebuf[4096]; MultiByteToWideChar(CP_UTF8, 0, text, -1, widetext, 4096); _locale_t locale = _create_locale(LC_ALL, ""); #else char buf[4096] = ""; #endif MENUITEMINFO mi = {sizeof(MENUITEMINFO),}; mi.fMask = MIIM_TYPE; for (int i=nbItems-1; i>=0 ; i--) { GetMenuItemInfo(hMenu, i, true, &mi); if (mi.fType == MFT_SEPARATOR) break; #ifdef _WIN32 GetMenuStringW(hMenu, i, widebuf, 4096, MF_BYPOSITION); if (_wcsnicoll_l(widetext, widebuf, 4096, locale) < 0) // setLocale() can break things (atof and comma as a decimal mark) so use temporary locale object pos = i; #else GetMenuString(hMenu, i, buf, sizeof(buf), MF_BYPOSITION); if (strcasecmp(text, buf) < 0) // not as good as on Win OS, e.g. French "Sélectionner" vs "Supprimer" pos = i; #endif } #ifdef _WIN32 _free_locale(locale); #endif return pos<0 ? nbItems : pos; }
static void test_OleUIAddVerbMenu(void) { static const WCHAR cadabraW[] = {'c','a','d','a','b','r','a',0}; HMENU hMenu, verbmenu; MENUITEMINFOW info; WCHAR buffW[50]; int count; BOOL ret; ret = OleUIAddVerbMenuW(NULL, NULL, NULL, 0, 0, 0, FALSE, 0, NULL); ok(!ret, "got %d\n", ret); verbmenu = (HMENU)0xdeadbeef; ret = OleUIAddVerbMenuW(NULL, NULL, NULL, 0, 0, 0, FALSE, 0, &verbmenu); ok(!ret, "got %d\n", ret); ok(verbmenu == NULL, "got %p\n", verbmenu); g_enumpos = 0; ret = OleUIAddVerbMenuW(&oleobject, NULL, NULL, 0, 0, 0, FALSE, 0, NULL); ok(!ret, "got %d\n", ret); hMenu = CreatePopupMenu(); memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); ret = InsertMenuItemW(hMenu, 0, TRUE, &info); ok(ret, "got %d\n", ret); count = GetMenuItemCount(hMenu); ok(count == 1, "got %d\n", count); g_enumpos = 0; ret = OleUIAddVerbMenuW(&oleobject, NULL, hMenu, 0, 0, 0, FALSE, 0, NULL); ok(!ret, "got %d\n", ret); count = GetMenuItemCount(hMenu); ok(count == 1, "got %d\n", count); ret = InsertMenuItemW(hMenu, 0, TRUE, &info); ok(ret, "got %d\n", ret); count = GetMenuItemCount(hMenu); ok(count == 2, "got %d\n", count); verbmenu = (HMENU)0xdeadbeef; g_enumpos = 0; ret = OleUIAddVerbMenuW(&oleobject, NULL, hMenu, 1, 0, 0, FALSE, 0, &verbmenu); ok(ret, "got %d\n", ret); ok(verbmenu == NULL, "got %p\n", verbmenu); count = GetMenuItemCount(hMenu); ok(count == 2, "got %d\n", count); /* object doesn't support EnumVerbs() */ g_enumverbsfail = TRUE; g_enumpos = 0; verbmenu = (HMENU)0xdeadbeef; ret = OleUIAddVerbMenuW(&oleobject, NULL, hMenu, 2, 0, 0, FALSE, 0, &verbmenu); ok(!ret, "got %d\n", ret); ok(verbmenu == NULL, "got %p\n", verbmenu); g_enumverbsfail = FALSE; /* added disabled item */ memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); info.fMask = MIIM_STATE|MIIM_SUBMENU; ret = GetMenuItemInfoW(hMenu, 2, TRUE, &info); ok(ret, "got %d\n", ret); ok(info.fState & MFS_DISABLED, "got state 0x%08x\n", info.fState); ok(info.hSubMenu == NULL, "got submenu %p\n", info.hSubMenu); count = GetMenuItemCount(hMenu); ok(count == 3, "got %d\n", count); /* now without object */ verbmenu = (HMENU)0xdeadbeef; ret = OleUIAddVerbMenuW(NULL, testW, hMenu, 3, 42, 0, FALSE, 0, &verbmenu); ok(!ret, "got %d\n", ret); ok(verbmenu == NULL, "got %p\n", verbmenu); memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); info.fMask = MIIM_STATE|MIIM_ID|MIIM_STRING|MIIM_SUBMENU; info.dwTypeData = buffW; info.cch = sizeof(buffW)/sizeof(WCHAR); ret = GetMenuItemInfoW(hMenu, 3, TRUE, &info); ok(ret, "got %d\n", ret); ok(info.fState == MF_GRAYED, "got state 0x%08x\n", info.fState); ok(info.wID == 42, "got id %d\n", info.wID); ok(info.hSubMenu == NULL, "got submenu %p\n", info.hSubMenu); count = GetMenuItemCount(hMenu); ok(count == 4, "got %d\n", count); verbmenu = (HMENU)0xdeadbeef; g_enumpos = 0; ret = OleUIAddVerbMenuW(&oleobject, NULL, hMenu, 4, 0, 0, FALSE, 0, &verbmenu); ok(ret, "got %d\n", ret); ok(verbmenu == NULL, "got %p\n", verbmenu); /* check newly added item */ memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); info.fMask = MIIM_STRING|MIIM_STATE|MIIM_SUBMENU; info.dwTypeData = buffW; info.cch = sizeof(buffW)/sizeof(WCHAR); ret = GetMenuItemInfoW(hMenu, 4, TRUE, &info); ok(ret, "got %d\n", ret); /* Item string contains verb, usertype and localized string for 'Object' word, exact format depends on localization. */ ok(strstrW(buffW, verbW) != NULL, "str %s\n", wine_dbgstr_w(buffW)); ok(info.fState == 0, "got state 0x%08x\n", info.fState); ok(info.hSubMenu == NULL, "got submenu %p\n", info.hSubMenu); count = GetMenuItemCount(hMenu); ok(count == 5, "got %d\n", count); DestroyMenu(hMenu); /* try to add verb menu repeatedly, with same id */ hMenu = CreatePopupMenu(); count = GetMenuItemCount(hMenu); ok(count == 0, "got %d\n", count); verbmenu = NULL; ret = OleUIAddVerbMenuW(NULL, NULL, hMenu, 0, 5, 10, TRUE, 3, &verbmenu); ok(!ret, "got %d\n", ret); ok(verbmenu == NULL, "got %p\n", verbmenu); count = GetMenuItemCount(hMenu); ok(count == 1, "got %d\n", count); verbmenu = NULL; ret = OleUIAddVerbMenuW(NULL, NULL, hMenu, 0, 5, 10, TRUE, 3, &verbmenu); ok(!ret, "got %d\n", ret); ok(verbmenu == NULL, "got %p\n", verbmenu); count = GetMenuItemCount(hMenu); ok(count == 1, "got %d\n", count); /* same position, different id */ verbmenu = NULL; ret = OleUIAddVerbMenuW(NULL, NULL, hMenu, 0, 6, 10, TRUE, 3, &verbmenu); ok(!ret, "got %d\n", ret); ok(verbmenu == NULL, "got %p\n", verbmenu); count = GetMenuItemCount(hMenu); ok(count == 1, "got %d\n", count); /* change added item string and state */ memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); info.fMask = MIIM_STRING|MIIM_STATE; info.fState = MFS_ENABLED; info.dwTypeData = buffW; lstrcpyW(buffW, cadabraW); ret = SetMenuItemInfoW(hMenu, 0, TRUE, &info); ok(ret, "got %d\n", ret); buffW[0] = 0; GetMenuStringW(hMenu, 0, buffW, sizeof(buffW)/sizeof(buffW[0]), MF_BYPOSITION); ok(!lstrcmpW(buffW, cadabraW), "got %s\n", wine_dbgstr_w(buffW)); verbmenu = NULL; ret = OleUIAddVerbMenuW(NULL, NULL, hMenu, 0, 5, 10, TRUE, 3, &verbmenu); ok(!ret, "got %d\n", ret); ok(verbmenu == NULL, "got %p\n", verbmenu); memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); info.fMask = MIIM_STRING|MIIM_STATE; buffW[0] = 0; info.dwTypeData = buffW; info.cch = sizeof(buffW)/sizeof(WCHAR); ret = GetMenuItemInfoW(hMenu, 0, TRUE, &info); ok(ret, "got %d\n", ret); ok(lstrcmpW(buffW, cadabraW), "got %s\n", wine_dbgstr_w(buffW)); ok(info.fState == MF_GRAYED, "got state 0x%08x\n", info.fState); count = GetMenuItemCount(hMenu); ok(count == 1, "got %d\n", count); DestroyMenu(hMenu); }
BOOL OnCreate(HWND hWnd) { HMENU hMenu; HMENU hEditMenu; HMENU hViewMenu; HMENU hShutMenu; HMENU hUpdateSpeedMenu; HMENU hCPUHistoryMenu; int nActivePage; int nParts[3]; RECT rc; WCHAR szTemp[256]; WCHAR szLogOffItem[MAX_PATH]; LPWSTR lpUserName; TCITEM item; DWORD len = 0; SendMessageW(hMainWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIconW(hInst, MAKEINTRESOURCEW(IDI_TASKMANAGER))); /* Initialize the Windows Common Controls DLL */ InitCommonControls(); /* Get the minimum window sizes */ GetWindowRect(hWnd, &rc); nMinimumWidth = (rc.right - rc.left); nMinimumHeight = (rc.bottom - rc.top); /* Create the status bar */ hStatusWnd = CreateStatusWindow(WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|SBT_NOBORDERS, L"", hWnd, STATUS_WINDOW); if(!hStatusWnd) return FALSE; /* Create the status bar panes */ nParts[0] = STATUS_SIZE1; nParts[1] = STATUS_SIZE2; nParts[2] = STATUS_SIZE3; SendMessageW(hStatusWnd, SB_SETPARTS, 3, (LPARAM) (LPINT) nParts); /* Create tab pages */ hTabWnd = GetDlgItem(hWnd, IDC_TAB); #if 1 hApplicationPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_APPLICATION_PAGE), hWnd, ApplicationPageWndProc); EnableDialogTheme(hApplicationPage); hProcessPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PROCESS_PAGE), hWnd, ProcessPageWndProc); EnableDialogTheme(hProcessPage); hPerformancePage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PERFORMANCE_PAGE), hWnd, PerformancePageWndProc); EnableDialogTheme(hPerformancePage); #else hApplicationPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_APPLICATION_PAGE), hTabWnd, ApplicationPageWndProc); EnableDialogTheme(hApplicationPage); hProcessPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PROCESS_PAGE), hTabWnd, ProcessPageWndProc); EnableDialogTheme(hProcessPage); hPerformancePage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PERFORMANCE_PAGE), hTabWnd, PerformancePageWndProc); EnableDialogTheme(hPerformancePage); #endif /* Insert tabs */ LoadStringW(hInst, IDS_TAB_APPS, szTemp, 256); memset(&item, 0, sizeof(TCITEM)); item.mask = TCIF_TEXT; item.pszText = szTemp; (void)TabCtrl_InsertItem(hTabWnd, 0, &item); LoadStringW(hInst, IDS_TAB_PROCESSES, szTemp, 256); memset(&item, 0, sizeof(TCITEM)); item.mask = TCIF_TEXT; item.pszText = szTemp; (void)TabCtrl_InsertItem(hTabWnd, 1, &item); LoadStringW(hInst, IDS_TAB_PERFORMANCE, szTemp, 256); memset(&item, 0, sizeof(TCITEM)); item.mask = TCIF_TEXT; item.pszText = szTemp; (void)TabCtrl_InsertItem(hTabWnd, 2, &item); /* Size everything correctly */ GetClientRect(hWnd, &rc); nOldWidth = rc.right; nOldHeight = rc.bottom; /* nOldStartX = rc.left; */ /*nOldStartY = rc.top; */ #define PAGE_OFFSET_LEFT 17 #define PAGE_OFFSET_TOP 72 #define PAGE_OFFSET_WIDTH (PAGE_OFFSET_LEFT*2) #define PAGE_OFFSET_HEIGHT (PAGE_OFFSET_TOP+32) if ((TaskManagerSettings.Left != 0) || (TaskManagerSettings.Top != 0) || (TaskManagerSettings.Right != 0) || (TaskManagerSettings.Bottom != 0)) { MoveWindow(hWnd, TaskManagerSettings.Left, TaskManagerSettings.Top, TaskManagerSettings.Right - TaskManagerSettings.Left, TaskManagerSettings.Bottom - TaskManagerSettings.Top, TRUE); #ifdef __GNUC__TEST__ MoveWindow(hApplicationPage, TaskManagerSettings.Left + PAGE_OFFSET_LEFT, TaskManagerSettings.Top + PAGE_OFFSET_TOP, TaskManagerSettings.Right - TaskManagerSettings.Left - PAGE_OFFSET_WIDTH, TaskManagerSettings.Bottom - TaskManagerSettings.Top - PAGE_OFFSET_HEIGHT, FALSE); MoveWindow(hProcessPage, TaskManagerSettings.Left + PAGE_OFFSET_LEFT, TaskManagerSettings.Top + PAGE_OFFSET_TOP, TaskManagerSettings.Right - TaskManagerSettings.Left - PAGE_OFFSET_WIDTH, TaskManagerSettings.Bottom - TaskManagerSettings.Top - PAGE_OFFSET_HEIGHT, FALSE); MoveWindow(hPerformancePage, TaskManagerSettings.Left + PAGE_OFFSET_LEFT, TaskManagerSettings.Top + PAGE_OFFSET_TOP, TaskManagerSettings.Right - TaskManagerSettings.Left - PAGE_OFFSET_WIDTH, TaskManagerSettings.Bottom - TaskManagerSettings.Top - PAGE_OFFSET_HEIGHT, FALSE); #endif } if (TaskManagerSettings.Maximized) ShowWindow(hWnd, SW_MAXIMIZE); /* Set the always on top style */ hMenu = GetMenu(hWnd); hEditMenu = GetSubMenu(hMenu, 1); hViewMenu = GetSubMenu(hMenu, 2); hShutMenu = GetSubMenu(hMenu, 4); hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1); hCPUHistoryMenu = GetSubMenu(hViewMenu, 7); /* Check or uncheck the always on top menu item */ if (TaskManagerSettings.AlwaysOnTop) { CheckMenuItem(hEditMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND|MF_CHECKED); SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); } else { CheckMenuItem(hEditMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND|MF_UNCHECKED); SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); } /* Check or uncheck the minimize on use menu item */ if (TaskManagerSettings.MinimizeOnUse) CheckMenuItem(hEditMenu, ID_OPTIONS_MINIMIZEONUSE, MF_BYCOMMAND|MF_CHECKED); else CheckMenuItem(hEditMenu, ID_OPTIONS_MINIMIZEONUSE, MF_BYCOMMAND|MF_UNCHECKED); /* Check or uncheck the hide when minimized menu item */ if (TaskManagerSettings.HideWhenMinimized) CheckMenuItem(hEditMenu, ID_OPTIONS_HIDEWHENMINIMIZED, MF_BYCOMMAND|MF_CHECKED); else CheckMenuItem(hEditMenu, ID_OPTIONS_HIDEWHENMINIMIZED, MF_BYCOMMAND|MF_UNCHECKED); /* Check or uncheck the show 16-bit tasks menu item */ if (TaskManagerSettings.Show16BitTasks) CheckMenuItem(hEditMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_CHECKED); else CheckMenuItem(hEditMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_UNCHECKED); /* Set the view mode */ CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, TaskManagerSettings.ViewMode, MF_BYCOMMAND); if (TaskManagerSettings.ShowKernelTimes) CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED); else CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED); CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, TaskManagerSettings.UpdateSpeed, MF_BYCOMMAND); if (TaskManagerSettings.CPUHistory_OneGraphPerCPU) CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND); else CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND); nActivePage = TaskManagerSettings.ActiveTabPage; TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 0); TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 1); TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 2); TabCtrl_SetCurFocus/*Sel*/(hTabWnd, nActivePage); /* Set the username in the "Log Off %s" item of the Shutdown menu */ /* 1- Get the menu item text and store it temporarily */ GetMenuStringW(hShutMenu, ID_SHUTDOWN_LOGOFF, szTemp, 256, MF_BYCOMMAND); /* 2- Retrieve the username length first, then allocate a buffer for it and call it again */ if (!GetUserNameW(NULL, &len) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { lpUserName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); if (lpUserName && GetUserNameW(lpUserName, &len)) { _snwprintf(szLogOffItem, sizeof(szLogOffItem)/sizeof(szLogOffItem[0]), szTemp, lpUserName); szLogOffItem[sizeof(szLogOffItem)/sizeof(szLogOffItem[0]) - 1] = UNICODE_NULL; } else { _snwprintf(szLogOffItem, sizeof(szLogOffItem)/sizeof(szLogOffItem[0]), szTemp, L"n/a"); } if (lpUserName) HeapFree(GetProcessHeap(), 0, lpUserName); } else { _snwprintf(szLogOffItem, sizeof(szLogOffItem)/sizeof(szLogOffItem[0]), szTemp, L"n/a"); } /* 3- Set the menu item text to its formatted counterpart */ ModifyMenuW(hShutMenu, ID_SHUTDOWN_LOGOFF, MF_BYCOMMAND | MF_STRING, ID_SHUTDOWN_LOGOFF, szLogOffItem); /* Setup update speed */ SetUpdateSpeed(hWnd); /* * Refresh the performance data * Sample it twice so we can establish * the delta values & cpu usage */ PerfDataRefresh(); PerfDataRefresh(); RefreshApplicationPage(); RefreshProcessPage(); RefreshPerformancePage(); TrayIcon_ShellAddTrayIcon(); return TRUE; }