mirror of
https://github.com/reactos/reactos.git
synced 2025-06-22 16:10:18 +00:00
[RSHELL]
* CMenuBand: Begin implementing submenus for shell items. * CMenuBand: Begin implementing context menus. CORE-7881 svn path=/branches/shell-experiments/; revision=62232
This commit is contained in:
parent
d5f6a80f41
commit
b42655951c
2 changed files with 213 additions and 20 deletions
|
@ -51,10 +51,11 @@ public:
|
||||||
virtual HRESULT PopupItem(UINT uItem) = 0;
|
virtual HRESULT PopupItem(UINT uItem) = 0;
|
||||||
virtual HRESULT HasSubMenu(UINT uItem) = 0;
|
virtual HRESULT HasSubMenu(UINT uItem) = 0;
|
||||||
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult) = 0;
|
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult) = 0;
|
||||||
|
virtual HRESULT OnContextMenu(NMMOUSE * rclick) = 0;
|
||||||
|
|
||||||
HRESULT OnHotItemChange(const NMTBHOTITEM * hot);
|
HRESULT OnHotItemChange(const NMTBHOTITEM * hot);
|
||||||
|
|
||||||
HRESULT PopupSubMenu(UINT uItem, IShellMenu* childShellMenu);
|
HRESULT PopupSubMenu(UINT index, IShellMenu* childShellMenu);
|
||||||
|
|
||||||
static LRESULT CALLBACK s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
static LRESULT CALLBACK s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
protected:
|
protected:
|
||||||
|
@ -83,6 +84,8 @@ public:
|
||||||
virtual HRESULT PopupItem(UINT uItem);
|
virtual HRESULT PopupItem(UINT uItem);
|
||||||
virtual HRESULT HasSubMenu(UINT uItem);
|
virtual HRESULT HasSubMenu(UINT uItem);
|
||||||
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
|
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
|
||||||
|
virtual HRESULT OnContextMenu(NMMOUSE * rclick);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HMENU m_hmenu;
|
HMENU m_hmenu;
|
||||||
};
|
};
|
||||||
|
@ -100,9 +103,10 @@ public:
|
||||||
virtual HRESULT PopupItem(UINT uItem);
|
virtual HRESULT PopupItem(UINT uItem);
|
||||||
virtual HRESULT HasSubMenu(UINT uItem);
|
virtual HRESULT HasSubMenu(UINT uItem);
|
||||||
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
|
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
|
||||||
|
virtual HRESULT OnContextMenu(NMMOUSE * rclick);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
LPITEMIDLIST GetPidlFromId(UINT uItem, INT* pIndex);
|
||||||
|
|
||||||
IShellFolder * m_shellFolder;
|
IShellFolder * m_shellFolder;
|
||||||
LPCITEMIDLIST m_idList;
|
LPCITEMIDLIST m_idList;
|
||||||
|
@ -248,6 +252,7 @@ public:
|
||||||
virtual HRESULT STDMETHODCALLTYPE IsEmpty(THIS);
|
virtual HRESULT STDMETHODCALLTYPE IsEmpty(THIS);
|
||||||
|
|
||||||
HRESULT CallCBWithId(UINT Id, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
HRESULT CallCBWithId(UINT Id, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
HRESULT CallCBWithPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
BOOL UseBigIcons() {
|
BOOL UseBigIcons() {
|
||||||
return m_useBigIcons;
|
return m_useBigIcons;
|
||||||
|
@ -957,15 +962,14 @@ HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, IShellMenu* childShellMenu)
|
HRESULT CMenuToolbarBase::PopupSubMenu(UINT index, IShellMenu* childShellMenu)
|
||||||
{
|
{
|
||||||
|
IBandSite* pBandSite;
|
||||||
|
IDeskBar* pDeskBar;
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
RECT rc;
|
RECT rc;
|
||||||
TBBUTTONINFO info = { 0 };
|
|
||||||
info.cbSize = sizeof(TBBUTTONINFO);
|
|
||||||
info.dwMask = 0;
|
|
||||||
int index = SendMessage(m_hwnd, TB_GETBUTTONINFO, uItem, (LPARAM) &info);
|
|
||||||
if (index < 0)
|
|
||||||
return E_FAIL;
|
|
||||||
if (!SendMessage(m_hwnd, TB_GETITEMRECT, index, (LPARAM) &rc))
|
if (!SendMessage(m_hwnd, TB_GETITEMRECT, index, (LPARAM) &rc))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
|
@ -978,10 +982,6 @@ HRESULT CMenuToolbarBase::PopupSubMenu(UINT uItem, IShellMenu* childShellMenu)
|
||||||
POINTL pt = { b.x, b.y };
|
POINTL pt = { b.x, b.y };
|
||||||
RECTL rcl = { a.x, a.y, b.x, b.y }; // maybe-TODO: fetch client area of deskbar?
|
RECTL rcl = { a.x, a.y, b.x, b.y }; // maybe-TODO: fetch client area of deskbar?
|
||||||
|
|
||||||
IBandSite* pBandSite;
|
|
||||||
IDeskBar* pDeskBar;
|
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
#ifndef USE_BUILTIN_MENUSITE
|
#ifndef USE_BUILTIN_MENUSITE
|
||||||
hr = CoCreateInstance(CLSID_MenuBandSite,
|
hr = CoCreateInstance(CLSID_MenuBandSite,
|
||||||
|
@ -1119,6 +1119,56 @@ HRESULT CMenuStaticToolbar::FillToolbar()
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT CMenuStaticToolbar::OnContextMenu(NMMOUSE * rclick)
|
||||||
|
{
|
||||||
|
CComPtr<IContextMenu> contextMenu;
|
||||||
|
HRESULT hr = m_menuBand->CallCBWithId(rclick->dwItemSpec, SMC_GETOBJECT, (WPARAM) &IID_IContextMenu, (LPARAM) &contextMenu);
|
||||||
|
if (hr != S_OK)
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
HMENU hPopup = CreatePopupMenu();
|
||||||
|
|
||||||
|
if (hPopup == NULL)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
int ID_SHELL_CMD_FIRST = 0xF;
|
||||||
|
int ID_SHELL_CMD_LAST = 0x7fef;
|
||||||
|
hr = contextMenu->QueryContextMenu(hPopup, 0, ID_SHELL_CMD_FIRST, ID_SHELL_CMD_LAST, CMF_VERBSONLY);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
DestroyMenu(hPopup);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
POINT pt = rclick->pt;
|
||||||
|
if (!ClientToScreen(m_hwnd, &pt))
|
||||||
|
{
|
||||||
|
DestroyMenu(hPopup);
|
||||||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
CComPtr<IOleWindow> site;
|
||||||
|
hr = m_menuBand->GetSite(IID_PPV_ARG(IOleWindow, &site));
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
DestroyMenu(hPopup);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND hwndSite;
|
||||||
|
hr = site->GetWindow(&hwndSite);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
DestroyMenu(hPopup);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
::TrackPopupMenu(hPopup, 0, pt.x, pt.y, 0, hwndSite, NULL);
|
||||||
|
|
||||||
|
DestroyMenu(hPopup);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT CMenuStaticToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
|
HRESULT CMenuStaticToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
|
||||||
{
|
{
|
||||||
return m_menuBand->CallCBWithId(wParam, SMC_EXEC, 0, 0);
|
return m_menuBand->CallCBWithId(wParam, SMC_EXEC, 0, 0);
|
||||||
|
@ -1131,7 +1181,14 @@ HRESULT CMenuStaticToolbar::PopupItem(UINT uItem)
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
return PopupSubMenu(uItem, shellMenu);
|
TBBUTTONINFO info = { 0 };
|
||||||
|
info.cbSize = sizeof(TBBUTTONINFO);
|
||||||
|
info.dwMask = 0;
|
||||||
|
int index = SendMessage(m_hwnd, TB_GETBUTTONINFO, uItem, (LPARAM) &info);
|
||||||
|
if (index < 0)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
return PopupSubMenu(index, shellMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CMenuStaticToolbar::HasSubMenu(UINT uItem)
|
HRESULT CMenuStaticToolbar::HasSubMenu(UINT uItem)
|
||||||
|
@ -1175,7 +1232,7 @@ HRESULT CMenuSFToolbar::FillToolbar()
|
||||||
INT index = 0;
|
INT index = 0;
|
||||||
INT indexOpen = 0;
|
INT indexOpen = 0;
|
||||||
|
|
||||||
IShellItem *psi;
|
CComPtr<IShellItem> psi;
|
||||||
SHCreateShellItem(NULL, m_shellFolder, item, &psi);
|
SHCreateShellItem(NULL, m_shellFolder, item, &psi);
|
||||||
|
|
||||||
hr = psi->GetDisplayName(SIGDN_NORMALDISPLAY, &MenuString);
|
hr = psi->GetDisplayName(SIGDN_NORMALDISPLAY, &MenuString);
|
||||||
|
@ -1184,9 +1241,18 @@ HRESULT CMenuSFToolbar::FillToolbar()
|
||||||
|
|
||||||
index = SHMapPIDLToSystemImageListIndex(m_shellFolder, item, &indexOpen);
|
index = SHMapPIDLToSystemImageListIndex(m_shellFolder, item, &indexOpen);
|
||||||
|
|
||||||
|
SFGAOF attrs;
|
||||||
|
hr = psi->GetAttributes(SFGAO_FOLDER, &attrs);
|
||||||
|
|
||||||
|
if (attrs != 0)
|
||||||
|
{
|
||||||
|
tbb.fsStyle |= BTNS_WHOLEDROPDOWN;
|
||||||
|
}
|
||||||
|
|
||||||
tbb.idCommand = i++;
|
tbb.idCommand = i++;
|
||||||
tbb.iString = (INT_PTR) MenuString;
|
tbb.iString = (INT_PTR) MenuString;
|
||||||
tbb.iBitmap = index;
|
tbb.iBitmap = index;
|
||||||
|
tbb.dwData = (DWORD_PTR) ILClone(item);
|
||||||
|
|
||||||
SendMessageW(m_hwnd, TB_ADDBUTTONS, 1, (LPARAM) (LPTBBUTTON) &tbb);
|
SendMessageW(m_hwnd, TB_ADDBUTTONS, 1, (LPARAM) (LPTBBUTTON) &tbb);
|
||||||
HeapFree(GetProcessHeap(), 0, MenuString);
|
HeapFree(GetProcessHeap(), 0, MenuString);
|
||||||
|
@ -1236,20 +1302,104 @@ HRESULT CMenuSFToolbar::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REF
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LPITEMIDLIST CMenuSFToolbar::GetPidlFromId(UINT uItem, INT* pIndex)
|
||||||
|
{
|
||||||
|
TBBUTTONINFO info = { 0 };
|
||||||
|
info.cbSize = sizeof(TBBUTTONINFO);
|
||||||
|
info.dwMask = 0;
|
||||||
|
int index = SendMessage(m_hwnd, TB_GETBUTTONINFO, uItem, (LPARAM) &info);
|
||||||
|
if (index < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (pIndex)
|
||||||
|
*pIndex = index;
|
||||||
|
|
||||||
|
TBBUTTON btn = { 0 };
|
||||||
|
if (!SendMessage(m_hwnd, TB_GETBUTTON, index, (LPARAM) &btn))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (LPITEMIDLIST)btn.dwData;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CMenuSFToolbar::OnContextMenu(NMMOUSE * rclick)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
CComPtr<IOleWindow> site;
|
||||||
|
CComPtr<IContextMenu> contextMenu;
|
||||||
|
|
||||||
|
hr = m_menuBand->GetSite(IID_PPV_ARG(IOleWindow, &site));
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND hwndSite;
|
||||||
|
hr = site->GetWindow(&hwndSite);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPITEMIDLIST pidl = GetPidlFromId(rclick->dwItemData, NULL);
|
||||||
|
|
||||||
|
hr = m_shellFolder->GetUIObjectOf(hwndSite, 1, (LPCITEMIDLIST *) &pidl, IID_IContextMenu, NULL, (PVOID *) &contextMenu);
|
||||||
|
if (hr != S_OK)
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
HMENU hPopup = CreatePopupMenu();
|
||||||
|
|
||||||
|
if (hPopup == NULL)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
int ID_SHELL_CMD_FIRST = 0xF;
|
||||||
|
int ID_SHELL_CMD_LAST = 0x7fef;
|
||||||
|
hr = contextMenu->QueryContextMenu(hPopup, 0, ID_SHELL_CMD_FIRST, ID_SHELL_CMD_LAST, CMF_VERBSONLY);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
DestroyMenu(hPopup);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
POINT pt = rclick->pt;
|
||||||
|
if (!ClientToScreen(m_hwnd, &pt))
|
||||||
|
{
|
||||||
|
DestroyMenu(hPopup);
|
||||||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
::TrackPopupMenu(hPopup, 0, pt.x, pt.y, 0, hwndSite, NULL);
|
||||||
|
|
||||||
|
DestroyMenu(hPopup);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT CMenuSFToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
|
HRESULT CMenuSFToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
|
||||||
{
|
{
|
||||||
// TODO: return m_menuBand->CallCBWithPidl(GetPidlFromId(wParam), SMC_SFEXEC, 0, 0);
|
return m_menuBand->CallCBWithPidl(GetPidlFromId(wParam, NULL), SMC_SFEXEC, 0, 0);
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CMenuSFToolbar::PopupItem(UINT uItem)
|
HRESULT CMenuSFToolbar::PopupItem(UINT uItem)
|
||||||
{
|
{
|
||||||
return S_OK;
|
int index;
|
||||||
|
CComPtr<IShellMenu> shellMenu;
|
||||||
|
HRESULT hr = m_menuBand->CallCBWithPidl(GetPidlFromId(uItem, &index), SMC_GETOBJECT, (WPARAM) &IID_IShellMenu, (LPARAM) &shellMenu);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
return PopupSubMenu(index, shellMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CMenuSFToolbar::HasSubMenu(UINT uItem)
|
HRESULT CMenuSFToolbar::HasSubMenu(UINT uItem)
|
||||||
{
|
{
|
||||||
return S_FALSE; // GetSubMenu(m_hmenu, uItem) ? S_OK : S_FALSE;
|
HRESULT hr;
|
||||||
|
CComPtr<IShellItem> psi;
|
||||||
|
SHCreateShellItem(NULL, m_shellFolder, GetPidlFromId(uItem, NULL), &psi);
|
||||||
|
|
||||||
|
SFGAOF attrs;
|
||||||
|
hr = psi->GetAttributes(SFGAO_FOLDER, &attrs);
|
||||||
|
|
||||||
|
return (attrs != 0) ? S_OK : S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMenuBand::CMenuBand() :
|
CMenuBand::CMenuBand() :
|
||||||
|
@ -1811,6 +1961,7 @@ HRESULT STDMETHODCALLTYPE CMenuBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wPa
|
||||||
NMHDR * hdr = (LPNMHDR) lParam;
|
NMHDR * hdr = (LPNMHDR) lParam;
|
||||||
NMTBCUSTOMDRAW * cdraw;
|
NMTBCUSTOMDRAW * cdraw;
|
||||||
NMTBHOTITEM * hot;
|
NMTBHOTITEM * hot;
|
||||||
|
NMMOUSE * rclick;
|
||||||
switch (hdr->code)
|
switch (hdr->code)
|
||||||
{
|
{
|
||||||
case TBN_HOTITEMCHANGE:
|
case TBN_HOTITEMCHANGE:
|
||||||
|
@ -1828,6 +1979,20 @@ HRESULT STDMETHODCALLTYPE CMenuBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wPa
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
|
case NM_RCLICK:
|
||||||
|
rclick = (LPNMMOUSE) hdr;
|
||||||
|
|
||||||
|
if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd))
|
||||||
|
{
|
||||||
|
return m_staticToolbar->OnContextMenu(rclick);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd))
|
||||||
|
{
|
||||||
|
return m_SFToolbar->OnContextMenu(rclick);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
case NM_CUSTOMDRAW:
|
case NM_CUSTOMDRAW:
|
||||||
cdraw = (LPNMTBCUSTOMDRAW) hdr;
|
cdraw = (LPNMTBCUSTOMDRAW) hdr;
|
||||||
switch (cdraw->nmcd.dwDrawStage)
|
switch (cdraw->nmcd.dwDrawStage)
|
||||||
|
@ -1984,6 +2149,34 @@ HRESULT CMenuBand::CallCBWithId(UINT Id, UINT uMsg, WPARAM wParam, LPARAM lParam
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT CMenuBand::CallCBWithPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (!m_psmc)
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
HWND hwnd;
|
||||||
|
GetWindow(&hwnd);
|
||||||
|
|
||||||
|
SMDATA smData = { 0 };
|
||||||
|
smData.punk = (IShellMenu2*)this;
|
||||||
|
smData.uIdParent = m_uId;
|
||||||
|
smData.uIdAncestor = m_uIdAncestor;
|
||||||
|
smData.hwnd = hwnd;
|
||||||
|
smData.pidlItem = pidl;
|
||||||
|
if (m_staticToolbar)
|
||||||
|
{
|
||||||
|
smData.hmenu = m_hmenu;
|
||||||
|
}
|
||||||
|
smData.pvUserData = NULL;
|
||||||
|
if (m_SFToolbar)
|
||||||
|
m_SFToolbar->GetShellFolder(NULL, &smData.pidlFolder, IID_PPV_ARG(IShellFolder, &smData.psf));
|
||||||
|
HRESULT hr = m_psmc->CallbackSM(&smData, uMsg, wParam, lParam);
|
||||||
|
ILFree(smData.pidlFolder);
|
||||||
|
if (smData.psf)
|
||||||
|
smData.psf->Release();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT CMenuBand::_CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
HRESULT CMenuBand::_CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (!m_psmc)
|
if (!m_psmc)
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
||||||
/* NOTE: The following constants may *NOT* be changed because
|
/* NOTE: The following constants *MUST NOT* be changed because
|
||||||
they're hardcoded and need to be the exact values
|
they're hardcoded and need to be the exact values
|
||||||
in order to get the start menu to work! */
|
in order to get the start menu to work! */
|
||||||
#define IDM_PROGRAMS 504
|
#define IDM_PROGRAMS 504
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue