[SHELL32]

- Implement IContextMenu3 interface. Implement drawing the icons on WM_DRAWITEM. CORE-8866

svn path=/trunk/; revision=67009
This commit is contained in:
Giannis Adamopoulos 2015-04-01 20:22:25 +00:00
parent 22c2b66b34
commit b1a175cbfa
2 changed files with 81 additions and 63 deletions

View file

@ -30,17 +30,14 @@ CNewMenu::CNewMenu()
m_pItems = NULL; m_pItems = NULL;
m_pLinkItem = NULL; m_pLinkItem = NULL;
m_pSite = NULL; m_pSite = NULL;
m_hbmFolder = NULL; m_hiconFolder = NULL;
m_hbmLink = NULL; m_hiconLink = NULL;
m_idCmdFirst = 0;
} }
CNewMenu::~CNewMenu() CNewMenu::~CNewMenu()
{ {
UnloadAllItems(); UnloadAllItems();
if (m_hbmFolder)
DeleteObject(m_hbmFolder);
if (m_hbmLink)
DeleteObject(m_hbmLink);
} }
void CNewMenu::UnloadItem(SHELLNEW_ITEM *pItem) void CNewMenu::UnloadItem(SHELLNEW_ITEM *pItem)
@ -50,8 +47,8 @@ void CNewMenu::UnloadItem(SHELLNEW_ITEM *pItem)
free(pItem->pwszDesc); free(pItem->pwszDesc);
free(pItem->pwszExt); free(pItem->pwszExt);
if (pItem->hBitmap) if (pItem->hIcon)
DeleteObject(pItem->hBitmap); DestroyIcon(pItem->hIcon);
HeapFree(GetProcessHeap(), 0, pItem); HeapFree(GetProcessHeap(), 0, pItem);
} }
@ -75,29 +72,6 @@ void CNewMenu::UnloadAllItems()
m_pLinkItem = NULL; m_pLinkItem = NULL;
} }
static HBITMAP IconToBitmap(HICON hIcon)
{
HDC hdc, hdcScr;
HBITMAP hbm, hbmOld;
RECT rc;
hdcScr = GetDC(NULL);
hdc = CreateCompatibleDC(hdcScr);
SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK));
hbm = CreateCompatibleBitmap(hdcScr, rc.right, rc.bottom);
ReleaseDC(NULL, hdcScr);
hbmOld = (HBITMAP)SelectObject(hdc, hbm);
FillRect(hdc, &rc, (HBRUSH)(COLOR_MENU + 1));
if (!DrawIconEx(hdc, 0, 0, hIcon, rc.right, rc.bottom, 0, NULL, DI_NORMAL))
ERR("DrawIcon failed: %x\n", GetLastError());
SelectObject(hdc, hbmOld);
DeleteDC(hdc);
return hbm;
}
CNewMenu::SHELLNEW_ITEM *CNewMenu::LoadItem(LPCWSTR pwszExt) CNewMenu::SHELLNEW_ITEM *CNewMenu::LoadItem(LPCWSTR pwszExt)
{ {
HKEY hKey; HKEY hKey;
@ -179,10 +153,7 @@ CNewMenu::SHELLNEW_ITEM *CNewMenu::LoadItem(LPCWSTR pwszExt)
pNewItem->pwszExt = _wcsdup(pwszExt); pNewItem->pwszExt = _wcsdup(pwszExt);
pNewItem->pwszDesc = _wcsdup(fi.szTypeName); pNewItem->pwszDesc = _wcsdup(fi.szTypeName);
if (fi.hIcon) if (fi.hIcon)
{ pNewItem->hIcon = fi.hIcon;
pNewItem->hBitmap = IconToBitmap(fi.hIcon);
DestroyIcon(fi.hIcon);
}
return pNewItem; return pNewItem;
} }
@ -262,16 +233,11 @@ CNewMenu::InsertShellNewItems(HMENU hMenu, UINT idCmdFirst, UINT Pos)
/* Insert new folder action */ /* Insert new folder action */
if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWFOLDER, wszBuf, _countof(wszBuf))) if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWFOLDER, wszBuf, _countof(wszBuf)))
wszBuf[0] = 0; wszBuf[0] = 0;
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA; mii.fMask = MIIM_ID | MIIM_BITMAP | MIIM_STRING;
mii.fType = MFT_STRING;
mii.dwTypeData = wszBuf; mii.dwTypeData = wszBuf;
mii.cch = wcslen(mii.dwTypeData); mii.cch = wcslen(mii.dwTypeData);
mii.wID = idCmd; mii.wID = idCmd;
if (m_hbmFolder) mii.hbmpItem = HBMMENU_CALLBACK;
{
mii.fMask |= MIIM_CHECKMARKS;
mii.hbmpChecked = mii.hbmpUnchecked = m_hbmFolder;
}
if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii)) if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii))
++idCmd; ++idCmd;
@ -281,11 +247,6 @@ CNewMenu::InsertShellNewItems(HMENU hMenu, UINT idCmdFirst, UINT Pos)
mii.dwTypeData = wszBuf; mii.dwTypeData = wszBuf;
mii.cch = wcslen(mii.dwTypeData); mii.cch = wcslen(mii.dwTypeData);
mii.wID = idCmd; mii.wID = idCmd;
if (m_hbmLink)
{
mii.fMask |= MIIM_CHECKMARKS;
mii.hbmpChecked = mii.hbmpUnchecked = m_hbmLink;
}
if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii)) if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii))
++idCmd; ++idCmd;
@ -296,22 +257,16 @@ CNewMenu::InsertShellNewItems(HMENU hMenu, UINT idCmdFirst, UINT Pos)
InsertMenuItemW(hMenu, Pos++, TRUE, &mii); InsertMenuItemW(hMenu, Pos++, TRUE, &mii);
/* Insert rest of items */ /* Insert rest of items */
mii.fType = MFT_STRING; mii.fMask = MIIM_ID | MIIM_BITMAP | MIIM_STRING;
mii.fState = MFS_ENABLED; mii.fType = 0;
SHELLNEW_ITEM *pCurItem = m_pItems; SHELLNEW_ITEM *pCurItem = m_pItems;
while (pCurItem) while (pCurItem)
{ {
TRACE("szDesc %s\n", debugstr_w(pCurItem->pwszDesc)); TRACE("szDesc %s\n", debugstr_w(pCurItem->pwszDesc));
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
mii.dwTypeData = pCurItem->pwszDesc; mii.dwTypeData = pCurItem->pwszDesc;
mii.cch = wcslen(mii.dwTypeData); mii.cch = wcslen(mii.dwTypeData);
mii.wID = idCmd; mii.wID = idCmd;
if (pCurItem->hBitmap)
{
mii.fMask |= MIIM_CHECKMARKS;
mii.hbmpChecked = mii.hbmpUnchecked = pCurItem->hBitmap;
}
if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii)) if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii))
++idCmd; ++idCmd;
pCurItem = pCurItem->pNext; pCurItem = pCurItem->pNext;
@ -562,6 +517,8 @@ CNewMenu::QueryContextMenu(HMENU hMenu,
MENUITEMINFOW mii; MENUITEMINFOW mii;
UINT cItems = 0; UINT cItems = 0;
m_idCmdFirst = idCmdFirst;
TRACE("%p %p %u %u %u %u\n", this, TRACE("%p %p %u %u %u %u\n", this,
hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
@ -637,15 +594,71 @@ CNewMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
return S_OK; return S_OK;
} }
HRESULT
WINAPI
CNewMenu::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
{
switch (uMsg)
{
case WM_MEASUREITEM:
{
MEASUREITEMSTRUCT* lpmis = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam);
if (!lpmis || lpmis->CtlType != ODT_MENU)
break;
if (lpmis->itemWidth < (UINT)GetSystemMetrics(SM_CXMENUCHECK))
lpmis->itemWidth = GetSystemMetrics(SM_CXMENUCHECK);
if (lpmis->itemHeight < 16)
lpmis->itemHeight = 16;
if (plResult)
*plResult = TRUE;
break;
}
case WM_DRAWITEM:
{
DRAWITEMSTRUCT* lpdis = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
if (!lpdis || lpdis->CtlType != ODT_MENU)
break;
DWORD id = LOWORD(lpdis->itemID) - m_idCmdFirst;
HICON hIcon = 0;
if (id == 0)
hIcon = m_hiconFolder;
else if (id == 1)
hIcon = m_hiconLink;
else
{
SHELLNEW_ITEM *pItem = FindItemFromIdOffset(id);
if (pItem)
hIcon = pItem->hIcon;
}
if (!hIcon)
break;
DrawIconEx(lpdis->hDC,
2,
lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top - 16) / 2,
hIcon,
16,
16,
0, NULL, DI_NORMAL);
if(plResult)
*plResult = TRUE;
}
}
return S_OK;
}
HRESULT WINAPI HRESULT WINAPI
CNewMenu::Initialize(LPCITEMIDLIST pidlFolder, CNewMenu::Initialize(LPCITEMIDLIST pidlFolder,
IDataObject *pdtobj, HKEY hkeyProgID) IDataObject *pdtobj, HKEY hkeyProgID)
{ {
/* Load folder and shortcut icons */ /* Load folder and shortcut icons */
HICON hIcon = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_FOLDER), IMAGE_ICON, 0, 0, LR_SHARED); m_hiconFolder = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_FOLDER), IMAGE_ICON, 16, 16, LR_SHARED);
m_hbmFolder = hIcon ? IconToBitmap(hIcon) : NULL; m_hiconLink = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_SHORTCUT), IMAGE_ICON, 16, 16, LR_SHARED);
hIcon = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_SHORTCUT), IMAGE_ICON, 0, 0, LR_SHARED);
m_hbmLink = hIcon ? IconToBitmap(hIcon) : NULL;
return S_OK; return S_OK;
} }

View file

@ -27,7 +27,7 @@ class CNewMenu :
public CComCoClass<CNewMenu, &CLSID_NewMenu>, public CComCoClass<CNewMenu, &CLSID_NewMenu>,
public CComObjectRootEx<CComMultiThreadModelNoCS>, public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IObjectWithSite, public IObjectWithSite,
public IContextMenu2, public IContextMenu3,
public IShellExtInit public IShellExtInit
{ {
private: private:
@ -47,7 +47,7 @@ private:
PBYTE pData; PBYTE pData;
ULONG cbData; ULONG cbData;
LPWSTR pwszDesc; LPWSTR pwszDesc;
HBITMAP hBitmap; HICON hIcon;
SHELLNEW_ITEM *pNext; SHELLNEW_ITEM *pNext;
}; };
@ -56,7 +56,8 @@ private:
SHELLNEW_ITEM *m_pLinkItem; SHELLNEW_ITEM *m_pLinkItem;
CComPtr<IUnknown> m_pSite; CComPtr<IUnknown> m_pSite;
HMENU m_hSubMenu; HMENU m_hSubMenu;
HBITMAP m_hbmFolder, m_hbmLink; HICON m_hiconFolder, m_hiconLink;
UINT m_idCmdFirst;
SHELLNEW_ITEM *LoadItem(LPCWSTR pwszExt); SHELLNEW_ITEM *LoadItem(LPCWSTR pwszExt);
void UnloadItem(SHELLNEW_ITEM *pItem); void UnloadItem(SHELLNEW_ITEM *pItem);
@ -80,6 +81,9 @@ public:
virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi); virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);
virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen); virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen);
// IContextMenu3
virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
// IContextMenu2 // IContextMenu2
virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam); virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
@ -93,6 +97,7 @@ DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CNewMenu) BEGIN_COM_MAP(CNewMenu)
COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2) COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit) COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit)