|
|
//*******************************************************************************************
//
// Filename : Menu.cpp
//
// Implementations for CCabItemMenu methods
//
// Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
//
//*******************************************************************************************
#include "pch.h"
#include "thisdll.h"
#include "resource.h"
#include "folder.h"
#include "menu.h"
#include "dataobj.h"
#include "cabitms.h"
// Copy a menu onto the beginning or end of another menu
// Adds uIDAdjust to each menu ID (pass in 0 for no adjustment)
// Will not add any item whose adjusted ID is greater than uMaxIDAdjust
// (pass in 0xffff to allow everything)
// Returns one more than the maximum adjusted ID that is used
//
BOOL _SHIsMenuSeparator(HMENU hm, int i) { MENUITEMINFO mii; mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_TYPE; mii.cch = 0; // WARNING: We MUST initialize it to 0!!!
if (!GetMenuItemInfo(hm, i, TRUE, &mii)) { return(FALSE); } if (mii.fType & MFT_SEPARATOR) { return(TRUE); } return(FALSE); }
//===================================================================
// Cab_MergeMenu parameter
//
#define MM_ADDSEPARATOR 0x00000001L
#define MM_SUBMENUSHAVEIDS 0x00000002L
UINT Cab_MergeMenus(HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags) { int nItem; HMENU hmSubMenu; BOOL bAlreadySeparated; MENUITEMINFO miiSrc; TCHAR szName[256]; UINT uTemp, uIDMax = uIDAdjust; if (!hmDst || !hmSrc) { goto MM_Exit; } nItem = GetMenuItemCount(hmDst); if (uInsert >= (UINT)nItem) { uInsert = (UINT)nItem; bAlreadySeparated = TRUE; } else { bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert);; } if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated) { // Add a separator between the menus
InsertMenu(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); bAlreadySeparated = TRUE; } // Go through the menu items and clone them
for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--) { miiSrc.cbSize = sizeof(MENUITEMINFO); miiSrc.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA; // We need to reset this every time through the loop in case
// menus DON'T have IDs
miiSrc.fType = MFT_STRING; miiSrc.dwTypeData = szName; miiSrc.dwItemData = 0; miiSrc.cch = ARRAYSIZE(szName); if (!GetMenuItemInfo(hmSrc, nItem, TRUE, &miiSrc)) { continue; } if (miiSrc.fType & MFT_SEPARATOR) { // This is a separator; don't put two of them in a row
if (bAlreadySeparated) { continue; } bAlreadySeparated = TRUE; } else if (miiSrc.hSubMenu) { if (uFlags & MM_SUBMENUSHAVEIDS) { // Adjust the ID and check it
miiSrc.wID += uIDAdjust; if (miiSrc.wID > uIDAdjustMax) { continue; } if (uIDMax <= miiSrc.wID) { uIDMax = miiSrc.wID + 1; } } else { // Don't set IDs for submenus that didn't have
// them already
miiSrc.fMask &= ~MIIM_ID; } hmSubMenu = miiSrc.hSubMenu; miiSrc.hSubMenu = CreatePopupMenu(); if (!miiSrc.hSubMenu) { goto MM_Exit; } uTemp = Cab_MergeMenus(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags&MM_SUBMENUSHAVEIDS); if (uIDMax <= uTemp) { uIDMax = uTemp; } bAlreadySeparated = FALSE; } else { // Adjust the ID and check it
miiSrc.wID += uIDAdjust; if (miiSrc.wID > uIDAdjustMax) { continue; } if (uIDMax <= miiSrc.wID) { uIDMax = miiSrc.wID + 1; } bAlreadySeparated = FALSE; } if (!InsertMenuItem(hmDst, uInsert, TRUE, &miiSrc)) { goto MM_Exit; } } // Ensure the correct number of separators at the beginning of the
// inserted menu items
if (uInsert == 0) { if (bAlreadySeparated) { DeleteMenu(hmDst, uInsert, MF_BYPOSITION); } } else { if (_SHIsMenuSeparator(hmDst, uInsert-1)) { if (bAlreadySeparated) { DeleteMenu(hmDst, uInsert, MF_BYPOSITION); } } else { if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated) { // Add a separator between the menus
InsertMenu(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); } } } MM_Exit: return(uIDMax); }
CCabItemMenu::CCabItemMenu(HWND hwndOwner, CCabFolder*pcf, LPCABITEM *apit, UINT cpit) : m_lSel(8) { m_hwndOwner = hwndOwner; m_pcfHere = pcf; pcf->AddRef();
// No need to check return value here; check in QueryInterface
m_lSel.AddItems(apit, cpit); }
CCabItemMenu::~CCabItemMenu() { m_pcfHere->Release(); }
// *** IUnknown methods ***
STDMETHODIMP CCabItemMenu::QueryInterface( REFIID riid, LPVOID FAR* ppvObj) { *ppvObj = NULL;
if (m_lSel.GetState() == CCabItemList::State_OutOfMem) { return(E_OUTOFMEMORY); }
LPUNKNOWN pObj; if (riid == IID_IUnknown) { pObj = (LPUNKNOWN)(IUnknown*)((IContextMenu*)this); // The (IShellFolder*) ^^^ up there is to disambiguate :) the reference
} else if (riid == IID_IContextMenu) { pObj = (LPUNKNOWN)(IContextMenu*)this; } else { return(E_NOINTERFACE); }
pObj->AddRef(); *ppvObj = pObj;
return(NOERROR); }
STDMETHODIMP_(ULONG) CCabItemMenu::AddRef(void) { return(m_cRef.AddRef()); }
STDMETHODIMP_(ULONG) CCabItemMenu::Release(void) { if (!m_cRef.Release()) { delete this; return(0); }
return(m_cRef.GetRef()); }
// *** IContextMenu methods ***
STDMETHODIMP CCabItemMenu::QueryContextMenu( HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { HMENU hmMerge = LoadPopupMenu(MENU_ITEMCONTEXT, 0);
if (!hmMerge) { return(E_OUTOFMEMORY); }
if (CMF_DVFILE & uFlags) { // No "copy" item on the file menu:
RemoveMenu(hmMerge, IDC_ITEM_COPY, MF_BYCOMMAND); }
UINT idMax = Cab_MergeMenus(hmenu, hmMerge, indexMenu, idCmdFirst, idCmdLast, MM_ADDSEPARATOR);
DestroyMenu(hmMerge);
SetMenuDefaultItem(hmenu, IDC_ITEM_EXTRACT+idCmdFirst, FALSE);
return(ResultFromShort(idMax - idCmdFirst)); }
STDMETHODIMP CCabItemMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) { if (lpici->cbSize < SIZEOF(CMINVOKECOMMANDINFO)) { return E_INVALIDARG; } if (HIWORD(lpici->lpVerb)) { // Deal with string commands
LPCMINVOKECOMMANDINFOEX lpicix = (LPCMINVOKECOMMANDINFOEX) lpici; // This value is only usable when fCmdInfoEx is true
#ifdef UNICODE
BOOL fUnicode = FALSE; if ((lpici->cbSize >= CMICEXSIZE_NT4) && ((lpici->fMask & CMIC_MASK_UNICODE) == CMIC_MASK_UNICODE)) { fUnicode = TRUE; } #endif
LPCTSTR pszVerb; #ifdef UNICODE
WCHAR szVerb[MAX_PATH];
if (!fUnicode || lpicix->lpVerbW == NULL) { SHAnsiToUnicode(lpici->lpVerb, szVerb, ARRAYSIZE(szVerb)); pszVerb = szVerb; } else pszVerb = lpicix->lpVerbW; #else
pszVerb = lpici->lpVerb; #endif
UINT idCmd = 0; if (NULL != pszVerb) { if (0 == lstrcmpi(pszVerb, TEXT("copy"))) { idCmd = IDC_ITEM_COPY; } else if (0 == lstrcmpi(pszVerb, TEXT("extract"))) { idCmd = IDC_ITEM_EXTRACT; } } lpici->lpVerb = (LPCSTR) IntToPtr(idCmd); }
switch ((UINT)LOWORD((DWORD_PTR)lpici->lpVerb)) { case IDC_ITEM_EXTRACT: { TCHAR szHere[MAX_PATH]; if (!m_pcfHere->GetPath(szHere)) { return(E_UNEXPECTED); } UINT cPidls = m_lSel.GetCount(); if (0 == cPidls) { return(E_UNEXPECTED); } IDataObject* pdo = (IDataObject*) (new CCabObj(m_hwndOwner, m_pcfHere, m_lSel.GetArray(), cPidls)); if (NULL == pdo) { return(E_OUTOFMEMORY); } // the object is created with a zero ref count, so we need to temporarily
// bump it up if we're going to use it:
pdo->AddRef();
CCabExtract ceHere(szHere);
BOOL fResult = ceHere.ExtractToFolder(m_hwndOwner, pdo, ShouldExtract, (LPARAM)this); pdo->Release();
return fResult ? S_OK : E_FAIL; }
case IDC_ITEM_COPY: { UINT cPidls = m_lSel.GetCount(); if (cPidls > 0) { IDataObject* pObj = (IDataObject*) (new CCabObj(m_hwndOwner, m_pcfHere, m_lSel.GetArray(), cPidls)); if (NULL != pObj) { // the object is created with a zero ref count, so we need to temporarily
// bump it up if we're going to use it:
pObj->AddRef(); HRESULT hr = OleSetClipboard(pObj); pObj->Release(); return hr; } } return E_FAIL; }
default: return(E_INVALIDARG); }
return(NOERROR); }
STDMETHODIMP CCabItemMenu::GetCommandString( UINT_PTR idCmd, UINT uType, UINT * pwReserved, LPSTR pszName, UINT cchMax) { return(E_NOTIMPL); }
HGLOBAL * CALLBACK CCabItemMenu::ShouldExtract(LPCTSTR pszFile, DWORD dwSize, UINT date, UINT time, UINT attribs, LPARAM lParam) { CCabItemMenu *pThis = (CCabItemMenu*)lParam;
if (pThis->m_lSel.IsInList(pszFile, dwSize, date, time, attribs)) { return(EXTRACT_TRUE); }
// Copy nothing for now
return(EXTRACT_FALSE); }
HMENU CCabItemMenu::LoadPopupMenu(UINT id, UINT uSubMenu) { HMENU hmParent = LoadMenu(g_ThisDll.GetInstance(), MAKEINTRESOURCE(id)); if (!hmParent) { return(NULL); }
HMENU hmPopup = GetSubMenu(hmParent, 0); RemoveMenu(hmParent, uSubMenu, MF_BYPOSITION); DestroyMenu(hmParent);
return(hmPopup); }
|