Author: janderwald Date: Tue Oct 23 06:00:30 2007 New Revision: 29808
URL: http://svn.reactos.org/svn/reactos?rev=29808&view=rev Log: - 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 :)
Modified: trunk/reactos/dll/win32/shell32/shlview.c trunk/reactos/dll/win32/shell32/shv_bg_cmenu.c trunk/reactos/dll/win32/shell32/shv_item_cmenu.c
Modified: trunk/reactos/dll/win32/shell32/shlview.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shlview.c... ============================================================================== --- trunk/reactos/dll/win32/shell32/shlview.c (original) +++ trunk/reactos/dll/win32/shell32/shlview.c Tue Oct 23 06:00:30 2007 @@ -109,6 +109,7 @@ LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */ UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */ POINT ptLastMousePos; /* Mouse position at last DragOver call */ + IContextMenu2 *pCM; } IShellViewImpl;
static const IShellViewVtbl svvt; @@ -948,7 +949,6 @@ BOOL fExplore = FALSE; HWND hwndTree = 0; LPCONTEXTMENU pContextMenu = NULL; - IContextMenu2 *pCM = NULL; CMINVOKECOMMANDINFO cmi;
TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault); @@ -957,9 +957,9 @@ if( ShellView_GetSelections(This) ) { IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl, - (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu); - - if(pContextMenu) + (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&This->pCM); + + if(This->pCM) { TRACE("-- pContextMenu\n"); hMenu = CreatePopupMenu(); @@ -977,7 +977,7 @@ wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
/* 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) SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND); @@ -1017,16 +1017,19 @@ DestroyMenu(hMenu); } } - if (pContextMenu) - IContextMenu_Release(pContextMenu); + if (This->pCM) + { + IContextMenu_Release(This->pCM); + This->pCM = NULL; + } } } else /* background context menu */ { hMenu = CreatePopupMenu();
- pCM = ISvBgCm_Constructor(This->pSFParent, FALSE); - IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0); + This->pCM = ISvBgCm_Constructor(This->pSFParent, FALSE); + IContextMenu2_QueryContextMenu(This->pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL); DestroyMenu(hMenu); @@ -1037,9 +1040,10 @@ cmi.cbSize = sizeof(cmi); cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand); cmi.hwnd = This->hWndParent; - IContextMenu2_InvokeCommand(pCM, &cmi); - - IContextMenu2_Release(pCM); + IContextMenu2_InvokeCommand(This->pCM, &cmi); + + IContextMenu2_Release(This->pCM); + This->pCM = NULL; } }
@@ -1582,6 +1586,26 @@ } 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 */ @@ -1616,6 +1640,9 @@
case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE); return 0; + case WM_DRAWITEM: + case WM_MEASUREITEM: + return ShellView_DoCustomItem(pThis, hWnd, uMessage, lParam);
case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList); break; @@ -1726,6 +1753,9 @@
if(This->pAdvSink) IAdviseSink_Release(This->pAdvSink); + + if (This->pCM) + IContextMenu_Release(This->pCM);
HeapFree(GetProcessHeap(),0,This); }
Modified: trunk/reactos/dll/win32/shell32/shv_bg_cmenu.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shv_bg_cm... ============================================================================== --- trunk/reactos/dll/win32/shell32/shv_bg_cmenu.c (original) +++ trunk/reactos/dll/win32/shell32/shv_bg_cmenu.c Tue Oct 23 06:00:30 2007 @@ -23,7 +23,7 @@ #define COBJMACROS #define NONAMELESSUNION #define NONAMELESSSTRUCT -//#define YDEBUG +#define YDEBUG #include "wine/debug.h"
#include "windef.h" @@ -36,6 +36,7 @@ #include "undocshell.h" #include "shlwapi.h" #include "stdio.h" +#include "winuser.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
@@ -277,7 +278,6 @@
}
- ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii);
@@ -298,8 +298,8 @@ InsertMenuItemW(hMenu, -1, TRUE, &mii);
- mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA; //MIIM_BITMAP; - mii.fType = MFT_STRING; + mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA; + mii.fType = MFT_OWNERDRAW; mii.fState = MFS_ENABLED;
pCurItem = s_SnHead; @@ -467,6 +467,74 @@ break; } } +} +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 @@ WPARAM wParam, LPARAM lParam) { - BgCmImpl *This = (BgCmImpl *)iface; - - FIXME("(%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam); + BgCmImpl *This = (BgCmImpl *)iface; + DRAWITEMSTRUCT * lpids = (DRAWITEMSTRUCT*) lParam; + MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*) 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; }
Modified: trunk/reactos/dll/win32/shell32/shv_item_cmenu.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shv_item_... ============================================================================== --- trunk/reactos/dll/win32/shell32/shv_item_cmenu.c (original) +++ trunk/reactos/dll/win32/shell32/shv_item_cmenu.c Tue Oct 23 06:00:30 2007 @@ -56,6 +56,8 @@ IContextMenu ** ecmenu; UINT esize; UINT ecount; + UINT iIdSHEFirst; + UINT iIdSHELast; } ItemCmImpl;
UINT @@ -215,6 +217,50 @@ 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 SH_EnlargeContextMenuArray(ItemCmImpl *This, UINT newsize) { @@ -253,7 +299,7 @@ HRESULT hResult; UINT idCmdFirst = 0x5000; UINT idCmdLast = 0xFFF0; - static const WCHAR szAny[] = { '*',0}; + static WCHAR szAny[] = { '*',0};
SH_EnumerateDynamicContextHandlerForKey(szAny, This, pDataObj);
@@ -283,17 +329,16 @@ }
TRACE("SH_LoadContextMenuHandlers num extensions %u\n", This->ecount); - + This->iIdSHEFirst = idCmdFirst; for (i = 0; i < This->ecount; i++) { cmenu = This->ecmenu[i]; - TRACE("Invoking menu %p\n", cmenu); - hResult = cmenu->lpVtbl->QueryContextMenu(hMenu, indexMenu, idCmdFirst, idCmdLast, idCmdLast, CMF_NORMAL); - TRACE("result %x\n",hResult); - } - - - + hResult = cmenu->lpVtbl->QueryContextMenu(cmenu, hMenu, indexMenu, idCmdFirst, idCmdLast, CMF_NORMAL); + idCmdFirst += (hResult & 0xFFFF); + } + This->iIdSHELast = idCmdFirst; + + TRACE("SH_LoadContextMenuHandlers first %x last %x\n", This->iIdSHEFirst, This->iIdSHELast); }
/************************************************************************** @@ -681,10 +726,20 @@ LPARAM lParam) { ItemCmImpl *This = (ItemCmImpl *)iface; - + LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) 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 =