4 * Copyright 2014 David Quintana
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <CommonControls.h>
23 #include <shlwapi_undoc.h>
25 #include "CMenuBand.h"
26 #include "CMenuToolbars.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(CMenuToolbars
);
31 HRESULT WINAPI
SHGetImageList(
37 #define TBSTYLE_EX_VERTICAL 4
40 #define TIMERID_HOTTRACK 1
41 #define SUBCLASS_ID_MENUBAND 1
43 CMenuToolbarBase::CMenuToolbarBase(CMenuBand
*menuBand
, BOOL usePager
) :
52 HRESULT
CMenuToolbarBase::IsWindowOwner(HWND hwnd
)
54 return (m_hwnd
&& m_hwnd
== hwnd
) ||
55 (m_hwndToolbar
&& m_hwndToolbar
== hwnd
) ? S_OK
: S_FALSE
;
58 void CMenuToolbarBase::InvalidateDraw()
60 InvalidateRect(m_hwnd
, NULL
, FALSE
);
63 HRESULT
CMenuToolbarBase::ShowWindow(BOOL fShow
)
65 ::ShowWindow(m_hwnd
, fShow
? SW_SHOW
: SW_HIDE
);
72 HRESULT
CMenuToolbarBase::UpdateImageLists()
75 if (m_menuBand
->UseBigIcons())
78 SendMessageW(m_hwndToolbar
, TB_SETPADDING
, 0, MAKELPARAM(4, 0));
83 SendMessageW(m_hwndToolbar
, TB_SETPADDING
, 0, MAKELPARAM(4, 4));
87 HRESULT hr
= SHGetImageList(shiml
, IID_PPV_ARG(IImageList
, &piml
));
90 SendMessageW(m_hwndToolbar
, TB_SETIMAGELIST
, 0, reinterpret_cast<LPARAM
>(piml
));
94 SendMessageW(m_hwndToolbar
, TB_SETIMAGELIST
, 0, 0);
99 HRESULT
CMenuToolbarBase::Close()
101 DestroyWindow(m_hwndToolbar
);
102 if (m_hwndToolbar
!= m_hwnd
)
103 DestroyWindow(m_hwnd
);
104 m_hwndToolbar
= NULL
;
109 HRESULT
CMenuToolbarBase::CreateToolbar(HWND hwndParent
, DWORD dwFlags
)
111 LONG tbStyles
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
112 TBSTYLE_TOOLTIPS
| TBSTYLE_TRANSPARENT
| TBSTYLE_REGISTERDROP
| TBSTYLE_LIST
| TBSTYLE_FLAT
| TBSTYLE_CUSTOMERASE
|
113 CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
;
114 LONG tbExStyles
= TBSTYLE_EX_DOUBLEBUFFER
;
116 if (dwFlags
& SMINIT_VERTICAL
)
118 tbStyles
|= CCS_VERT
;
119 tbExStyles
|= TBSTYLE_EX_VERTICAL
| WS_EX_TOOLWINDOW
;
124 if (!::GetClientRect(hwndParent
, &rc
) || (rc
.left
== rc
.right
) || (rc
.top
== rc
.bottom
))
132 HWND hwndToolbar
= CreateWindowEx(
133 tbExStyles
, TOOLBARCLASSNAMEW
, NULL
,
134 tbStyles
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
135 hwndParent
, NULL
, _AtlBaseModule
.GetModuleInstance(), 0);
137 if (hwndToolbar
== NULL
)
142 LONG pgStyles
= PGS_VERT
| WS_CHILD
| WS_VISIBLE
;
145 HWND hwndPager
= CreateWindowEx(
146 pgExStyles
, WC_PAGESCROLLER
, NULL
,
147 pgStyles
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
148 hwndParent
, NULL
, _AtlBaseModule
.GetModuleInstance(), 0);
150 ::SetParent(hwndToolbar
, hwndPager
);
151 ::SetParent(hwndPager
, hwndParent
);
153 SendMessage(hwndPager
, PGM_SETCHILD
, 0, reinterpret_cast<LPARAM
>(hwndToolbar
));
154 m_hwndToolbar
= hwndToolbar
;
159 ::SetParent(hwndToolbar
, hwndParent
);
160 m_hwndToolbar
= hwndToolbar
;
161 m_hwnd
= hwndToolbar
;
164 /* Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure */
165 SendMessageW(hwndToolbar
, TB_BUTTONSTRUCTSIZE
, sizeof(TBBUTTON
), 0);
167 //if (dwFlags & SMINIT_TOPLEVEL)
169 // /* Hide the placeholders for the button images */
170 // SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0);
174 SetWindowLongPtr(hwndToolbar
, GWLP_USERDATA
, reinterpret_cast<LONG_PTR
>(this));
175 m_SubclassOld
= (WNDPROC
) SetWindowLongPtr(hwndToolbar
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(CMenuToolbarBase::s_SubclassProc
));
182 HRESULT
CMenuToolbarBase::GetIdealSize(SIZE
& size
)
184 size
.cx
= size
.cy
= 0;
186 if (m_hwndToolbar
&& !m_hasIdealSize
)
188 SendMessageW(m_hwndToolbar
, TB_AUTOSIZE
, 0, 0);
189 SendMessageW(m_hwndToolbar
, TB_GETMAXSIZE
, 0, reinterpret_cast<LPARAM
>(&m_idealSize
));
190 m_hasIdealSize
= TRUE
;
198 HRESULT
CMenuToolbarBase::SetPosSize(int x
, int y
, int cx
, int cy
)
200 if (m_hwnd
!= m_hwndToolbar
)
202 SetWindowPos(m_hwndToolbar
, NULL
, x
, y
, cx
, m_idealSize
.cy
, 0);
204 SetWindowPos(m_hwnd
, NULL
, x
, y
, cx
, cy
, 0);
205 DWORD btnSize
= SendMessage(m_hwndToolbar
, TB_GETBUTTONSIZE
, 0, 0);
206 SendMessage(m_hwndToolbar
, TB_SETBUTTONSIZE
, 0, MAKELPARAM(cx
, HIWORD(btnSize
)));
210 HRESULT
CMenuToolbarBase::GetWindow(HWND
*phwnd
)
220 LRESULT CALLBACK
CMenuToolbarBase::s_SubclassProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
222 CMenuToolbarBase
* pthis
= reinterpret_cast<CMenuToolbarBase
*>(GetWindowLongPtr(hWnd
, GWLP_USERDATA
));
223 return pthis
->SubclassProc(hWnd
, uMsg
, wParam
, lParam
);
226 LRESULT
CMenuToolbarBase::SubclassProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
231 if (wParam
== TIMERID_HOTTRACK
)
233 KillTimer(hWnd
, TIMERID_HOTTRACK
);
235 m_menuBand
->_OnPopupSubMenu(-1, NULL
, NULL
, NULL
);
237 if (HasSubMenu(m_hotItem
) == S_OK
)
239 PopupItem(m_hotItem
);
244 return m_SubclassOld(hWnd
, uMsg
, wParam
, lParam
);
247 HRESULT
CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM
* hot
)
249 if (hot
->dwFlags
& HICF_LEAVING
)
251 KillTimer(m_hwndToolbar
, TIMERID_HOTTRACK
);
253 m_menuBand
->_OnHotItemChanged(NULL
, -1);
254 m_menuBand
->_MenuItemHotTrack(MPOS_CHILDTRACKING
);
256 else if (m_hotItem
!= hot
->idNew
)
259 SystemParametersInfo(SPI_GETMENUSHOWDELAY
, 0, &elapsed
, 0);
260 SetTimer(m_hwndToolbar
, TIMERID_HOTTRACK
, elapsed
, NULL
);
262 m_hotItem
= hot
->idNew
;
263 m_menuBand
->_OnHotItemChanged(this, m_hotItem
);
264 m_menuBand
->_MenuItemHotTrack(MPOS_CHILDTRACKING
);
269 HRESULT
CMenuToolbarBase::PopupSubMenu(UINT itemId
, UINT index
, IShellMenu
* childShellMenu
)
271 IBandSite
* pBandSite
;
277 if (!SendMessage(m_hwndToolbar
, TB_GETITEMRECT
, index
, reinterpret_cast<LPARAM
>(&rc
)))
280 POINT a
= { rc
.left
, rc
.top
};
281 POINT b
= { rc
.right
, rc
.bottom
};
283 ClientToScreen(m_hwndToolbar
, &a
);
284 ClientToScreen(m_hwndToolbar
, &b
);
286 POINTL pt
= { b
.x
- 4, a
.y
};
287 RECTL rcl
= { a
.x
, a
.y
, b
.x
, b
.y
}; // maybe-TODO: fetch client area of deskbar?
290 #if USE_SYSTEM_MENUSITE
291 hr
= CoCreateInstance(CLSID_MenuBandSite
,
293 CLSCTX_INPROC_SERVER
,
294 IID_PPV_ARG(IBandSite
, &pBandSite
));
296 hr
= CMenuSite_Constructor(IID_PPV_ARG(IBandSite
, &pBandSite
));
301 hr
= CMenuSite_Wrapper(pBandSite
, IID_PPV_ARG(IBandSite
, &pBandSite
));
306 #if USE_SYSTEM_MENUDESKBAR
307 hr
= CoCreateInstance(CLSID_MenuDeskBar
,
309 CLSCTX_INPROC_SERVER
,
310 IID_PPV_ARG(IDeskBar
, &pDeskBar
));
312 hr
= CMenuDeskBar_Constructor(IID_PPV_ARG(IDeskBar
, &pDeskBar
));
317 hr
= CMenuDeskBar_Wrapper(pDeskBar
, IID_PPV_ARG(IDeskBar
, &pDeskBar
));
322 hr
= pDeskBar
->SetClient(pBandSite
);
326 hr
= pBandSite
->AddBand(childShellMenu
);
330 CComPtr
<IMenuPopup
> popup
;
331 hr
= pDeskBar
->QueryInterface(IID_PPV_ARG(IMenuPopup
, &popup
));
335 m_menuBand
->_OnPopupSubMenu(itemId
, popup
, &pt
, &rcl
);
340 HRESULT
CMenuToolbarBase::PopupSubMenu(UINT index
, HMENU menu
)
344 if (!SendMessage(m_hwndToolbar
, TB_GETITEMRECT
, index
, reinterpret_cast<LPARAM
>(&rc
)))
347 POINT b
= { rc
.right
, rc
.bottom
};
349 ClientToScreen(m_hwndToolbar
, &b
);
351 HMENU popup
= GetSubMenu(menu
, index
);
353 m_menuBand
->_TrackSubMenuUsingTrackPopupMenu(popup
, b
.x
, b
.y
);
358 HRESULT
CMenuToolbarBase::DoContextMenu(IContextMenu
* contextMenu
)
361 HMENU hPopup
= CreatePopupMenu();
366 hr
= contextMenu
->QueryContextMenu(hPopup
, 0, 0, UINT_MAX
, CMF_NORMAL
);
373 DWORD dwPos
= GetMessagePos();
374 UINT uCommand
= ::TrackPopupMenu(hPopup
, TPM_RETURNCMD
, GET_X_LPARAM(dwPos
), GET_Y_LPARAM(dwPos
), 0, m_hwnd
, NULL
);
378 CMINVOKECOMMANDINFO cmi
= { 0 };
379 cmi
.cbSize
= sizeof(cmi
);
380 cmi
.lpVerb
= MAKEINTRESOURCEA(uCommand
);
382 hr
= contextMenu
->InvokeCommand(&cmi
);
388 HRESULT
CMenuToolbarBase::OnCommand(WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
391 if (HasSubMenu(wParam
) == S_OK
)
393 KillTimer(m_hwndToolbar
, TIMERID_HOTTRACK
);
397 return m_menuBand
->_MenuItemHotTrack(MPOS_EXECUTE
);
400 HRESULT
CMenuToolbarBase::ChangeHotItem(DWORD dwSelectType
)
402 int prev
= m_hotItem
;
405 if (dwSelectType
!= 0xFFFFFFFF)
407 int count
= SendMessage(m_hwndToolbar
, TB_BUTTONCOUNT
, 0, 0);
411 TBBUTTONINFO info
= { 0 };
412 info
.cbSize
= sizeof(TBBUTTONINFO
);
414 index
= SendMessage(m_hwndToolbar
, TB_GETBUTTONINFO
, m_hotItem
, reinterpret_cast<LPARAM
>(&info
));
417 if (dwSelectType
== VK_HOME
)
420 dwSelectType
= VK_DOWN
;
422 else if (dwSelectType
== VK_END
)
425 dwSelectType
= VK_UP
;
429 if (dwSelectType
== VK_UP
)
433 else if (dwSelectType
== VK_DOWN
)
440 if (dwSelectType
== VK_UP
)
444 else if (dwSelectType
== VK_DOWN
)
450 TBBUTTON btn
= { 0 };
451 while (index
>= 0 && index
< count
)
453 DWORD res
= SendMessage(m_hwndToolbar
, TB_GETBUTTON
, index
, reinterpret_cast<LPARAM
>(&btn
));
459 m_hotItem
= btn
.idCommand
;
460 if (prev
!= m_hotItem
)
462 SendMessage(m_hwndToolbar
, TB_SETHOTITEM
, index
, 0);
463 return m_menuBand
->_OnHotItemChanged(this, m_hotItem
);
468 if (dwSelectType
== VK_UP
)
472 else if (dwSelectType
== VK_DOWN
)
480 if (prev
!= m_hotItem
)
482 SendMessage(m_hwndToolbar
, TB_SETHOTITEM
, -1, 0);
483 m_menuBand
->_OnHotItemChanged(NULL
, -1);
489 AllocAndGetMenuString(HMENU hMenu
, UINT ItemIDByPosition
, WCHAR
** String
)
493 Length
= GetMenuStringW(hMenu
, ItemIDByPosition
, NULL
, 0, MF_BYPOSITION
);
498 /* Also allocate space for the terminating NULL character */
500 *String
= (PWSTR
) HeapAlloc(GetProcessHeap(), 0, Length
* sizeof(WCHAR
));
502 GetMenuStringW(hMenu
, ItemIDByPosition
, *String
, Length
, MF_BYPOSITION
);
507 CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand
*menuBand
) :
508 CMenuToolbarBase(menuBand
, FALSE
),
513 HRESULT
CMenuStaticToolbar::GetMenu(
520 *pdwFlags
= m_dwMenuFlags
;
525 HRESULT
CMenuStaticToolbar::SetMenu(
531 m_dwMenuFlags
= dwFlags
;
536 HRESULT
CMenuStaticToolbar::FillToolbar()
539 int ic
= GetMenuItemCount(m_hmenu
);
541 for (i
= 0; i
< ic
; i
++)
544 TBBUTTON tbb
= { 0 };
545 PWSTR MenuString
= NULL
;
547 tbb
.fsState
= TBSTATE_ENABLED
;
550 info
.cbSize
= sizeof(info
);
551 info
.fMask
= MIIM_FTYPE
| MIIM_ID
;
553 GetMenuItemInfoW(m_hmenu
, i
, TRUE
, &info
);
555 if (info
.fType
== MFT_STRING
)
557 if (!AllocAndGetMenuString(m_hmenu
, i
, &MenuString
))
558 return E_OUTOFMEMORY
;
559 if (::GetSubMenu(m_hmenu
, i
) != NULL
)
560 tbb
.fsStyle
|= BTNS_DROPDOWN
;
561 tbb
.iString
= (INT_PTR
) MenuString
;
562 tbb
.idCommand
= info
.wID
;
564 SMINFO
* sminfo
= new SMINFO();
565 sminfo
->dwMask
= SMIM_ICON
| SMIM_FLAGS
;
566 if (SUCCEEDED(m_menuBand
->_CallCBWithItemId(info
.wID
, SMC_GETINFO
, 0, reinterpret_cast<LPARAM
>(sminfo
))))
568 tbb
.iBitmap
= sminfo
->iIcon
;
569 tbb
.dwData
= reinterpret_cast<DWORD_PTR
>(sminfo
);
570 // FIXME: remove before deleting the toolbar or it will leak
575 tbb
.fsStyle
|= BTNS_SEP
;
578 SendMessageW(m_hwndToolbar
, TB_ADDBUTTONS
, 1, reinterpret_cast<LPARAM
>(&tbb
));
581 HeapFree(GetProcessHeap(), 0, MenuString
);
587 HRESULT
CMenuStaticToolbar::OnContextMenu(NMMOUSE
* rclick
)
589 CComPtr
<IContextMenu
> contextMenu
;
590 HRESULT hr
= m_menuBand
->_CallCBWithItemId(rclick
->dwItemSpec
, SMC_GETOBJECT
, reinterpret_cast<WPARAM
>(&IID_IContextMenu
), reinterpret_cast<LPARAM
>(&contextMenu
));
594 return DoContextMenu(contextMenu
);
597 HRESULT
CMenuStaticToolbar::OnCommand(WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
600 hr
= CMenuToolbarBase::OnCommand(wParam
, lParam
, theResult
);
604 // in case the clicked item has a submenu, we do not need to execute the item
608 return m_menuBand
->_CallCBWithItemId(wParam
, SMC_EXEC
, 0, 0);
611 HRESULT
CMenuStaticToolbar::PopupItem(UINT uItem
)
613 TBBUTTONINFO info
= { 0 };
614 info
.cbSize
= sizeof(TBBUTTONINFO
);
616 int index
= SendMessage(m_hwndToolbar
, TB_GETBUTTONINFO
, uItem
, reinterpret_cast<LPARAM
>(&info
));
620 TBBUTTON btn
= { 0 };
621 SendMessage(m_hwndToolbar
, TB_GETBUTTON
, index
, reinterpret_cast<LPARAM
>(&btn
));
623 SMINFO
* nfo
= reinterpret_cast<SMINFO
*>(btn
.dwData
);
627 if (nfo
->dwFlags
&SMIF_TRACKPOPUP
)
629 return PopupSubMenu(index
, m_hmenu
);
633 CComPtr
<IShellMenu
> shellMenu
;
634 HRESULT hr
= m_menuBand
->_CallCBWithItemId(uItem
, SMC_GETOBJECT
, reinterpret_cast<WPARAM
>(&IID_IShellMenu
), reinterpret_cast<LPARAM
>(&shellMenu
));
638 return PopupSubMenu(uItem
, index
, shellMenu
);
642 HRESULT
CMenuStaticToolbar::HasSubMenu(UINT uItem
)
644 TBBUTTONINFO info
= { 0 };
645 info
.cbSize
= sizeof(TBBUTTONINFO
);
647 int index
= SendMessage(m_hwndToolbar
, TB_GETBUTTONINFO
, uItem
, reinterpret_cast<LPARAM
>(&info
));
650 return ::GetSubMenu(m_hmenu
, index
) ? S_OK
: S_FALSE
;
653 CMenuSFToolbar::CMenuSFToolbar(CMenuBand
* menuBand
) :
654 CMenuToolbarBase(menuBand
, TRUE
),
659 CMenuSFToolbar::~CMenuSFToolbar()
663 HRESULT
CMenuSFToolbar::FillToolbar()
670 m_shellFolder
->EnumObjects(m_hwndToolbar
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &eidl
);
672 LPITEMIDLIST item
= static_cast<LPITEMIDLIST
>(CoTaskMemAlloc(sizeof(ITEMIDLIST
)));
674 while ((hr
= eidl
->Next(1, &item
, &fetched
)) == S_OK
)
679 TBBUTTON tbb
= { 0 };
680 tbb
.fsState
= TBSTATE_ENABLED
;
683 CComPtr
<IShellItem
> psi
;
684 hr
= SHCreateShellItem(NULL
, m_shellFolder
, item
, &psi
);
688 hr
= psi
->GetDisplayName(SIGDN_NORMALDISPLAY
, &MenuString
);
692 index
= SHMapPIDLToSystemImageListIndex(m_shellFolder
, item
, &indexOpen
);
695 hr
= psi
->GetAttributes(SFGAO_FOLDER
, &attrs
);
699 tbb
.fsStyle
|= BTNS_DROPDOWN
;
703 tbb
.iString
= (INT_PTR
) MenuString
;
705 tbb
.dwData
= reinterpret_cast<DWORD_PTR
>(ILClone(item
));
706 // FIXME: remove before deleting the toolbar or it will leak
708 SendMessageW(m_hwndToolbar
, TB_ADDBUTTONS
, 1, reinterpret_cast<LPARAM
>(&tbb
));
709 HeapFree(GetProcessHeap(), 0, MenuString
);
714 // If no items were added, show the "empty" placeholder
717 TBBUTTON tbb
= { 0 };
718 PCWSTR MenuString
= L
"(Empty)";
720 tbb
.fsState
= 0/*TBSTATE_DISABLED*/;
722 tbb
.iString
= (INT_PTR
) MenuString
;
725 SendMessageW(m_hwndToolbar
, TB_ADDBUTTONS
, 1, reinterpret_cast<LPARAM
>(&tbb
));
733 HRESULT
CMenuSFToolbar::SetShellFolder(IShellFolder
*psf
, LPCITEMIDLIST pidlFolder
, HKEY hKey
, DWORD dwFlags
)
736 m_idList
= pidlFolder
;
738 m_dwMenuFlags
= dwFlags
;
742 HRESULT
CMenuSFToolbar::GetShellFolder(DWORD
*pdwFlags
, LPITEMIDLIST
*ppidl
, REFIID riid
, void **ppv
)
746 hr
= m_shellFolder
->QueryInterface(riid
, ppv
);
751 *pdwFlags
= m_dwMenuFlags
;
755 LPITEMIDLIST pidl
= NULL
;
759 pidl
= ILClone(m_idList
);
762 (*(IUnknown
**) ppv
)->Release();
773 LPITEMIDLIST
CMenuSFToolbar::GetPidlFromId(UINT uItem
, INT
* pIndex
)
775 TBBUTTONINFO info
= { 0 };
776 info
.cbSize
= sizeof(TBBUTTONINFO
);
778 int index
= SendMessage(m_hwndToolbar
, TB_GETBUTTONINFO
, uItem
, reinterpret_cast<LPARAM
>(&info
));
785 TBBUTTON btn
= { 0 };
786 if (!SendMessage(m_hwndToolbar
, TB_GETBUTTON
, index
, reinterpret_cast<LPARAM
>(&btn
)))
789 return reinterpret_cast<LPITEMIDLIST
>(btn
.dwData
);
792 HRESULT
CMenuSFToolbar::OnContextMenu(NMMOUSE
* rclick
)
795 CComPtr
<IContextMenu
> contextMenu
;
796 LPCITEMIDLIST pidl
= reinterpret_cast<LPCITEMIDLIST
>(rclick
->dwItemData
);
798 hr
= m_shellFolder
->GetUIObjectOf(m_hwndToolbar
, 1, &pidl
, IID_IContextMenu
, NULL
, reinterpret_cast<VOID
**>(&contextMenu
));
802 return DoContextMenu(contextMenu
);
805 HRESULT
CMenuSFToolbar::OnCommand(WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
808 hr
= CMenuToolbarBase::OnCommand(wParam
, lParam
, theResult
);
812 // in case the clicked item has a submenu, we do not need to execute the item
816 return m_menuBand
->_CallCBWithItemPidl(GetPidlFromId(wParam
), SMC_SFEXEC
, 0, 0);
819 HRESULT
CMenuSFToolbar::PopupItem(UINT uItem
)
826 CComPtr
<IShellMenuCallback
> psmc
;
827 CComPtr
<IShellMenu
> shellMenu
;
829 LPITEMIDLIST pidl
= GetPidlFromId(uItem
, &index
);
834 #if USE_SYSTEM_MENUBAND
835 hr
= CoCreateInstance(CLSID_MenuBand
,
837 CLSCTX_INPROC_SERVER
,
838 IID_PPV_ARG(IShellMenu
, &shellMenu
));
840 hr
= CMenuBand_Constructor(IID_PPV_ARG(IShellMenu
, &shellMenu
));
845 hr
= CMenuBand_Wrapper(shellMenu
, IID_PPV_ARG(IShellMenu
, &shellMenu
));
850 m_menuBand
->GetMenuInfo(&psmc
, &uId
, &uIdAncestor
, &flags
);
852 // FIXME: not sure what to use as uId/uIdAncestor here
853 hr
= shellMenu
->Initialize(psmc
, 0, uId
, SMINIT_VERTICAL
);
857 CComPtr
<IShellFolder
> childFolder
;
858 hr
= m_shellFolder
->BindToObject(pidl
, NULL
, IID_PPV_ARG(IShellFolder
, &childFolder
));
862 hr
= shellMenu
->SetShellFolder(childFolder
, NULL
, NULL
, 0);
866 return PopupSubMenu(uItem
, index
, shellMenu
);
869 HRESULT
CMenuSFToolbar::HasSubMenu(UINT uItem
)
872 CComPtr
<IShellItem
> psi
;
873 hr
= SHCreateShellItem(NULL
, m_shellFolder
, GetPidlFromId(uItem
), &psi
);
878 hr
= psi
->GetAttributes(SFGAO_FOLDER
, &attrs
);
882 return (attrs
!= 0) ? S_OK
: S_FALSE
;