From 5809f6ada61c6193aa5aa8ae60c3ef3878ec849c Mon Sep 17 00:00:00 2001 From: Shriraj Sawant Date: Thu, 29 Jun 2017 12:23:13 +0000 Subject: [PATCH] [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 --- reactos/dll/shellext/qcklnch/CISFBand.cpp | 209 +++++++++++++++--- reactos/dll/shellext/qcklnch/CISFBand.h | 44 +++- .../dll/shellext/qcklnch/CQuickLaunchBand.cpp | 61 +++-- .../dll/shellext/qcklnch/CQuickLaunchBand.h | 27 ++- reactos/dll/shellext/qcklnch/precomp.h | 2 + reactos/dll/shellext/qcklnch/qcklnch.rc | 16 +- reactos/dll/shellext/qcklnch/resource.h | 8 + 7 files changed, 316 insertions(+), 51 deletions(-) create mode 100644 reactos/dll/shellext/qcklnch/resource.h diff --git a/reactos/dll/shellext/qcklnch/CISFBand.cpp b/reactos/dll/shellext/qcklnch/CISFBand.cpp index 35ce841f318..9e8ec78f513 100644 --- a/reactos/dll/shellext/qcklnch/CISFBand.cpp +++ b/reactos/dll/shellext/qcklnch/CISFBand.cpp @@ -41,6 +41,54 @@ LRESULT CISFBand::OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHa return 0; } +LRESULT CISFBand::OnRButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + HRESULT hr; + CComPtr 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 HWND CISFBand::CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst) { @@ -49,41 +97,38 @@ HWND CISFBand::CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst) // Create the toolbar. 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); if (hWndToolbar == NULL) return NULL; // Set the image list. 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); //Enumerate objects - CComPtr pedl; - HRESULT hr2 = m_pISF->EnumObjects(0, SHCONTF_FOLDERS, &pedl); + CComPtr pedl; 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; - for (int i=0; pedl->Next(MAX_PATH, &pidl, 0) != S_FALSE; i++, count++) - { - WCHAR sz[MAX_PATH]; - int index = SHMapPIDLToSystemImageListIndex(m_pISF, pidl, NULL); - m_pISF->GetDisplayNameOf(pidl, SHGDN_NORMAL, &stret); - StrRetToBuf(&stret, pidl, sz, sizeof(sz)); + WCHAR sz[MAX_PATH]; + 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 }; - SendMessage(hWndToolbar, TB_INSERTBUTTONW, 0, (LPARAM)&tb); - } - } - else return NULL; + TBBUTTON tb = { MAKELONG(index, 0), i, TBSTATE_ENABLED, buttonStyles,{ 0 }, (DWORD_PTR)pidl, (INT_PTR)sz }; + SendMessage(hWndToolbar, TB_INSERTBUTTONW, 0, (LPARAM)&tb); + } // Resize the toolbar, and then show it. - SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0); - ::ShowWindow(hWndToolbar, TRUE); + SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0); CoTaskMemFree((void*)pidl); return hWndToolbar; @@ -94,21 +139,22 @@ HWND CISFBand::CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst) // *** IObjectWithSite *** HRESULT STDMETHODCALLTYPE CISFBand::SetSite(IUnknown *pUnkSite) { - HRESULT hRet; + HRESULT hr; HWND hwndParent; TRACE("CISFBand::SetSite(0x%p)\n", pUnkSite); - hRet = IUnknown_GetWindow(pUnkSite, &hwndParent); - if (FAILED(hRet)) + hr = IUnknown_GetWindow(pUnkSite, &hwndParent); + if (FAILED(hr)) { - TRACE("Querying site window failed: 0x%x\n", hRet); - return hRet; + TRACE("Querying site window failed: 0x%x\n", hr); + return hr; } m_Site = pUnkSite; m_hWndTb = CreateSimpleToolbar(hwndParent, m_hInstance); - SubclassWindow(m_hWndTb); + hr = SubclassWindow(m_hWndTb); + if (FAILED_UNEXPECTEDLY(hr)) return hr; return S_OK; } @@ -414,6 +460,117 @@ HWND CISFBand::CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst) 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(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(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 extern "C" diff --git a/reactos/dll/shellext/qcklnch/CISFBand.h b/reactos/dll/shellext/qcklnch/CISFBand.h index 98ecba56966..c8abfd756c5 100644 --- a/reactos/dll/shellext/qcklnch/CISFBand.h +++ b/reactos/dll/shellext/qcklnch/CISFBand.h @@ -18,14 +18,22 @@ class CISFBand : public IPersistStream, public IWinEventHandler, public IOleCommandTarget, - public IShellFolderBand + public IShellFolderBand, + public IContextMenu { - HINSTANCE m_hInstance; + //band + DWORD m_BandID; CComPtr m_Site; + + //Toolbar + HWND m_hWndTb; + HINSTANCE m_hInstance; CComPtr m_pISF; - PCIDLIST_ABSOLUTE m_pidl; - HWND m_hWndTb; - DWORD m_BandID; + PCIDLIST_ABSOLUTE m_pidl; + + //Menu + HMENU m_qMenu; + UINT m_idCmdFirst; public: @@ -35,6 +43,7 @@ public: //Personal Methods HWND CreateSimpleToolbar(HWND hWndParent, HINSTANCE hInst); LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnRButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); //IObjectWithSite @@ -168,10 +177,32 @@ public: virtual HRESULT STDMETHODCALLTYPE SetBandInfoSFB( 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_RBUTTONUP, OnRButtonUp) END_MSG_MAP() DECLARE_NOT_AGGREGATABLE(CISFBand) @@ -186,6 +217,7 @@ public: COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler) COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) COM_INTERFACE_ENTRY_IID(IID_IShellFolderBand, IShellFolderBand) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) END_COM_MAP() }; diff --git a/reactos/dll/shellext/qcklnch/CQuickLaunchBand.cpp b/reactos/dll/shellext/qcklnch/CQuickLaunchBand.cpp index b9f37841741..5ed92247f17 100644 --- a/reactos/dll/shellext/qcklnch/CQuickLaunchBand.cpp +++ b/reactos/dll/shellext/qcklnch/CQuickLaunchBand.cpp @@ -73,22 +73,20 @@ static const GUID CLSID_QuickLaunchBand = { 0x260cb95d, 0x4544, 0x44f6, { 0xa0, HRESULT CQuickLaunchBand::FinalConstruct() { HRESULT hr = CISFBand_CreateInstance(IID_IUnknown, (void**) &m_punkISFB); - if (SUCCEEDED(hr)) - { - CComPtr pISFB; - hr = m_punkISFB->QueryInterface(IID_IShellFolderBand, (void**) &pISFB); - if (SUCCEEDED(hr)) - { - CComPtr pISF; - hr = SHGetDesktopFolder(&pISF); - if (SUCCEEDED(hr)) - { - LPITEMIDLIST pidl = PidlBrowse(m_hWndBro, CSIDL_DESKTOP); - if (pidl == NULL) return E_FAIL; - pISFB->InitializeSFB(pISF, pidl); - } - } - } + if (FAILED_UNEXPECTEDLY(hr)) return hr; + + CComPtr pISFB; + hr = m_punkISFB->QueryInterface(IID_IShellFolderBand, (void**) &pISFB); + if (FAILED_UNEXPECTEDLY(hr)) return hr; + + CComPtr pISF; + hr = SHGetDesktopFolder(&pISF); + if (FAILED_UNEXPECTEDLY(hr)) return hr; + + LPITEMIDLIST pidl = PidlBrowse(m_hWndBro, CSIDL_DESKTOP); + if (pidl == NULL) return E_FAIL; + + pISFB->InitializeSFB(pISF, pidl); return hr; } @@ -359,3 +357,34 @@ static const GUID CLSID_QuickLaunchBand = { 0x260cb95d, 0x4544, 0x44f6, { 0xa0, 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 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 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 pICM; + HRESULT hr = m_punkISFB->QueryInterface(IID_IContextMenu, (void**)&pICM); + if (FAILED(hr)) return hr; + + return pICM->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags); + } \ No newline at end of file diff --git a/reactos/dll/shellext/qcklnch/CQuickLaunchBand.h b/reactos/dll/shellext/qcklnch/CQuickLaunchBand.h index b2185ed43cd..ee017bd0bfc 100644 --- a/reactos/dll/shellext/qcklnch/CQuickLaunchBand.h +++ b/reactos/dll/shellext/qcklnch/CQuickLaunchBand.h @@ -22,7 +22,8 @@ class CQuickLaunchBand : public IDeskBar, public IPersistStream, public IWinEventHandler, - public IOleCommandTarget + public IOleCommandTarget, + public IContextMenu { HWND m_hWndBro; CComPtr m_punkISFB; @@ -155,9 +156,30 @@ class CQuickLaunchBand : /*[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_PROTECT_FINAL_CONSTRUCT() @@ -169,5 +191,6 @@ class CQuickLaunchBand : COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler) COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) END_COM_MAP() }; \ No newline at end of file diff --git a/reactos/dll/shellext/qcklnch/precomp.h b/reactos/dll/shellext/qcklnch/precomp.h index 50e8168984b..ab5d3f33f6d 100644 --- a/reactos/dll/shellext/qcklnch/precomp.h +++ b/reactos/dll/shellext/qcklnch/precomp.h @@ -35,6 +35,8 @@ #include #include +#include "resource.h" + #undef DbgPrint #include "CQuickLaunchBand.h" diff --git a/reactos/dll/shellext/qcklnch/qcklnch.rc b/reactos/dll/shellext/qcklnch/qcklnch.rc index d4f8a553ad1..a7e5b5c4160 100644 --- a/reactos/dll/shellext/qcklnch/qcklnch.rc +++ b/reactos/dll/shellext/qcklnch/qcklnch.rc @@ -1,10 +1,24 @@ #include #include #include +#include "resource.h" 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 diff --git a/reactos/dll/shellext/qcklnch/resource.h b/reactos/dll/shellext/qcklnch/resource.h new file mode 100644 index 00000000000..6d5b3bbdd68 --- /dev/null +++ b/reactos/dll/shellext/qcklnch/resource.h @@ -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