- add a member to shlview to able to track the current context menu

- make the background menu use owner drawn items to show icon (icon not yet shown)
- let the shell item menu also accept owner drawn images
- this makes winrar shellextension appear however the language is _not_ correct in most cases and executing a command is at your own risk :)

svn path=/trunk/; revision=29808
This commit is contained in:
Johannes Anderwald 2007-10-23 02:00:30 +00:00
parent 4ce5c80551
commit 4da0e180ee
3 changed files with 192 additions and 25 deletions

View file

@ -109,6 +109,7 @@ typedef struct
LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */ LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */ UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
POINT ptLastMousePos; /* Mouse position at last DragOver call */ POINT ptLastMousePos; /* Mouse position at last DragOver call */
IContextMenu2 *pCM;
} IShellViewImpl; } IShellViewImpl;
static const IShellViewVtbl svvt; static const IShellViewVtbl svvt;
@ -948,7 +949,6 @@ static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL
BOOL fExplore = FALSE; BOOL fExplore = FALSE;
HWND hwndTree = 0; HWND hwndTree = 0;
LPCONTEXTMENU pContextMenu = NULL; LPCONTEXTMENU pContextMenu = NULL;
IContextMenu2 *pCM = NULL;
CMINVOKECOMMANDINFO cmi; CMINVOKECOMMANDINFO cmi;
TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault); TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
@ -957,9 +957,9 @@ static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL
if( ShellView_GetSelections(This) ) if( ShellView_GetSelections(This) )
{ {
IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl, IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
(REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu); (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&This->pCM);
if(pContextMenu) if(This->pCM)
{ {
TRACE("-- pContextMenu\n"); TRACE("-- pContextMenu\n");
hMenu = CreatePopupMenu(); hMenu = CreatePopupMenu();
@ -977,7 +977,7 @@ static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL
wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0); wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
/* let the ContextMenu merge its items in */ /* let the ContextMenu merge its items in */
if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags ))) if (SUCCEEDED(IContextMenu_QueryContextMenu( This->pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
{ {
if (This->FolderSettings.fFlags & FWF_DESKTOP) if (This->FolderSettings.fFlags & FWF_DESKTOP)
SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND); SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
@ -1017,16 +1017,19 @@ static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL
DestroyMenu(hMenu); DestroyMenu(hMenu);
} }
} }
if (pContextMenu) if (This->pCM)
IContextMenu_Release(pContextMenu); {
IContextMenu_Release(This->pCM);
This->pCM = NULL;
}
} }
} }
else /* background context menu */ else /* background context menu */
{ {
hMenu = CreatePopupMenu(); hMenu = CreatePopupMenu();
pCM = ISvBgCm_Constructor(This->pSFParent, FALSE); This->pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0); IContextMenu2_QueryContextMenu(This->pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL); uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
DestroyMenu(hMenu); DestroyMenu(hMenu);
@ -1037,9 +1040,10 @@ static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL
cmi.cbSize = sizeof(cmi); cmi.cbSize = sizeof(cmi);
cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand); cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
cmi.hwnd = This->hWndParent; cmi.hwnd = This->hWndParent;
IContextMenu2_InvokeCommand(pCM, &cmi); IContextMenu2_InvokeCommand(This->pCM, &cmi);
IContextMenu2_Release(pCM); IContextMenu2_Release(This->pCM);
This->pCM = NULL;
} }
} }
@ -1582,6 +1586,26 @@ static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, L
} }
return TRUE; return TRUE;
} }
/**********************************************************
* ShellView_DoMeasureItem
*/
static LRESULT ShellView_DoCustomItem(IShellViewImpl * pThis, HWND hWnd, UINT uMsg, LPARAM lParam)
{
if (!pThis->pCM)
{
/* no menu */
ERR("no menu!!!\n");
return FALSE;
}
if (pThis->pCM->lpVtbl->HandleMenuMsg(pThis->pCM, uMsg, (WPARAM)hWnd, lParam) == S_OK)
return TRUE;
else
return FALSE;
}
/********************************************************** /**********************************************************
* ShellView_WndProc * ShellView_WndProc
*/ */
@ -1616,6 +1640,9 @@ static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wPara
case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE); case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
return 0; return 0;
case WM_DRAWITEM:
case WM_MEASUREITEM:
return ShellView_DoCustomItem(pThis, hWnd, uMessage, lParam);
case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList); case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
break; break;
@ -1727,6 +1754,9 @@ static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
if(This->pAdvSink) if(This->pAdvSink)
IAdviseSink_Release(This->pAdvSink); IAdviseSink_Release(This->pAdvSink);
if (This->pCM)
IContextMenu_Release(This->pCM);
HeapFree(GetProcessHeap(),0,This); HeapFree(GetProcessHeap(),0,This);
} }
return refCount; return refCount;

View file

@ -23,7 +23,7 @@
#define COBJMACROS #define COBJMACROS
#define NONAMELESSUNION #define NONAMELESSUNION
#define NONAMELESSSTRUCT #define NONAMELESSSTRUCT
//#define YDEBUG #define YDEBUG
#include "wine/debug.h" #include "wine/debug.h"
#include "windef.h" #include "windef.h"
@ -36,6 +36,7 @@
#include "undocshell.h" #include "undocshell.h"
#include "shlwapi.h" #include "shlwapi.h"
#include "stdio.h" #include "stdio.h"
#include "winuser.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell); WINE_DEFAULT_DEBUG_CHANNEL(shell);
@ -277,7 +278,6 @@ InsertShellNewItems(HMENU hMenu, UINT idFirst, UINT idMenu, BgCmImpl * This)
} }
ZeroMemory(&mii, sizeof(mii)); ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii); mii.cbSize = sizeof(mii);
@ -298,8 +298,8 @@ InsertShellNewItems(HMENU hMenu, UINT idFirst, UINT idMenu, BgCmImpl * This)
InsertMenuItemW(hMenu, -1, TRUE, &mii); InsertMenuItemW(hMenu, -1, TRUE, &mii);
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA; //MIIM_BITMAP; mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
mii.fType = MFT_STRING; mii.fType = MFT_OWNERDRAW;
mii.fState = MFS_ENABLED; mii.fState = MFS_ENABLED;
pCurItem = s_SnHead; pCurItem = s_SnHead;
@ -468,6 +468,74 @@ DoShellNewCmd(BgCmImpl * This, LPCMINVOKECOMMANDINFO lpcmi)
} }
} }
} }
HRESULT
DoMeasureItem(BgCmImpl *This, HWND hWnd, MEASUREITEMSTRUCT * lpmis)
{
PSHELLNEW_ITEM pCurItem;
PSHELLNEW_ITEM pItem;
UINT i;
HDC hDC;
SIZE size;
TRACE("DoMeasureItem entered with id %x\n", lpmis->itemID);
pCurItem = s_SnHead;
i = This->iIdShellNewFirst;
pItem = NULL;
while(pCurItem)
{
if (i == lpmis->itemID)
{
pItem = pCurItem;
break;
}
pCurItem = pCurItem->Next;
i++;
}
if (!pItem)
return E_FAIL;
hDC = GetDC(hWnd);
GetTextExtentPoint32W(hDC, pCurItem->szDesc, strlenW(pCurItem->szDesc), &size);
lpmis->itemWidth = size.cx + 32;
lpmis->itemHeight = max(size.cy, 20);
ReleaseDC (hWnd, hDC);
return S_OK;
}
HRESULT
DoDrawItem(BgCmImpl *This, HWND hWnd, DRAWITEMSTRUCT * drawItem)
{
PSHELLNEW_ITEM pCurItem;
PSHELLNEW_ITEM pItem;
UINT i;
pCurItem = s_SnHead;
TRACE("DoDrawItem entered with id %x\n", drawItem->itemID);
i = This->iIdShellNewFirst;
pItem = NULL;
while(pCurItem)
{
if (i == drawItem->itemID)
{
pItem = pCurItem;
break;
}
pCurItem = pCurItem->Next;
i++;
}
if (!pItem)
return E_FAIL;
drawItem->rcItem.left += 20;
DrawTextW(drawItem->hDC, pCurItem->szDesc, wcslen(pCurItem->szDesc), &drawItem->rcItem, 0);
return S_OK;
}
/************************************************************************** /**************************************************************************
@ -870,9 +938,23 @@ static HRESULT WINAPI ISVBgCm_fnHandleMenuMsg(
WPARAM wParam, WPARAM wParam,
LPARAM lParam) LPARAM lParam)
{ {
BgCmImpl *This = (BgCmImpl *)iface; BgCmImpl *This = (BgCmImpl *)iface;
DRAWITEMSTRUCT * lpids = (DRAWITEMSTRUCT*) lParam;
MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*) lParam;
FIXME("(%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam); TRACE("ISVBgCm_fnHandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam);
switch(uMsg)
{
case WM_MEASUREITEM:
if (lpmis->itemID >= This->iIdShellNewFirst && lpmis->itemID <= This->iIdShellNewLast)
return DoMeasureItem(This, (HWND)wParam, lpmis);
break;
case WM_DRAWITEM:
if (lpmis->itemID >= This->iIdShellNewFirst && lpmis->itemID <= This->iIdShellNewLast)
return DoDrawItem(This, (HWND)wParam, lpids);
break;
}
return E_NOTIMPL; return E_NOTIMPL;
} }

View file

@ -56,6 +56,8 @@ typedef struct
IContextMenu ** ecmenu; IContextMenu ** ecmenu;
UINT esize; UINT esize;
UINT ecount; UINT ecount;
UINT iIdSHEFirst;
UINT iIdSHELast;
} ItemCmImpl; } ItemCmImpl;
UINT UINT
@ -215,6 +217,50 @@ void WINAPI _InsertMenuItem (
InsertMenuItemA( hmenu, indexMenu, fByPosition, &mii); InsertMenuItemA( hmenu, indexMenu, fByPosition, &mii);
} }
HRESULT
DoCustomItemAction(ItemCmImpl *This, LPARAM lParam, UINT uMsg)
{
IContextMenu2 * cmenu;
IContextMenu * menu;
MEASUREITEMSTRUCT * lpmis = (MEASUREITEMSTRUCT *)lParam;
DRAWITEMSTRUCT * drawItem = (DRAWITEMSTRUCT *)lParam;
HRESULT hResult;
TRACE("DoCustomItemAction entered with uMsg %x lParam %p\n", uMsg, lParam);
if (uMsg == WM_MEASUREITEM)
{
menu = This->ecmenu[lpmis->itemID - This->iIdSHEFirst];
}
else if (uMsg == WM_DRAWITEM)
{
menu = This->ecmenu[drawItem->itemID - This->iIdSHEFirst];
}
else
{
ERR("unexpected message\n");
return E_FAIL;
}
if (!menu)
{
ERR("item is not valid\n");
return E_FAIL;
}
hResult = menu->lpVtbl->QueryInterface(menu, &IID_IContextMenu2, (void**)&cmenu);
if (hResult != S_OK)
{
ERR("failed to get IID_IContextMenu2 interface\n");
return hResult;
}
hResult = cmenu->lpVtbl->HandleMenuMsg(cmenu, uMsg, (WPARAM)0, lParam);
TRACE("returning hResult %x\n", hResult);
return hResult;
}
BOOL BOOL
SH_EnlargeContextMenuArray(ItemCmImpl *This, UINT newsize) SH_EnlargeContextMenuArray(ItemCmImpl *This, UINT newsize)
{ {
@ -253,7 +299,7 @@ SH_LoadContextMenuHandlers(ItemCmImpl *This, IDataObject * pDataObj, HMENU hMenu
HRESULT hResult; HRESULT hResult;
UINT idCmdFirst = 0x5000; UINT idCmdFirst = 0x5000;
UINT idCmdLast = 0xFFF0; UINT idCmdLast = 0xFFF0;
static const WCHAR szAny[] = { '*',0}; static WCHAR szAny[] = { '*',0};
SH_EnumerateDynamicContextHandlerForKey(szAny, This, pDataObj); SH_EnumerateDynamicContextHandlerForKey(szAny, This, pDataObj);
@ -283,17 +329,16 @@ SH_LoadContextMenuHandlers(ItemCmImpl *This, IDataObject * pDataObj, HMENU hMenu
} }
TRACE("SH_LoadContextMenuHandlers num extensions %u\n", This->ecount); TRACE("SH_LoadContextMenuHandlers num extensions %u\n", This->ecount);
This->iIdSHEFirst = idCmdFirst;
for (i = 0; i < This->ecount; i++) for (i = 0; i < This->ecount; i++)
{ {
cmenu = This->ecmenu[i]; cmenu = This->ecmenu[i];
TRACE("Invoking menu %p\n", cmenu); hResult = cmenu->lpVtbl->QueryContextMenu(cmenu, hMenu, indexMenu, idCmdFirst, idCmdLast, CMF_NORMAL);
hResult = cmenu->lpVtbl->QueryContextMenu(hMenu, indexMenu, idCmdFirst, idCmdLast, idCmdLast, CMF_NORMAL); idCmdFirst += (hResult & 0xFFFF);
TRACE("result %x\n",hResult);
} }
This->iIdSHELast = idCmdFirst;
TRACE("SH_LoadContextMenuHandlers first %x last %x\n", This->iIdSHEFirst, This->iIdSHELast);
} }
/************************************************************************** /**************************************************************************
@ -681,10 +726,20 @@ static HRESULT WINAPI ISvItemCm_fnHandleMenuMsg(
LPARAM lParam) LPARAM lParam)
{ {
ItemCmImpl *This = (ItemCmImpl *)iface; ItemCmImpl *This = (ItemCmImpl *)iface;
LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam;
TRACE("(%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam); TRACE("(%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam);
return E_NOTIMPL; switch(uMsg)
{
case WM_MEASUREITEM:
case WM_DRAWITEM:
if (lpmis->itemID >= This->iIdSHEFirst && lpmis->itemID <= This->iIdSHELast)
return DoCustomItemAction(This, lParam, uMsg);
break;
}
return E_NOTIMPL;
} }
static const IContextMenu2Vtbl cmvt = static const IContextMenu2Vtbl cmvt =