|
|
/*****************************************************************************\
FILE: ImageMenu.cpp
DESCRIPTION: This code will display a submenu on the context menus for imagines. This will allow the conversion and manipulation of images.
BryanSt 8/9/2000 Updated and Converted to C++
Copyright (C) Microsoft Corp 2000-2000. All rights reserved. \*****************************************************************************/
#include "priv.h"
#include "imagemenu.h"
//===========================
// *** Structures ***
//===========================
struct VERBINFO { UINT idc; DWORD sfgao; LPCTSTR ptszCmd; LPCTSTR pszExt; } c_rgvi[] = { { IDC_IMAGEMENU_CONVERT_GIF, 0, TEXT("ImageMenu_Convert_ToGIF"), TEXT(".gif")}, { IDC_IMAGEMENU_CONVERT_JPEG, 0, TEXT("ImageMenu_Convert_ToJPEG"), TEXT(".jpeg")}, { IDC_IMAGEMENU_CONVERT_PNG, 0, TEXT("ImageMenu_Convert_ToPNG"), TEXT(".png")}, { IDC_IMAGEMENU_CONVERT_TIFF, 0, TEXT("ImageMenu_Convert_ToTIFF"), TEXT(".tiff")}, { IDC_IMAGEMENU_CONVERT_BMP, 0, TEXT("ImageMenu_Convert_ToBMP"), TEXT(".bmp")}, };
//===========================
// *** Class Internals & Helpers ***
//===========================
HRESULT CImageMenu::_ConvertImage(IN HWND hwnd, IN UINT idc) { LPTSTR pszCurrFile = m_pszFileList; UINT nFileCount = m_nFileCount; HRESULT hr = S_OK; LPTSTR pszErrorMessage = NULL;
if (pszCurrFile) { while (SUCCEEDED(hr) && nFileCount--) { TCHAR szSource[MAX_PATH]; TCHAR szDest[MAX_PATH];
StrCpyN(szSource, pszCurrFile, ARRAYSIZE(szSource)); StrCpyN(szDest, pszCurrFile, ARRAYSIZE(szDest));
LPTSTR pszExtension = PathFindExtension(szDest); if (pszExtension) { LPCTSTR pszNewExt = NULL;
// Replace the extension with the target type.
switch (idc) { case IDC_IMAGEMENU_CONVERT_GIF: pszNewExt = TEXT(".gif"); break; case IDC_IMAGEMENU_CONVERT_JPEG: pszNewExt = TEXT(".jpeg"); break; case IDC_IMAGEMENU_CONVERT_PNG: pszNewExt = TEXT(".png"); break; case IDC_IMAGEMENU_CONVERT_BMP: pszNewExt = TEXT(".bmp"); break; case IDC_IMAGEMENU_CONVERT_TIFF: pszNewExt = TEXT(".tiff"); break; }
if (pszNewExt) { StrCpy(pszExtension, pszNewExt);
hr = SHConvertGraphicsFile(szSource, szDest, SHCGF_REPLACEFILE); } else { pszErrorMessage = TEXT("We don't support converting these types of files."); hr = E_FAIL; } } else { pszErrorMessage = TEXT("Couldn't find the file extension."); hr = E_FAIL; }
pszCurrFile += (lstrlen(pszCurrFile) + 1); if (!pszCurrFile[0]) { // We are done.
break; } } } else { pszErrorMessage = TEXT("Someone didn't set our pidl."); hr = E_FAIL; }
if (FAILED(hr)) { ErrorMessageBox(hwnd, TEXT("Error"), IDS_ERROR_CONVERTIMAGEFAILED, hr, pszErrorMessage, 0); }
return hr; }
// Returns the submenu of the given menu and ID. Returns NULL if there
// is no submenu
int _MergePopupMenus(HMENU hmDest, HMENU hmSource, int idCmdFirst, int idCmdLast) { int i, idFinal = idCmdFirst;
for (i = GetMenuItemCount(hmSource) - 1; i >= 0; --i) { MENUITEMINFO mii;
mii.cbSize = SIZEOF(mii); mii.fMask = MIIM_ID|MIIM_SUBMENU; mii.cch = 0; // just in case
if (EVAL(GetMenuItemInfo(hmSource, i, TRUE, &mii))) { HMENU hmDestSub = SHGetMenuFromID(hmDest, mii.wID); if (hmDestSub) { int idTemp = Shell_MergeMenus(hmDestSub, mii.hSubMenu, (UINT)0, idCmdFirst, idCmdLast, MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS);
if (idFinal < idTemp) idFinal = idTemp; } } }
return idFinal; }
/*****************************************************************************\
FUNCTION: AddToPopupMenu
DESCRIPTION: Swiped from utils.c in RNAUI, in turn swiped from the ;Internal shell. ;Internal ;Internal Takes a destination menu and a (menu id, submenu index) pair, and inserts the items from the (menu id, submenu index) at location imi in the destination menu, with a separator, returning the number of items added. (imi = index to menu item) Returns the first the number of items added. hmenuDst - destination menu idMenuToAdd - menu resource identifier idSubMenuIndex - submenu from menu resource to act as template indexMenu - location at which menu items should be inserted idCmdFirst - first available menu identifier idCmdLast - first unavailable menu identifier uFlags - flags for Shell_MergeMenus \*****************************************************************************/ #define FLAGS_MENUMERGE (MM_SUBMENUSHAVEIDS | MM_DONTREMOVESEPS)
UINT AddToPopupMenu(HMENU hmenuDst, UINT idMenuToAdd, UINT idSubMenuIndex, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { UINT nLastItem = 0;
HMENU hmenuSrc = LoadMenu(g_hinst, MAKEINTRESOURCE(idMenuToAdd)); if (hmenuSrc) { nLastItem = Shell_MergeMenus(hmenuDst, GetSubMenu(hmenuSrc, idSubMenuIndex), indexMenu, idCmdFirst, idCmdLast, (uFlags | FLAGS_MENUMERGE)); DestroyMenu(hmenuSrc); }
return nLastItem; }
UINT MergeInToPopupMenu(HMENU hmenuDst, UINT idMenuToMerge, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { UINT nLastItem = 0;
HMENU hmenuSrc = LoadMenu(g_hinst, MAKEINTRESOURCE(idMenuToMerge)); if (hmenuSrc) { nLastItem = _MergePopupMenus(hmenuDst, hmenuSrc, idCmdFirst, idCmdLast); DestroyMenu(hmenuSrc); }
return nLastItem; }
//===========================
// *** IShellExtInit Interface ***
//===========================
HRESULT CImageMenu::Initialize(IN LPCITEMIDLIST pidlFolder, IN IDataObject *pdtobj, IN HKEY hkeyProgID) { HRESULT hr = S_OK;
if (pdtobj) { hr = DataObj_QueryFileList(pdtobj, &m_pszFileList, &m_nFileCount); } else { MessageBox(NULL, TEXT("IShellExtInit::Initialize() was called but no IDataObject was provided."), TEXT("Error"), MB_OK); }
return hr; }
//===========================
// *** IContextMenu Interface ***
//===========================
HRESULT CImageMenu::QueryContextMenu(IN HMENU hmenu, IN UINT indexMenu, IN UINT idCmdFirst, IN UINT idCmdLast, IN UINT uFlags) { HRESULT hr = S_OK; BOOL fAddMenu = TRUE;
if (m_pszFileList) { LPTSTR pszCurrFile = m_pszFileList;
for (UINT nIndex = 0; SUCCEEDED(hr) && fAddMenu && (nIndex < m_nFileCount); nIndex++) { LPTSTR pszExtension = PathFindExtension(pszCurrFile); if (pszExtension) { for (int nExtIndex = 0; SUCCEEDED(hr) && (nExtIndex < ARRAYSIZE(c_rgvi)); nExtIndex++) { if (StrCmpI(c_rgvi[nExtIndex].pszExt, pszExtension)) { nExtIndex = ARRAYSIZE(c_rgvi); } else if (nExtIndex = ARRAYSIZE(c_rgvi) - 1) { fAddMenu = FALSE; break; } } } else { fAddMenu = FALSE; break; }
pszCurrFile += (lstrlen(pszCurrFile) + 1); if (!pszCurrFile[0]) { // We are done.
break; } } } else { hr = E_FAIL; ErrorMessageBox(NULL, TEXT("Error"), IDS_ERROR_CONVERTIMAGEFAILED, hr, TEXT("Someone didn't set our pidl."), 0); }
if (fAddMenu) { AddToPopupMenu(hmenu, IDM_IMAGEMENU, 0, indexMenu, idCmdFirst, idCmdLast, MM_ADDSEPARATOR); if (SUCCEEDED(hr)) hr = ResultFromShort(ARRAYSIZE(c_rgvi)+1); }
return hr; }
HRESULT CImageMenu::InvokeCommand(IN LPCMINVOKECOMMANDINFO pici) { UINT idc; HRESULT hr = E_FAIL;
if (pici->cbSize < sizeof(*pici)) return E_INVALIDARG;
if (HIWORD(pici->lpVerb)) { int ivi; idc = (UINT)-1; for (ivi = 0; ivi < ARRAYSIZE(c_rgvi); ivi++) { TCHAR szVerb[MAX_PATH];
SHAnsiToTChar(pici->lpVerb, szVerb, ARRAYSIZE(szVerb)); if (!StrCmpI(c_rgvi[ivi].ptszCmd, szVerb)) { // Yes, the command is equal to the verb str, so this is the one.
idc = c_rgvi[ivi].idc; break; } } } else idc = LOWORD(pici->lpVerb);
switch (idc) { case IDC_IMAGEMENU_CONVERT_GIF: case IDC_IMAGEMENU_CONVERT_JPEG: case IDC_IMAGEMENU_CONVERT_PNG: case IDC_IMAGEMENU_CONVERT_TIFF: case IDC_IMAGEMENU_CONVERT_BMP: hr = _ConvertImage(pici->hwnd, idc); break;
default: ErrorMessageBox(pici->hwnd, TEXT("Error"), IDS_ERROR_MESSAGENUMBER, hr, NULL, 0); hr = E_INVALIDARG; break; }
return hr; }
HRESULT CImageMenu::GetCommandString(IN UINT_PTR idCmd, IN UINT uType, IN UINT * pwReserved, IN LPSTR pszName, IN UINT cchMax) { HRESULT hr = E_FAIL; BOOL fUnicode = FALSE;
if (idCmd < ARRAYSIZE(c_rgvi)) { switch (uType) { /*
case GCS_HELPTEXTW: fUnicode = TRUE; // Fall thru...
case GCS_HELPTEXTA: GetHelpText: if (EVAL(cchMax)) { BOOL fResult; pszName[0] = '\0'; if (fUnicode) fResult = LoadStringW(HINST_THISDLL, IDS_ITEM_HELP((UINT)idCmd), (LPWSTR)pszName, cchMax); else fResult = LoadStringA(HINST_THISDLL, IDS_ITEM_HELP((UINT)idCmd), pszName, cchMax); if (EVAL(fResult)) hr = S_OK; else hr = E_INVALIDARG; } else hr = E_INVALIDARG; break; */ case GCS_VALIDATEW: case GCS_VALIDATEA: hr = S_OK; break;
case GCS_VERBW: fUnicode = TRUE; // Fall thru...
case GCS_VERBA: { int ivi; for (ivi = 0; ivi < ARRAYSIZE(c_rgvi); ivi++) { if (c_rgvi[ivi].idc == idCmd) { if (fUnicode) SHTCharToUnicode(c_rgvi[ivi].ptszCmd, (LPWSTR)pszName, cchMax); else SHTCharToAnsi(c_rgvi[ivi].ptszCmd, pszName, cchMax);
hr = S_OK; break; } } break; }
default: hr = E_NOTIMPL; break; } }
return hr; }
//===========================
// *** IUnknown Interface ***
//===========================
ULONG CImageMenu::AddRef() { m_cRef++; return m_cRef; }
ULONG CImageMenu::Release() { ASSERT(m_cRef > 0); m_cRef--;
if (m_cRef > 0) return m_cRef;
delete this; return 0; }
HRESULT CImageMenu::QueryInterface(REFIID riid, void **ppvObj) { HRESULT hr = E_NOINTERFACE;
static const QITAB qit[] = { QITABENT(CImageMenu, IShellExtInit), QITABENT(CImageMenu, IContextMenu), { 0 }, };
return QISearch(this, qit, riid, ppvObj); }
//===========================
// *** Class Methods ***
//===========================
CImageMenu::CImageMenu() : m_cRef(1) { // This needs to be allocated in Zero Inited Memory.
// Assert that all Member Variables are inited to Zero.
m_pszFileList = FALSE; m_nFileCount = 0; }
CImageMenu::~CImageMenu() { if (m_pszFileList) { DataObj_FreeList(m_pszFileList); } }
HRESULT CImageMenu_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT void **ppvObject) { HRESULT hr = E_INVALIDARG;
if (!punkOuter && ppvObject) { CImageMenu * pThis = new CImageMenu();
if (pThis) { hr = pThis->QueryInterface(riid, ppvObject); pThis->Release(); } else { *ppvObject = NULL; hr = E_OUTOFMEMORY; } }
return hr; }
|