#include "precomp.h"
#include <commoncontrols.h>
+#include <traycmd.h>
HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu);
static const WCHAR szTrayWndClass[] = L"Shell_TrayWnd";
+struct EFFECTIVE_INFO
+{
+ HWND hwndFound;
+ HWND hwndDesktop;
+ HWND hwndProgman;
+ HWND hTrayWnd;
+ BOOL bMustBeInMonitor;
+};
+
+static BOOL CALLBACK
+FindEffectiveProc(HWND hwnd, LPARAM lParam)
+{
+ EFFECTIVE_INFO *pei = (EFFECTIVE_INFO *)lParam;
+
+ if (!IsWindowVisible(hwnd) || IsIconic(hwnd))
+ return TRUE; // continue
+
+ if (pei->hTrayWnd == hwnd || pei->hwndDesktop == hwnd ||
+ pei->hwndProgman == hwnd)
+ {
+ return TRUE; // continue
+ }
+
+ if (pei->bMustBeInMonitor)
+ {
+ // is the window in the nearest monitor?
+ HMONITOR hMon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
+ if (hMon)
+ {
+ MONITORINFO info;
+ ZeroMemory(&info, sizeof(info));
+ info.cbSize = sizeof(info);
+ if (GetMonitorInfoW(hMon, &info))
+ {
+ RECT rcWindow, rcMonitor, rcIntersect;
+ rcMonitor = info.rcMonitor;
+
+ GetWindowRect(hwnd, &rcWindow);
+
+ if (!IntersectRect(&rcIntersect, &rcMonitor, &rcWindow))
+ return TRUE; // continue
+ }
+ }
+ }
+
+ pei->hwndFound = hwnd;
+ return FALSE; // stop if found
+}
+
+static BOOL
+IsThereAnyEffectiveWindow(BOOL bMustBeInMonitor)
+{
+ EFFECTIVE_INFO ei;
+ ei.hwndFound = NULL;
+ ei.hwndDesktop = GetDesktopWindow();
+ ei.hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL);
+ ei.hwndProgman = FindWindowW(L"Progman", NULL);
+ ei.bMustBeInMonitor = bMustBeInMonitor;
+
+ EnumWindows(FindEffectiveProc, (LPARAM)&ei);
+ if (ei.hwndFound && FALSE)
+ {
+ WCHAR szClass[64], szText[64];
+ GetClassNameW(ei.hwndFound, szClass, _countof(szClass));
+ GetWindowTextW(ei.hwndFound, szText, _countof(szText));
+ MessageBoxW(NULL, szText, szClass, 0);
+ }
+ return ei.hwndFound != NULL;
+}
+
+CSimpleArray<HWND> g_MinimizedAll;
+
/*
* ITrayWindow
*/
SW_SHOWNORMAL);
}
+ VOID ToggleDesktop()
+ {
+ if (::IsThereAnyEffectiveWindow(TRUE))
+ {
+ ShowDesktop();
+ }
+ else
+ {
+ RestoreAll();
+ }
+ }
+
BOOL STDMETHODCALLTYPE ExecContextMenuCmd(IN UINT uiCmd)
{
switch (uiCmd)
break;
case ID_SHELL_CMD_SHOW_DESKTOP:
+ ShowDesktop();
break;
case ID_SHELL_CMD_TILE_WND_H:
ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
break;
+ case ID_SHELL_CMD_RESTORE_ALL:
+ RestoreAll();
+ break;
+
default:
TRACE("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command ID!\n", uiCmd);
return FALSE;
case IDHK_PREV_TASK:
break;
case IDHK_MINIMIZE_ALL:
+ MinimizeAll();
break;
case IDHK_RESTORE_ALL:
+ RestoreAll();
break;
case IDHK_DESKTOP:
+ ToggleDesktop();
break;
case IDHK_PAGER:
break;
{
switch (uCommand)
{
- case IDM_TASKBARANDSTARTMENU:
- DisplayProperties();
- break;
-
- case IDM_SEARCH:
- SHFindFiles(NULL, NULL);
- break;
-
- case IDM_HELPANDSUPPORT:
- ExecResourceCmd(IDS_HELP_COMMAND);
- break;
-
- case IDM_RUN:
- DisplayRunFileDlg();
- break;
-
- /* FIXME: Handle these commands as well */
- case IDM_SYNCHRONIZE:
- case IDM_DISCONNECT:
- case IDM_UNDOCKCOMPUTER:
- break;
-
- case IDM_LOGOFF:
- LogoffWindowsDialog(m_hWnd); // FIXME: Maybe handle it in a similar way as DoExitWindows?
- break;
+ case TRAYCMD_STARTMENU:
+ // TODO:
+ break;
+ case TRAYCMD_RUN_DIALOG:
+ DisplayRunFileDlg();
+ break;
+ case TRAYCMD_LOGOFF_DIALOG:
+ LogoffWindowsDialog(m_hWnd); // FIXME: Maybe handle it in a similar way as DoExitWindows?
+ break;
+ case TRAYCMD_CASCADE:
+ CascadeWindows(NULL, MDITILE_SKIPDISABLED, NULL, 0, NULL);
+ break;
+ case TRAYCMD_TILE_H:
+ TileWindows(NULL, MDITILE_HORIZONTAL, NULL, 0, NULL);
+ break;
+ case TRAYCMD_TILE_V:
+ TileWindows(NULL, MDITILE_VERTICAL, NULL, 0, NULL);
+ break;
+ case TRAYCMD_TOGGLE_DESKTOP:
+ ToggleDesktop();
+ break;
+ case TRAYCMD_DATE_AND_TIME:
+ ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
+ break;
+ case TRAYCMD_TASKBAR_PROPERTIES:
+ DisplayProperties();
+ break;
+ case TRAYCMD_MINIMIZE_ALL:
+ MinimizeAll();
+ break;
+ case TRAYCMD_RESTORE_ALL:
+ RestoreAll();
+ break;
+ case TRAYCMD_SHOW_DESKTOP:
+ ShowDesktop();
+ break;
+ case TRAYCMD_SHOW_TASK_MGR:
+ OpenTaskManager(m_hWnd);
+ break;
+ case TRAYCMD_CUSTOMIZE_TASKBAR:
+ break;
+ case TRAYCMD_LOCK_TASKBAR:
+ if (SHRestricted(REST_CLASSICSHELL) == 0)
+ {
+ Lock(!g_TaskbarSettings.bLock);
+ }
+ break;
+ case TRAYCMD_HELP_AND_SUPPORT:
+ ExecResourceCmd(IDS_HELP_COMMAND);
+ break;
+ case TRAYCMD_CONTROL_PANEL:
+ // TODO:
+ break;
+ case TRAYCMD_SHUTDOWN_DIALOG:
+ DoExitWindows();
+ break;
+ case TRAYCMD_PRINTERS_AND_FAXES:
+ // TODO:
+ break;
+ case TRAYCMD_LOCK_DESKTOP:
+ // TODO:
+ break;
+ case TRAYCMD_SWITCH_USER_DIALOG:
+ // TODO:
+ break;
+ case TRAYCMD_SEARCH_FILES:
+ SHFindFiles(NULL, NULL);
+ break;
+ case TRAYCMD_SEARCH_COMPUTERS:
+ SHFindComputer(NULL, NULL);
+ break;
- case IDM_SHUTDOWN:
- DoExitWindows();
- break;
+ default:
+ break;
}
return FALSE;
return HandleHotKey(wParam);
}
+ struct MINIMIZE_INFO
+ {
+ HWND hwndDesktop;
+ HWND hTrayWnd;
+ HWND hwndProgman;
+ BOOL bRet;
+ CSimpleArray<HWND> *pMinimizedAll;
+ BOOL bShowDesktop;
+ };
+
+ static BOOL IsDialog(HWND hwnd)
+ {
+ WCHAR szClass[32];
+ GetClassNameW(hwnd, szClass, _countof(szClass));
+ return wcscmp(szClass, L"#32770") == 0;
+ }
+
+ static BOOL CALLBACK MinimizeWindowsProc(HWND hwnd, LPARAM lParam)
+ {
+ MINIMIZE_INFO *info = (MINIMIZE_INFO *)lParam;
+ if (hwnd == info->hwndDesktop || hwnd == info->hTrayWnd ||
+ hwnd == info->hwndProgman)
+ {
+ return TRUE;
+ }
+ if (!info->bShowDesktop)
+ {
+ if (!::IsWindowEnabled(hwnd) || IsDialog(hwnd))
+ return TRUE;
+ HWND hwndOwner = ::GetWindow(hwnd, GW_OWNER);
+ if (hwndOwner && !::IsWindowEnabled(hwndOwner))
+ return TRUE;
+ }
+ if (::IsWindowVisible(hwnd) && !::IsIconic(hwnd))
+ {
+ ::ShowWindowAsync(hwnd, SW_MINIMIZE);
+ info->bRet = TRUE;
+ info->pMinimizedAll->Add(hwnd);
+ }
+ return TRUE;
+ }
+
+ VOID MinimizeAll(BOOL bShowDesktop = FALSE)
+ {
+ MINIMIZE_INFO info;
+ info.hwndDesktop = GetDesktopWindow();;
+ info.hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL);
+ info.hwndProgman = FindWindowW(L"Progman", NULL);
+ info.bRet = FALSE;
+ info.pMinimizedAll = &g_MinimizedAll;
+ info.bShowDesktop = bShowDesktop;
+ EnumWindows(MinimizeWindowsProc, (LPARAM)&info);
+
+ // invalid handles should be cleared to avoid mismatch of handles
+ for (INT i = 0; i < g_MinimizedAll.GetSize(); ++i)
+ {
+ if (!::IsWindow(g_MinimizedAll[i]))
+ g_MinimizedAll[i] = NULL;
+ }
+
+ ::SetForegroundWindow(m_DesktopWnd);
+ ::SetFocus(m_DesktopWnd);
+ }
+
+ VOID ShowDesktop()
+ {
+ MinimizeAll(TRUE);
+ }
+
+ VOID RestoreAll()
+ {
+ for (INT i = g_MinimizedAll.GetSize() - 1; i >= 0; --i)
+ {
+ HWND hwnd = g_MinimizedAll[i];
+ if (::IsWindowVisible(hwnd) && ::IsIconic(hwnd))
+ {
+ ::ShowWindow(hwnd, SW_RESTORE);
+ }
+ }
+ g_MinimizedAll.RemoveAll();
+ }
+
LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT Ret = FALSE;
return 0;
}
+ LRESULT OnInitMenuPopup(INT code, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+ {
+ HMENU hMenu = (HMENU)wParam;
+ if (::IsThereAnyEffectiveWindow(FALSE))
+ {
+ ::EnableMenuItem(hMenu, ID_SHELL_CMD_CASCADE_WND, MF_BYCOMMAND | MF_ENABLED);
+ ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_H, MF_BYCOMMAND | MF_ENABLED);
+ ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_V, MF_BYCOMMAND | MF_ENABLED);
+ }
+ else
+ {
+ ::EnableMenuItem(hMenu, ID_SHELL_CMD_CASCADE_WND, MF_BYCOMMAND | MF_GRAYED);
+ ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_H, MF_BYCOMMAND | MF_GRAYED);
+ ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_V, MF_BYCOMMAND | MF_GRAYED);
+ }
+ return 0;
+ }
+
LRESULT OnRebarAutoSize(INT code, LPNMHDR nmhdr, BOOL& bHandled)
{
#if 0
MESSAGE_HANDLER(WM_CLOSE, OnDoExitWindows)
MESSAGE_HANDLER(WM_HOTKEY, OnHotkey)
MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize)
+ MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
MESSAGE_HANDLER(TWM_SETTINGSCHANGED, OnTaskbarSettingsChanged)
MESSAGE_HANDLER(TWM_OPENSTARTMENU, OnOpenStartMenu)
MESSAGE_HANDLER(TWM_DOEXITWINDOWS, OnDoExitWindows)
UINT idCmdLast,
UINT uFlags)
{
- HMENU menubase = LoadPopupMenu(hExplorerInstance, MAKEINTRESOURCEW(IDM_TRAYWND));
- if (!menubase)
+ HMENU hMenuBase;
+
+ hMenuBase = LoadPopupMenu(hExplorerInstance, MAKEINTRESOURCEW(IDM_TRAYWND));
+
+ if (g_MinimizedAll.GetSize() != 0 && !::IsThereAnyEffectiveWindow(TRUE))
+ {
+ CStringW strRestoreAll(MAKEINTRESOURCEW(IDS_RESTORE_ALL));
+ MENUITEMINFOW mii = { sizeof(mii) };
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.wID = ID_SHELL_CMD_RESTORE_ALL;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = const_cast<LPWSTR>(&strRestoreAll[0]);
+ SetMenuItemInfoW(hMenuBase, ID_SHELL_CMD_SHOW_DESKTOP, FALSE, &mii);
+ }
+
+ if (!hMenuBase)
return HRESULT_FROM_WIN32(GetLastError());
if (SHRestricted(REST_CLASSICSHELL) != 0)
MF_BYCOMMAND);
}
- CheckMenuItem(menubase,
+ CheckMenuItem(hMenuBase,
ID_LOCKTASKBAR,
MF_BYCOMMAND | (g_TaskbarSettings.bLock ? MF_CHECKED : MF_UNCHECKED));
UINT idCmdNext;
- idCmdNext = Shell_MergeMenus(hPopup, menubase, indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS | MM_ADDSEPARATOR);
+ idCmdNext = Shell_MergeMenus(hPopup, hMenuBase, indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS | MM_ADDSEPARATOR);
m_idCmdCmFirst = idCmdNext - idCmdFirst;
- ::DestroyMenu(menubase);
+ ::DestroyMenu(hMenuBase);
if (TrayWnd->m_TrayBandSite != NULL)
{
--- /dev/null
+/*
+ * Tray Commands
+ *
+ * Copyright 2018 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef TRAYCMD_H_
+#define TRAYCMD_H_
+
+/* TODO: Add more and implement them */
+#define TRAYCMD_STARTMENU 305 /* Same as IDMA_START. */
+#define TRAYCMD_RUN_DIALOG 401 /* Implemented. Same as IDM_RUN. */
+#define TRAYCMD_LOGOFF_DIALOG 402 /* Implemented. Same as IDM_LOGOFF. */
+#define TRAYCMD_CASCADE 403 /* */
+#define TRAYCMD_TILE_H 404 /* */
+#define TRAYCMD_TILE_V 405 /* */
+#define TRAYCMD_TOGGLE_DESKTOP 407 /* Implemented. */
+#define TRAYCMD_DATE_AND_TIME 408 /* Implemented. */
+#define TRAYCMD_TASKBAR_PROPERTIES 413 /* Implemented. Same as IDM_TASKBARANDSTARTMENU. */
+#define TRAYCMD_MINIMIZE_ALL 415 /* Implemented. */
+#define TRAYCMD_RESTORE_ALL 416 /* Implemented. Same as IDMA_RESTORE_OPEN. */
+#define TRAYCMD_SHOW_DESKTOP 419 /* Implemented. */
+#define TRAYCMD_SHOW_TASK_MGR 420 /* Implemented. */
+#define TRAYCMD_CUSTOMIZE_TASKBAR 421 /* */
+#define TRAYCMD_LOCK_TASKBAR 424 /* Implemented. */
+#define TRAYCMD_HELP_AND_SUPPORT 503 /* Implemented. Same as IDM_HELPANDSUPPORT. */
+#define TRAYCMD_CONTROL_PANEL 505 /* Same as IDM_CONTROLPANEL. */
+#define TRAYCMD_SHUTDOWN_DIALOG 506 /* Implemented. Same as IDM_SHUTDOWN. */
+#define TRAYCMD_PRINTERS_AND_FAXES 510 /* Same as IDM_PRINTERSANDFAXES. */
+#define TRAYCMD_LOCK_DESKTOP 517 /* */
+#define TRAYCMD_SWITCH_USER_DIALOG 5000 /* */
+#define TRAYCMD_SEARCH_FILES 41093 /* Implemented. Same as IDMA_SEARCH. */
+#define TRAYCMD_SEARCH_COMPUTERS 41094 /* Implemented. */
+
+#endif /* ndef TRAYCMD_H_ */