mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
[SHIMGVW] Only enable toolbar edit and print buttons if the shell verb exists (#7725)
CORE-20002
This commit is contained in:
parent
e5fc4de8c9
commit
46d01bc7fd
3 changed files with 127 additions and 36 deletions
|
@ -33,6 +33,7 @@ HWND g_hwndFullscreen = NULL;
|
|||
SHIMGVW_FILENODE * g_pCurrentFile = NULL;
|
||||
GpImage * g_pImage = NULL;
|
||||
SHIMGVW_SETTINGS g_Settings;
|
||||
UINT g_ImageId;
|
||||
|
||||
static const UINT s_ZoomSteps[] =
|
||||
{
|
||||
|
@ -402,6 +403,10 @@ Preview_pLoadImage(PPREVIEW_DATA pData, LPCWSTR szOpenFileName)
|
|||
Preview_ResetZoom(pData);
|
||||
|
||||
Preview_UpdateTitle(pData, szOpenFileName);
|
||||
|
||||
++g_ImageId;
|
||||
EnableCommandIfVerbExists(g_ImageId, g_hMainWnd, IDC_PRINT, L"print", pData->m_szFile);
|
||||
EnableCommandIfVerbExists(g_ImageId, g_hMainWnd, IDC_MODIFY, L"edit", pData->m_szFile);
|
||||
}
|
||||
|
||||
static VOID
|
||||
|
@ -557,15 +562,17 @@ Preview_pSaveImageAs(PPREVIEW_DATA pData)
|
|||
static VOID
|
||||
Preview_pPrintImage(PPREVIEW_DATA pData)
|
||||
{
|
||||
/* FIXME */
|
||||
ShellExecuteVerb(g_hMainWnd, L"print", pData->m_szFile, FALSE);
|
||||
}
|
||||
|
||||
static VOID
|
||||
Preview_UpdateUI(PPREVIEW_DATA pData)
|
||||
{
|
||||
BOOL bEnable = (g_pImage != NULL);
|
||||
PostMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_SAVEAS, bEnable);
|
||||
PostMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_PRINT, bEnable);
|
||||
SendMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_SAVEAS, bEnable);
|
||||
// These will be validated and enabled later by EnableCommandIfVerbExists
|
||||
SendMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_PRINT, FALSE);
|
||||
SendMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_MODIFY, FALSE);
|
||||
}
|
||||
|
||||
static VOID
|
||||
|
@ -1397,26 +1404,8 @@ Preview_Delete(PPREVIEW_DATA pData)
|
|||
static VOID
|
||||
Preview_Edit(HWND hwnd)
|
||||
{
|
||||
SHELLEXECUTEINFOW sei;
|
||||
PPREVIEW_DATA pData = Preview_GetData(hwnd);
|
||||
|
||||
if (!pData->m_szFile[0])
|
||||
return;
|
||||
|
||||
ZeroMemory(&sei, sizeof(sei));
|
||||
sei.cbSize = sizeof(sei);
|
||||
sei.lpVerb = L"edit";
|
||||
sei.lpFile = pData->m_szFile;
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
if (!ShellExecuteExW(&sei))
|
||||
{
|
||||
DPRINT1("Preview_Edit: ShellExecuteExW() failed with code %ld\n", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Destroy the window to quit the application
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
PPREVIEW_DATA pData = Preview_GetData(g_hMainWnd);
|
||||
ShellExecuteVerb(pData->m_hwnd, L"edit", pData->m_szFile, TRUE);
|
||||
}
|
||||
|
||||
static VOID
|
||||
|
@ -1715,6 +1704,13 @@ PreviewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case WM_UPDATECOMMANDSTATE:
|
||||
{
|
||||
PPREVIEW_DATA pData = Preview_GetData(g_hMainWnd);
|
||||
if (g_ImageId == lParam)
|
||||
SendMessage(pData->m_hwndToolBar, TB_ENABLEBUTTON, LOWORD(wParam), HIWORD(wParam));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||
|
@ -1738,6 +1734,7 @@ ImageView_Main(HWND hwnd, LPCWSTR szFileName)
|
|||
INITCOMMONCONTROLSEX Icc = { .dwSize = sizeof(Icc), .dwICC = ICC_WIN95_CLASSES };
|
||||
|
||||
InitCommonControlsEx(&Icc);
|
||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); // Give UI higher priority than background threads
|
||||
|
||||
/* Initialize COM */
|
||||
hrCoInit = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "resource.h"
|
||||
|
||||
#define WM_UPDATECOMMANDSTATE (WM_APP + 0)
|
||||
|
||||
extern HINSTANCE g_hInstance;
|
||||
extern GpImage *g_pImage;
|
||||
|
||||
|
@ -72,6 +74,8 @@ void Anime_Pause(PANIME pAnime);
|
|||
BOOL Anime_OnTimer(PANIME pAnime, WPARAM wParam);
|
||||
|
||||
void DoShellContextMenuOnFile(HWND hwnd, PCWSTR File, LPARAM lParam);
|
||||
void EnableCommandIfVerbExists(UINT ImageId, HWND hwnd, UINT CmdId, PCWSTR Verb, PCWSTR File);
|
||||
void ShellExecuteVerb(HWND hwnd, PCWSTR Verb, PCWSTR File, BOOL Quit);
|
||||
void DisplayHelp(HWND hwnd);
|
||||
|
||||
static inline LPVOID QuickAlloc(SIZE_T cbSize, BOOL bZero)
|
||||
|
|
|
@ -47,11 +47,10 @@ static void
|
|||
ModifyShellContextMenu(IContextMenu *pCM, HMENU hMenu, UINT CmdIdFirst, PCWSTR Assoc)
|
||||
{
|
||||
HRESULT hr;
|
||||
UINT id, i;
|
||||
for (i = 0; i < GetMenuItemCount(hMenu); ++i)
|
||||
for (UINT i = 0, c = GetMenuItemCount(hMenu); i < c; ++i)
|
||||
{
|
||||
WCHAR buf[200];
|
||||
id = GetMenuItemIdByPos(hMenu, i);
|
||||
UINT id = GetMenuItemIdByPos(hMenu, i);
|
||||
if (id == (UINT)-1)
|
||||
continue;
|
||||
|
||||
|
@ -131,8 +130,8 @@ die:
|
|||
g_pContextMenu = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
DoShellContextMenuOnFile(HWND hwnd, PCWSTR File, LPARAM lParam)
|
||||
HRESULT
|
||||
GetUIObjectOfPath(HWND hwnd, PCWSTR File, REFIID riid, void **ppv)
|
||||
{
|
||||
HRESULT hr;
|
||||
IShellFolder *pSF;
|
||||
|
@ -140,19 +139,110 @@ DoShellContextMenuOnFile(HWND hwnd, PCWSTR File, LPARAM lParam)
|
|||
PIDLIST_ABSOLUTE pidl = ILCreateFromPath(File);
|
||||
if (pidl && SUCCEEDED(SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &pSF), &pidlItem)))
|
||||
{
|
||||
hr = IShellFolder_GetUIObjectOf(pSF, hwnd, 1, &pidlItem, riid, NULL, ppv);
|
||||
IShellFolder_Release(pSF);
|
||||
}
|
||||
SHFree(pidl);
|
||||
return hr;
|
||||
}
|
||||
|
||||
void
|
||||
DoShellContextMenuOnFile(HWND hwnd, PCWSTR File, LPARAM lParam)
|
||||
{
|
||||
IContextMenu *pCM;
|
||||
hr = IShellFolder_GetUIObjectOf(pSF, hwnd, 1, &pidlItem, &IID_IContextMenu, NULL, (void**)&pCM);
|
||||
HRESULT hr = GetUIObjectOfPath(hwnd, File, IID_PPV_ARG(IContextMenu, &pCM));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DoShellContextMenu(hwnd, pCM, File, lParam);
|
||||
IContextMenu_Release(pCM);
|
||||
}
|
||||
IShellFolder_Release(pSF);
|
||||
}
|
||||
SHFree(pidl);
|
||||
}
|
||||
|
||||
void DisplayHelp(HWND hwnd)
|
||||
typedef struct _ENABLECOMMANDDATA
|
||||
{
|
||||
HWND hwnd;
|
||||
PCWSTR Verb;
|
||||
UINT CmdId;
|
||||
UINT ImageId;
|
||||
WCHAR File[ANYSIZE_ARRAY];
|
||||
} ENABLECOMMANDDATA;
|
||||
|
||||
static DWORD CALLBACK
|
||||
EnableCommandIfVerbExistsProc(LPVOID ThreadParam)
|
||||
{
|
||||
enum { first = 1, last = 0x7fff };
|
||||
ENABLECOMMANDDATA *pData = ThreadParam;
|
||||
IContextMenu *pCM;
|
||||
HRESULT hr = GetUIObjectOfPath(pData->hwnd, pData->File, IID_PPV_ARG(IContextMenu, &pCM));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
HMENU hMenu = CreatePopupMenu();
|
||||
hr = IContextMenu_QueryContextMenu(pCM, hMenu, 0, first, last, CMF_NORMAL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
for (UINT i = 0, c = GetMenuItemCount(hMenu); i < c; ++i)
|
||||
{
|
||||
WCHAR buf[200];
|
||||
UINT id = GetMenuItemIdByPos(hMenu, i);
|
||||
if (id == (UINT)-1)
|
||||
continue;
|
||||
|
||||
*buf = UNICODE_NULL;
|
||||
hr = IContextMenu_GetCommandString(pCM, id - first, GCS_VERBW, NULL, (char*)buf, _countof(buf));
|
||||
if (SUCCEEDED(hr) && !lstrcmpiW(buf, pData->Verb))
|
||||
{
|
||||
PostMessageW(pData->hwnd, WM_UPDATECOMMANDSTATE, MAKELONG(pData->CmdId, TRUE), pData->ImageId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DestroyMenu(hMenu);
|
||||
IContextMenu_Release(pCM);
|
||||
}
|
||||
SHFree(pData);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
EnableCommandIfVerbExists(UINT ImageId, HWND hwnd, UINT CmdId, PCWSTR Verb, PCWSTR File)
|
||||
{
|
||||
const SIZE_T cch = lstrlenW(File) + 1;
|
||||
ENABLECOMMANDDATA *pData = SHAlloc(FIELD_OFFSET(ENABLECOMMANDDATA, File[cch]));
|
||||
if (pData)
|
||||
{
|
||||
pData->hwnd = hwnd;
|
||||
pData->Verb = Verb; // Note: This assumes the string is valid for the lifetime of the thread.
|
||||
pData->CmdId = CmdId;
|
||||
pData->ImageId = ImageId;
|
||||
CopyMemory(pData->File, File, cch * sizeof(*File));
|
||||
SHCreateThread(EnableCommandIfVerbExistsProc, pData, CTF_COINIT | CTF_INSIST, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShellExecuteVerb(HWND hwnd, PCWSTR Verb, PCWSTR File, BOOL Quit)
|
||||
{
|
||||
SHELLEXECUTEINFOW sei = { sizeof(sei), SEE_MASK_INVOKEIDLIST | SEE_MASK_ASYNCOK };
|
||||
if (!*File)
|
||||
return;
|
||||
|
||||
sei.hwnd = hwnd;
|
||||
sei.lpVerb = Verb;
|
||||
sei.lpFile = File;
|
||||
sei.nShow = SW_SHOW;
|
||||
if (!ShellExecuteExW(&sei))
|
||||
{
|
||||
DPRINT1("ShellExecuteExW(%ls, %ls) failed with code %ld\n", Verb, File, GetLastError());
|
||||
}
|
||||
else if (Quit)
|
||||
{
|
||||
// Destroy the window to quit the application
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DisplayHelp(HWND hwnd)
|
||||
{
|
||||
SHELL_ErrorBox(hwnd, ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue