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;
|
SHIMGVW_FILENODE * g_pCurrentFile = NULL;
|
||||||
GpImage * g_pImage = NULL;
|
GpImage * g_pImage = NULL;
|
||||||
SHIMGVW_SETTINGS g_Settings;
|
SHIMGVW_SETTINGS g_Settings;
|
||||||
|
UINT g_ImageId;
|
||||||
|
|
||||||
static const UINT s_ZoomSteps[] =
|
static const UINT s_ZoomSteps[] =
|
||||||
{
|
{
|
||||||
|
@ -402,6 +403,10 @@ Preview_pLoadImage(PPREVIEW_DATA pData, LPCWSTR szOpenFileName)
|
||||||
Preview_ResetZoom(pData);
|
Preview_ResetZoom(pData);
|
||||||
|
|
||||||
Preview_UpdateTitle(pData, szOpenFileName);
|
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
|
static VOID
|
||||||
|
@ -557,15 +562,17 @@ Preview_pSaveImageAs(PPREVIEW_DATA pData)
|
||||||
static VOID
|
static VOID
|
||||||
Preview_pPrintImage(PPREVIEW_DATA pData)
|
Preview_pPrintImage(PPREVIEW_DATA pData)
|
||||||
{
|
{
|
||||||
/* FIXME */
|
ShellExecuteVerb(g_hMainWnd, L"print", pData->m_szFile, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
Preview_UpdateUI(PPREVIEW_DATA pData)
|
Preview_UpdateUI(PPREVIEW_DATA pData)
|
||||||
{
|
{
|
||||||
BOOL bEnable = (g_pImage != NULL);
|
BOOL bEnable = (g_pImage != NULL);
|
||||||
PostMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_SAVEAS, bEnable);
|
SendMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_SAVEAS, bEnable);
|
||||||
PostMessageW(pData->m_hwndToolBar, TB_ENABLEBUTTON, IDC_PRINT, 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
|
static VOID
|
||||||
|
@ -1397,26 +1404,8 @@ Preview_Delete(PPREVIEW_DATA pData)
|
||||||
static VOID
|
static VOID
|
||||||
Preview_Edit(HWND hwnd)
|
Preview_Edit(HWND hwnd)
|
||||||
{
|
{
|
||||||
SHELLEXECUTEINFOW sei;
|
PPREVIEW_DATA pData = Preview_GetData(g_hMainWnd);
|
||||||
PPREVIEW_DATA pData = Preview_GetData(hwnd);
|
ShellExecuteVerb(pData->m_hwnd, L"edit", pData->m_szFile, TRUE);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
|
@ -1715,6 +1704,13 @@ PreviewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
{
|
{
|
||||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
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 = { .dwSize = sizeof(Icc), .dwICC = ICC_WIN95_CLASSES };
|
||||||
|
|
||||||
InitCommonControlsEx(&Icc);
|
InitCommonControlsEx(&Icc);
|
||||||
|
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); // Give UI higher priority than background threads
|
||||||
|
|
||||||
/* Initialize COM */
|
/* Initialize COM */
|
||||||
hrCoInit = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
hrCoInit = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
|
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define WM_UPDATECOMMANDSTATE (WM_APP + 0)
|
||||||
|
|
||||||
extern HINSTANCE g_hInstance;
|
extern HINSTANCE g_hInstance;
|
||||||
extern GpImage *g_pImage;
|
extern GpImage *g_pImage;
|
||||||
|
|
||||||
|
@ -72,6 +74,8 @@ void Anime_Pause(PANIME pAnime);
|
||||||
BOOL Anime_OnTimer(PANIME pAnime, WPARAM wParam);
|
BOOL Anime_OnTimer(PANIME pAnime, WPARAM wParam);
|
||||||
|
|
||||||
void DoShellContextMenuOnFile(HWND hwnd, PCWSTR File, LPARAM lParam);
|
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);
|
void DisplayHelp(HWND hwnd);
|
||||||
|
|
||||||
static inline LPVOID QuickAlloc(SIZE_T cbSize, BOOL bZero)
|
static inline LPVOID QuickAlloc(SIZE_T cbSize, BOOL bZero)
|
||||||
|
|
|
@ -47,11 +47,10 @@ static void
|
||||||
ModifyShellContextMenu(IContextMenu *pCM, HMENU hMenu, UINT CmdIdFirst, PCWSTR Assoc)
|
ModifyShellContextMenu(IContextMenu *pCM, HMENU hMenu, UINT CmdIdFirst, PCWSTR Assoc)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
UINT id, i;
|
for (UINT i = 0, c = GetMenuItemCount(hMenu); i < c; ++i)
|
||||||
for (i = 0; i < GetMenuItemCount(hMenu); ++i)
|
|
||||||
{
|
{
|
||||||
WCHAR buf[200];
|
WCHAR buf[200];
|
||||||
id = GetMenuItemIdByPos(hMenu, i);
|
UINT id = GetMenuItemIdByPos(hMenu, i);
|
||||||
if (id == (UINT)-1)
|
if (id == (UINT)-1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -131,8 +130,8 @@ die:
|
||||||
g_pContextMenu = NULL;
|
g_pContextMenu = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
HRESULT
|
||||||
DoShellContextMenuOnFile(HWND hwnd, PCWSTR File, LPARAM lParam)
|
GetUIObjectOfPath(HWND hwnd, PCWSTR File, REFIID riid, void **ppv)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
IShellFolder *pSF;
|
IShellFolder *pSF;
|
||||||
|
@ -140,19 +139,110 @@ DoShellContextMenuOnFile(HWND hwnd, PCWSTR File, LPARAM lParam)
|
||||||
PIDLIST_ABSOLUTE pidl = ILCreateFromPath(File);
|
PIDLIST_ABSOLUTE pidl = ILCreateFromPath(File);
|
||||||
if (pidl && SUCCEEDED(SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &pSF), &pidlItem)))
|
if (pidl && SUCCEEDED(SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &pSF), &pidlItem)))
|
||||||
{
|
{
|
||||||
IContextMenu *pCM;
|
hr = IShellFolder_GetUIObjectOf(pSF, hwnd, 1, &pidlItem, riid, NULL, ppv);
|
||||||
hr = IShellFolder_GetUIObjectOf(pSF, hwnd, 1, &pidlItem, &IID_IContextMenu, NULL, (void**)&pCM);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
DoShellContextMenu(hwnd, pCM, File, lParam);
|
|
||||||
IContextMenu_Release(pCM);
|
|
||||||
}
|
|
||||||
IShellFolder_Release(pSF);
|
IShellFolder_Release(pSF);
|
||||||
}
|
}
|
||||||
SHFree(pidl);
|
SHFree(pidl);
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayHelp(HWND hwnd)
|
void
|
||||||
|
DoShellContextMenuOnFile(HWND hwnd, PCWSTR File, LPARAM lParam)
|
||||||
|
{
|
||||||
|
IContextMenu *pCM;
|
||||||
|
HRESULT hr = GetUIObjectOfPath(hwnd, File, IID_PPV_ARG(IContextMenu, &pCM));
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
DoShellContextMenu(hwnd, pCM, File, lParam);
|
||||||
|
IContextMenu_Release(pCM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
SHELL_ErrorBox(hwnd, ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue