[QCKLNCH]

-Created menu resource in qcklnch.rc
-Added resource.h to manage menu resources and all.
-Added IContextMenu.
-Implemented QueryContextMenu and stubbed other methods.
-Handled WM_RBUTTONUP for folder context menus.
-Minor code corrections.
-Tested working of some menu functions in winXP VM, though further testing is required.

svn path=/branches/GSoC_2017/shellext/; revision=75231
This commit is contained in:
Shriraj Sawant 2017-06-29 12:23:13 +00:00
parent 8c802b5ece
commit 5809f6ada6
7 changed files with 316 additions and 51 deletions

View file

@ -41,6 +41,54 @@ LRESULT CISFBand::OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHa
return 0; return 0;
} }
LRESULT CISFBand::OnRButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HRESULT hr;
CComPtr<IContextMenu> picm;
HMENU fmenu = CreatePopupMenu();
TBBUTTON tb;
POINT pt;
DWORD pos = GetMessagePos();
pt.x = GET_X_LPARAM(pos);
pt.y = GET_Y_LPARAM(pos);
ScreenToClient(&pt);
int index = SendMessage(m_hWndTb, TB_HITTEST, 0, (LPARAM)&pt);
bool chk = SendMessage(m_hWndTb, TB_GETBUTTON, abs(index), (LPARAM)&tb);
LPITEMIDLIST pidl = (LPITEMIDLIST)tb.dwData;
if (chk)
{
ClientToScreen(&pt);
hr = m_pISF->GetUIObjectOf(m_hWndTb, 1, &pidl, IID_IContextMenu, NULL, (void**)&picm);
hr = picm->QueryContextMenu(fmenu, 0, 1, 0x7FFF, CMF_DEFAULTONLY);
int id = TrackPopupMenuEx(fmenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RETURNCMD, pt.x, pt.y, m_hWndTb, 0);
if (id > 0)
{
CMINVOKECOMMANDINFOEX info = { 0 };
info.cbSize = sizeof(info);
info.fMask = CMIC_MASK_UNICODE | CMIC_MASK_PTINVOKE;
if (GetKeyState(VK_CONTROL) < 0)
{
info.fMask |= CMIC_MASK_CONTROL_DOWN;
}
if (GetKeyState(VK_SHIFT) < 0)
{
info.fMask |= CMIC_MASK_SHIFT_DOWN;
}
info.hwnd = m_hWndTb;
info.lpVerb = MAKEINTRESOURCEA(id - 1);
info.lpVerbW = MAKEINTRESOURCEW(id - 0x7FFF);
info.nShow = SW_SHOWNORMAL;
info.ptInvoke = pt;
picm->InvokeCommand((LPCMINVOKECOMMANDINFO)&info);
}
}
DestroyMenu(fmenu);
return 0;
}
//ToolbarTest //ToolbarTest
HWND CISFBand::CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst) HWND CISFBand::CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst)
{ {
@ -49,41 +97,38 @@ HWND CISFBand::CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst)
// Create the toolbar. // Create the toolbar.
HWND hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, HWND hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
WS_CHILD | TBSTYLE_FLAT | TBSTYLE_LIST | CCS_NORESIZE, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, WS_CHILD | TBSTYLE_FLAT | TBSTYLE_LIST | CCS_NORESIZE | CCS_NODIVIDER, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
hWndParent, NULL, hInst, NULL); hWndParent, NULL, hInst, NULL);
if (hWndToolbar == NULL) if (hWndToolbar == NULL)
return NULL; return NULL;
// Set the image list. // Set the image list.
HIMAGELIST* piml; HIMAGELIST* piml;
HRESULT hr1 = SHGetImageList(SHIL_SMALL, IID_IImageList, (void**)&piml); HRESULT hr = SHGetImageList(SHIL_SMALL, IID_IImageList, (void**)&piml);
if (FAILED_UNEXPECTEDLY(hr)) return NULL;
SendMessage(hWndToolbar, TB_SETIMAGELIST, 0, (LPARAM)piml); SendMessage(hWndToolbar, TB_SETIMAGELIST, 0, (LPARAM)piml);
//Enumerate objects //Enumerate objects
CComPtr<IEnumIDList> pedl; CComPtr<IEnumIDList> pedl;
HRESULT hr2 = m_pISF->EnumObjects(0, SHCONTF_FOLDERS, &pedl);
LPITEMIDLIST pidl = NULL; LPITEMIDLIST pidl = NULL;
STRRET stret; STRRET stret;
ULONG count = 0;
hr = m_pISF->EnumObjects(0, SHCONTF_FOLDERS, &pedl);
if (FAILED_UNEXPECTEDLY(hr)) return NULL;
if (SUCCEEDED(hr1) && SUCCEEDED(hr2)) for (int i=0; pedl->Next(1, &pidl, 0) != S_FALSE; i++, count++)
{ {
ULONG count = 0; WCHAR sz[MAX_PATH];
for (int i=0; pedl->Next(MAX_PATH, &pidl, 0) != S_FALSE; i++, count++) int index = SHMapPIDLToSystemImageListIndex(m_pISF, pidl, NULL);
{ m_pISF->GetDisplayNameOf(pidl, SHGDN_NORMAL, &stret);
WCHAR sz[MAX_PATH]; StrRetToBuf(&stret, pidl, sz, sizeof(sz));
int index = SHMapPIDLToSystemImageListIndex(m_pISF, pidl, NULL);
m_pISF->GetDisplayNameOf(pidl, SHGDN_NORMAL, &stret);
StrRetToBuf(&stret, pidl, sz, sizeof(sz));
TBBUTTON tb = { MAKELONG(index, 0), i, TBSTATE_ENABLED, buttonStyles,{ 0 }, (DWORD_PTR)pidl, (INT_PTR)sz }; TBBUTTON tb = { MAKELONG(index, 0), i, TBSTATE_ENABLED, buttonStyles,{ 0 }, (DWORD_PTR)pidl, (INT_PTR)sz };
SendMessage(hWndToolbar, TB_INSERTBUTTONW, 0, (LPARAM)&tb); SendMessage(hWndToolbar, TB_INSERTBUTTONW, 0, (LPARAM)&tb);
} }
}
else return NULL;
// Resize the toolbar, and then show it. // Resize the toolbar, and then show it.
SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0); SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
::ShowWindow(hWndToolbar, TRUE);
CoTaskMemFree((void*)pidl); CoTaskMemFree((void*)pidl);
return hWndToolbar; return hWndToolbar;
@ -94,21 +139,22 @@ HWND CISFBand::CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst)
// *** IObjectWithSite *** // *** IObjectWithSite ***
HRESULT STDMETHODCALLTYPE CISFBand::SetSite(IUnknown *pUnkSite) HRESULT STDMETHODCALLTYPE CISFBand::SetSite(IUnknown *pUnkSite)
{ {
HRESULT hRet; HRESULT hr;
HWND hwndParent; HWND hwndParent;
TRACE("CISFBand::SetSite(0x%p)\n", pUnkSite); TRACE("CISFBand::SetSite(0x%p)\n", pUnkSite);
hRet = IUnknown_GetWindow(pUnkSite, &hwndParent); hr = IUnknown_GetWindow(pUnkSite, &hwndParent);
if (FAILED(hRet)) if (FAILED(hr))
{ {
TRACE("Querying site window failed: 0x%x\n", hRet); TRACE("Querying site window failed: 0x%x\n", hr);
return hRet; return hr;
} }
m_Site = pUnkSite; m_Site = pUnkSite;
m_hWndTb = CreateSimpleToolbar(hwndParent, m_hInstance); m_hWndTb = CreateSimpleToolbar(hwndParent, m_hInstance);
SubclassWindow(m_hWndTb); hr = SubclassWindow(m_hWndTb);
if (FAILED_UNEXPECTEDLY(hr)) return hr;
return S_OK; return S_OK;
} }
@ -414,6 +460,117 @@ HWND CISFBand::CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst)
return E_NOTIMPL; return E_NOTIMPL;
} }
/*****************************************************************************/
// *** IContextMenu ***
HRESULT STDMETHODCALLTYPE CISFBand::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
{
/*HRESULT hr = E_INVALIDARG;
if (idCmd == IDM_DISPLAY)
{
switch (uFlags)
{
case GCS_HELPTEXTW:
// Only useful for pre-Vista versions of Windows that
// have a Status bar.
hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName),
cchMax,
L"Display File Name");
break;
case GCS_VERBW:
// GCS_VERBW is an optional feature that enables a caller
// to discover the canonical name for the verb that is passed in
// through idCommand.
hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName),
cchMax,
L"DisplayFileName");
break;
}
}
return hr; */
return S_OK;
}
HRESULT STDMETHODCALLTYPE CISFBand::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
/* BOOL fEx = FALSE;
BOOL fUnicode = FALSE;
if (pici->cbSize == sizeof(CMINVOKECOMMANDINFOEX))
{
fEx = TRUE;
if ((pici->fMask & CMIC_MASK_UNICODE))
{
fUnicode = TRUE;
}
}
if (!fUnicode && HIWORD(pici->lpVerb))
{
if (StrCmpIA(pici->lpVerb, m_pszVerb))
{
return E_FAIL;
}
}
else if (fUnicode && HIWORD(((CMINVOKECOMMANDINFOEX *)pici)->lpVerbW))
{
if (StrCmpIW(((CMINVOKECOMMANDINFOEX *)pici)->lpVerbW, m_pwszVerb))
{
return E_FAIL;
}
}
else if (LOWORD(pici->lpVerb) != IDM_DISPLAY)
{
return E_FAIL;
}
else
{
::MessageBox(pici->hwnd,
L"The File Name",
L"File Name",
MB_OK | MB_ICONINFORMATION);
}*/
if (!HIWORD(pici->lpVerb))
{
switch (LOWORD(pici->lpVerb) /*- m_idCmdFirst*/)
{
case IDM_LARGE_ICONS:
{
::MessageBox(0, L"IDM_LARGE_ICONS", L"Test", MB_OK | MB_ICONINFORMATION);
break;
}
case IDM_SMALL_ICONS:
{
::MessageBox(0, L"IDM_SMALL_ICONS", L"Test", MB_OK | MB_ICONINFORMATION);
break;
}
case IDM_SHOW_TEXT:
{
::MessageBox(0, L"IDM_SHOW_TEXT", L"Test", MB_OK | MB_ICONINFORMATION);
break;
}
}
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CISFBand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
m_idCmdFirst = idCmdFirst;
m_qMenu = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDR_POPUPMENU));
m_qMenu = GetSubMenu(m_qMenu, 0);
UINT idMax = Shell_MergeMenus(hmenu, m_qMenu, indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS);
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(idMax - idCmdFirst +1));
}
/*****************************************************************************/ /*****************************************************************************/
//C Constructor //C Constructor
extern "C" extern "C"

View file

@ -18,14 +18,22 @@ class CISFBand :
public IPersistStream, public IPersistStream,
public IWinEventHandler, public IWinEventHandler,
public IOleCommandTarget, public IOleCommandTarget,
public IShellFolderBand public IShellFolderBand,
public IContextMenu
{ {
HINSTANCE m_hInstance; //band
DWORD m_BandID;
CComPtr<IUnknown> m_Site; CComPtr<IUnknown> m_Site;
//Toolbar
HWND m_hWndTb;
HINSTANCE m_hInstance;
CComPtr<IShellFolder> m_pISF; CComPtr<IShellFolder> m_pISF;
PCIDLIST_ABSOLUTE m_pidl; PCIDLIST_ABSOLUTE m_pidl;
HWND m_hWndTb;
DWORD m_BandID; //Menu
HMENU m_qMenu;
UINT m_idCmdFirst;
public: public:
@ -35,6 +43,7 @@ public:
//Personal Methods //Personal Methods
HWND CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst); HWND CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst);
LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnRButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//IObjectWithSite //IObjectWithSite
@ -168,10 +177,32 @@ public:
virtual HRESULT STDMETHODCALLTYPE SetBandInfoSFB( virtual HRESULT STDMETHODCALLTYPE SetBandInfoSFB(
PBANDINFOSFB pbi PBANDINFOSFB pbi
); );
//IContextMenu
virtual HRESULT STDMETHODCALLTYPE GetCommandString(
UINT_PTR idCmd,
UINT uFlags,
UINT *pwReserved,
LPSTR pszName,
UINT cchMax
);
virtual HRESULT STDMETHODCALLTYPE InvokeCommand(
LPCMINVOKECOMMANDINFO pici
);
virtual HRESULT STDMETHODCALLTYPE QueryContextMenu(
HMENU hmenu,
UINT indexMenu,
UINT idCmdFirst,
UINT idCmdLast,
UINT uFlags
);
//***************************************************************************************************** //*****************************************************************************************************
BEGIN_MSG_MAP(CStartButton) BEGIN_MSG_MAP(CISFBand)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_RBUTTONUP, OnRButtonUp)
END_MSG_MAP() END_MSG_MAP()
DECLARE_NOT_AGGREGATABLE(CISFBand) DECLARE_NOT_AGGREGATABLE(CISFBand)
@ -186,6 +217,7 @@ public:
COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler) COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
COM_INTERFACE_ENTRY_IID(IID_IShellFolderBand, IShellFolderBand) COM_INTERFACE_ENTRY_IID(IID_IShellFolderBand, IShellFolderBand)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
END_COM_MAP() END_COM_MAP()
}; };

View file

@ -73,22 +73,20 @@ static const GUID CLSID_QuickLaunchBand = { 0x260cb95d, 0x4544, 0x44f6, { 0xa0,
HRESULT CQuickLaunchBand::FinalConstruct() HRESULT CQuickLaunchBand::FinalConstruct()
{ {
HRESULT hr = CISFBand_CreateInstance(IID_IUnknown, (void**) &m_punkISFB); HRESULT hr = CISFBand_CreateInstance(IID_IUnknown, (void**) &m_punkISFB);
if (SUCCEEDED(hr)) if (FAILED_UNEXPECTEDLY(hr)) return hr;
{
CComPtr<IShellFolderBand> pISFB; CComPtr<IShellFolderBand> pISFB;
hr = m_punkISFB->QueryInterface(IID_IShellFolderBand, (void**) &pISFB); hr = m_punkISFB->QueryInterface(IID_IShellFolderBand, (void**) &pISFB);
if (SUCCEEDED(hr)) if (FAILED_UNEXPECTEDLY(hr)) return hr;
{
CComPtr<IShellFolder> pISF; CComPtr<IShellFolder> pISF;
hr = SHGetDesktopFolder(&pISF); hr = SHGetDesktopFolder(&pISF);
if (SUCCEEDED(hr)) if (FAILED_UNEXPECTEDLY(hr)) return hr;
{
LPITEMIDLIST pidl = PidlBrowse(m_hWndBro, CSIDL_DESKTOP); LPITEMIDLIST pidl = PidlBrowse(m_hWndBro, CSIDL_DESKTOP);
if (pidl == NULL) return E_FAIL; if (pidl == NULL) return E_FAIL;
pISFB->InitializeSFB(pISF, pidl);
} pISFB->InitializeSFB(pISF, pidl);
}
}
return hr; return hr;
} }
@ -359,3 +357,34 @@ static const GUID CLSID_QuickLaunchBand = { 0x260cb95d, 0x4544, 0x44f6, { 0xa0,
return pOCT->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); return pOCT->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
} }
/*****************************************************************************/
// *** IContextMenu ***
HRESULT STDMETHODCALLTYPE CQuickLaunchBand::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
{
//Internal CISFBand Calls
CComPtr<IContextMenu> pICM;
HRESULT hr = m_punkISFB->QueryInterface(IID_IContextMenu, (void**)&pICM);
if (FAILED(hr)) return hr;
return pICM->GetCommandString(idCmd, uFlags, pwReserved, pszName, cchMax);
}
HRESULT STDMETHODCALLTYPE CQuickLaunchBand::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
//Internal CISFBand Calls
CComPtr<IContextMenu> pICM;
HRESULT hr = m_punkISFB->QueryInterface(IID_IContextMenu, (void**)&pICM);
if (FAILED(hr)) return hr;
return pICM->InvokeCommand(pici);
}
HRESULT STDMETHODCALLTYPE CQuickLaunchBand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
//Internal CISFBand Calls
CComPtr<IContextMenu> pICM;
HRESULT hr = m_punkISFB->QueryInterface(IID_IContextMenu, (void**)&pICM);
if (FAILED(hr)) return hr;
return pICM->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
}

View file

@ -22,7 +22,8 @@ class CQuickLaunchBand :
public IDeskBar, public IDeskBar,
public IPersistStream, public IPersistStream,
public IWinEventHandler, public IWinEventHandler,
public IOleCommandTarget public IOleCommandTarget,
public IContextMenu
{ {
HWND m_hWndBro; HWND m_hWndBro;
CComPtr<IUnknown> m_punkISFB; CComPtr<IUnknown> m_punkISFB;
@ -155,9 +156,30 @@ class CQuickLaunchBand :
/*[in, out]*/ OLECMDTEXT *pCmdText /*[in, out]*/ OLECMDTEXT *pCmdText
); );
//IContextMenu
virtual HRESULT STDMETHODCALLTYPE GetCommandString(
UINT_PTR idCmd,
UINT uFlags,
UINT *pwReserved,
LPSTR pszName,
UINT cchMax
);
virtual HRESULT STDMETHODCALLTYPE InvokeCommand(
LPCMINVOKECOMMANDINFO pici
);
virtual HRESULT STDMETHODCALLTYPE QueryContextMenu(
HMENU hmenu,
UINT indexMenu,
UINT idCmdFirst,
UINT idCmdLast,
UINT uFlags
);
//***************************************************************************************************** //*****************************************************************************************************
DECLARE_REGISTRY_RESOURCEID(1001) DECLARE_REGISTRY_RESOURCEID(IDR_QCKLNCH)
DECLARE_NOT_AGGREGATABLE(CQuickLaunchBand) DECLARE_NOT_AGGREGATABLE(CQuickLaunchBand)
DECLARE_PROTECT_FINAL_CONSTRUCT() DECLARE_PROTECT_FINAL_CONSTRUCT()
@ -169,5 +191,6 @@ class CQuickLaunchBand :
COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler) COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
END_COM_MAP() END_COM_MAP()
}; };

View file

@ -35,6 +35,8 @@
#include <wine/debug.h> #include <wine/debug.h>
#include <wine/unicode.h> #include <wine/unicode.h>
#include "resource.h"
#undef DbgPrint #undef DbgPrint
#include "CQuickLaunchBand.h" #include "CQuickLaunchBand.h"

View file

@ -1,10 +1,24 @@
#include <windef.h> #include <windef.h>
#include <winuser.h> #include <winuser.h>
#include <commctrl.h> #include <commctrl.h>
#include "resource.h"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
1001 REGISTRY "rgs/qcklnch.rgs" IDR_QCKLNCH REGISTRY "rgs/qcklnch.rgs"
IDR_POPUPMENU MENUEX DISCARDABLE
BEGIN
POPUP ""
BEGIN
POPUP "&View", IDM_VIEW_MENU
BEGIN
MENUITEM "&Large Icons", IDM_LARGE_ICONS
MENUITEM "&Small Icons", IDM_SMALL_ICONS
END
MENUITEM "&Show Text", IDM_SHOW_TEXT
END
END
#include <reactos/manifest_dll.rc> #include <reactos/manifest_dll.rc>

View file

@ -0,0 +1,8 @@
#pragma once
#define IDR_QCKLNCH 1001
#define IDR_POPUPMENU 2000
#define IDM_LARGE_ICONS 1
#define IDM_SMALL_ICONS 2
#define IDM_SHOW_TEXT 3
#define IDM_VIEW_MENU 4