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
);
68 if (m_menuBand
->UseBigIcons())
71 SendMessageW(m_hwndToolbar
, TB_SETPADDING
, 0, MAKELPARAM(0, 0));
79 HRESULT hr
= SHGetImageList(shiml
, IID_PPV_ARG(IImageList
, &piml
));
82 SendMessageW(m_hwndToolbar
, TB_SETIMAGELIST
, 0, reinterpret_cast<LPARAM
>(piml
));
86 SendMessageW(m_hwndToolbar
, TB_SETIMAGELIST
, 0, 0);
92 HRESULT
CMenuToolbarBase::Close()
94 DestroyWindow(m_hwndToolbar
);
95 if (m_hwndToolbar
!= m_hwnd
)
96 DestroyWindow(m_hwnd
);
102 HRESULT
CMenuToolbarBase::CreateToolbar(HWND hwndParent
, DWORD dwFlags
)
104 LONG tbStyles
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
105 TBSTYLE_TOOLTIPS
| TBSTYLE_TRANSPARENT
| TBSTYLE_REGISTERDROP
| TBSTYLE_LIST
| TBSTYLE_FLAT
| TBSTYLE_CUSTOMERASE
|
106 CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NORESIZE
| CCS_TOP
;
107 LONG tbExStyles
= TBSTYLE_EX_DOUBLEBUFFER
;
109 if (dwFlags
& SMINIT_VERTICAL
)
111 tbStyles
|= CCS_VERT
;
112 tbExStyles
|= TBSTYLE_EX_VERTICAL
| WS_EX_TOOLWINDOW
;
117 if (!::GetClientRect(hwndParent
, &rc
) || (rc
.left
== rc
.right
) || (rc
.top
== rc
.bottom
))
125 HWND hwndToolbar
= CreateWindowEx(
126 tbExStyles
, TOOLBARCLASSNAMEW
, NULL
,
127 tbStyles
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
128 hwndParent
, NULL
, _AtlBaseModule
.GetModuleInstance(), 0);
130 if (hwndToolbar
== NULL
)
135 LONG pgStyles
= PGS_VERT
| WS_CHILD
| WS_VISIBLE
;
138 HWND hwndPager
= CreateWindowEx(
139 pgExStyles
, WC_PAGESCROLLER
, NULL
,
140 pgStyles
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
,
141 hwndParent
, NULL
, _AtlBaseModule
.GetModuleInstance(), 0);
143 ::SetParent(hwndToolbar
, hwndPager
);
144 ::SetParent(hwndPager
, hwndParent
);
146 SendMessage(hwndPager
, PGM_SETCHILD
, 0, reinterpret_cast<LPARAM
>(hwndToolbar
));
147 m_hwndToolbar
= hwndToolbar
;
152 ::SetParent(hwndToolbar
, hwndParent
);
153 m_hwndToolbar
= hwndToolbar
;
154 m_hwnd
= hwndToolbar
;
157 /* Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure */
158 SendMessageW(hwndToolbar
, TB_BUTTONSTRUCTSIZE
, sizeof(TBBUTTON
), 0);
160 //if (dwFlags & SMINIT_TOPLEVEL)
162 // /* Hide the placeholders for the button images */
163 // SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0);
167 if (m_menuBand
->UseBigIcons())
170 SendMessageW(hwndToolbar
, TB_SETPADDING
, 0, MAKELPARAM(0, 0));
178 HRESULT hr
= SHGetImageList(shiml
, IID_PPV_ARG(IImageList
, &piml
));
181 SendMessageW(hwndToolbar
, TB_SETIMAGELIST
, 0, reinterpret_cast<LPARAM
>(piml
));
185 SendMessageW(hwndToolbar
, TB_SETIMAGELIST
, 0, 0);
188 SetWindowLongPtr(hwndToolbar
, GWLP_USERDATA
, reinterpret_cast<LONG_PTR
>(this));
189 m_SubclassOld
= (WNDPROC
) SetWindowLongPtr(hwndToolbar
, GWLP_WNDPROC
, reinterpret_cast<LONG_PTR
>(CMenuToolbarBase::s_SubclassProc
));
194 HRESULT
CMenuToolbarBase::GetIdealSize(SIZE
& size
)
196 size
.cx
= size
.cy
= 0;
198 if (m_hwndToolbar
&& !m_hasIdealSize
)
200 SendMessageW(m_hwndToolbar
, TB_AUTOSIZE
, 0, 0);
201 SendMessageW(m_hwndToolbar
, TB_GETMAXSIZE
, 0, reinterpret_cast<LPARAM
>(&m_idealSize
));
202 m_hasIdealSize
= TRUE
;
210 HRESULT
CMenuToolbarBase::SetPosSize(int x
, int y
, int cx
, int cy
)
212 if (m_hwnd
!= m_hwndToolbar
)
214 SetWindowPos(m_hwndToolbar
, NULL
, x
, y
, cx
, m_idealSize
.cy
, 0);
216 SetWindowPos(m_hwnd
, NULL
, x
, y
, cx
, cy
, 0);
217 DWORD btnSize
= SendMessage(m_hwndToolbar
, TB_GETBUTTONSIZE
, 0, 0);
218 SendMessage(m_hwndToolbar
, TB_SETBUTTONSIZE
, 0, MAKELPARAM(cx
, HIWORD(btnSize
)));
222 HRESULT
CMenuToolbarBase::GetWindow(HWND
*phwnd
)
232 LRESULT CALLBACK
CMenuToolbarBase::s_SubclassProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
234 CMenuToolbarBase
* pthis
= reinterpret_cast<CMenuToolbarBase
*>(GetWindowLongPtr(hWnd
, GWLP_USERDATA
));
235 return pthis
->SubclassProc(hWnd
, uMsg
, wParam
, lParam
);
238 LRESULT
CMenuToolbarBase::SubclassProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
243 if (wParam
== TIMERID_HOTTRACK
)
245 KillTimer(hWnd
, TIMERID_HOTTRACK
);
247 m_menuBand
->_OnPopupSubMenu(-1, NULL
, NULL
, NULL
);
249 if (HasSubMenu(m_hotItem
) == S_OK
)
251 PopupItem(m_hotItem
);
256 return m_SubclassOld(hWnd
, uMsg
, wParam
, lParam
);
259 HRESULT
CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM
* hot
)
261 if (hot
->dwFlags
& HICF_LEAVING
)
263 KillTimer(m_hwndToolbar
, TIMERID_HOTTRACK
);
265 m_menuBand
->_OnHotItemChanged(NULL
, -1);
266 m_menuBand
->_MenuItemHotTrack(MPOS_CHILDTRACKING
);
268 else if (m_hotItem
!= hot
->idNew
)
271 SystemParametersInfo(SPI_GETMENUSHOWDELAY
, 0, &elapsed
, 0);
272 SetTimer(m_hwndToolbar
, TIMERID_HOTTRACK
, elapsed
, NULL
);
274 m_hotItem
= hot
->idNew
;
275 m_menuBand
->_OnHotItemChanged(this, m_hotItem
);
276 m_menuBand
->_MenuItemHotTrack(MPOS_CHILDTRACKING
);
281 HRESULT
CMenuToolbarBase::PopupSubMenu(UINT itemId
, UINT index
, IShellMenu
* childShellMenu
)
283 IBandSite
* pBandSite
;
289 if (!SendMessage(m_hwndToolbar
, TB_GETITEMRECT
, index
, reinterpret_cast<LPARAM
>(&rc
)))
292 POINT a
= { rc
.left
, rc
.top
};
293 POINT b
= { rc
.right
, rc
.bottom
};
295 ClientToScreen(m_hwndToolbar
, &a
);
296 ClientToScreen(m_hwndToolbar
, &b
);
298 POINTL pt
= { b
.x
, a
.y
};
299 RECTL rcl
= { a
.x
, a
.y
, b
.x
, b
.y
}; // maybe-TODO: fetch client area of deskbar?
302 #if USE_SYSTEM_MENUSITE
303 hr
= CoCreateInstance(CLSID_MenuBandSite
,
305 CLSCTX_INPROC_SERVER
,
306 IID_PPV_ARG(IBandSite
, &pBandSite
));
308 hr
= CMenuSite_Constructor(IID_PPV_ARG(IBandSite
, &pBandSite
));
313 hr
= CMenuSite_Wrapper(pBandSite
, IID_PPV_ARG(IBandSite
, &pBandSite
));
318 #if USE_SYSTEM_MENUDESKBAR
319 hr
= CoCreateInstance(CLSID_MenuDeskBar
,
321 CLSCTX_INPROC_SERVER
,
322 IID_PPV_ARG(IDeskBar
, &pDeskBar
));
324 hr
= CMenuDeskBar_Constructor(IID_PPV_ARG(IDeskBar
, &pDeskBar
));
329 hr
= CMenuDeskBar_Wrapper(pDeskBar
, IID_PPV_ARG(IDeskBar
, &pDeskBar
));
334 hr
= pDeskBar
->SetClient(pBandSite
);
338 hr
= pBandSite
->AddBand(childShellMenu
);
342 CComPtr
<IMenuPopup
> popup
;
343 hr
= pDeskBar
->QueryInterface(IID_PPV_ARG(IMenuPopup
, &popup
));
347 m_menuBand
->_OnPopupSubMenu(itemId
, popup
, &pt
, &rcl
);
352 HRESULT
CMenuToolbarBase::PopupSubMenu(UINT index
, HMENU menu
)
356 if (!SendMessage(m_hwndToolbar
, TB_GETITEMRECT
, index
, reinterpret_cast<LPARAM
>(&rc
)))
359 POINT b
= { rc
.right
, rc
.bottom
};
361 ClientToScreen(m_hwndToolbar
, &b
);
363 HMENU popup
= GetSubMenu(menu
, index
);
365 m_menuBand
->_TrackSubMenuUsingTrackPopupMenu(popup
, b
.x
, b
.y
);
370 HRESULT
CMenuToolbarBase::DoContextMenu(IContextMenu
* contextMenu
)
373 HMENU hPopup
= CreatePopupMenu();
378 hr
= contextMenu
->QueryContextMenu(hPopup
, 0, 0, UINT_MAX
, CMF_NORMAL
);
385 DWORD dwPos
= GetMessagePos();
386 UINT uCommand
= ::TrackPopupMenu(hPopup
, TPM_RETURNCMD
, GET_X_LPARAM(dwPos
), GET_Y_LPARAM(dwPos
), 0, m_hwnd
, NULL
);
390 CMINVOKECOMMANDINFO cmi
= { 0 };
391 cmi
.cbSize
= sizeof(cmi
);
392 cmi
.lpVerb
= MAKEINTRESOURCEA(uCommand
);
394 hr
= contextMenu
->InvokeCommand(&cmi
);
400 HRESULT
CMenuToolbarBase::OnCommand(WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
403 if (HasSubMenu(wParam
) == S_OK
)
405 KillTimer(m_hwndToolbar
, TIMERID_HOTTRACK
);
409 return m_menuBand
->_MenuItemHotTrack(MPOS_EXECUTE
);
412 HRESULT
CMenuToolbarBase::ChangeHotItem(DWORD dwSelectType
)
414 int prev
= m_hotItem
;
417 if (dwSelectType
!= 0xFFFFFFFF)
419 int count
= SendMessage(m_hwndToolbar
, TB_BUTTONCOUNT
, 0, 0);
423 TBBUTTONINFO info
= { 0 };
424 info
.cbSize
= sizeof(TBBUTTONINFO
);
426 index
= SendMessage(m_hwndToolbar
, TB_GETBUTTONINFO
, m_hotItem
, reinterpret_cast<LPARAM
>(&info
));
429 if (dwSelectType
== VK_HOME
)
432 dwSelectType
= VK_DOWN
;
434 else if (dwSelectType
== VK_END
)
437 dwSelectType
= VK_UP
;
441 if (dwSelectType
== VK_UP
)
445 else if (dwSelectType
== VK_DOWN
)
452 if (dwSelectType
== VK_UP
)
456 else if (dwSelectType
== VK_DOWN
)
462 TBBUTTON btn
= { 0 };
463 while (index
>= 0 && index
< count
)
465 DWORD res
= SendMessage(m_hwndToolbar
, TB_GETBUTTON
, index
, reinterpret_cast<LPARAM
>(&btn
));
471 m_hotItem
= btn
.idCommand
;
472 if (prev
!= m_hotItem
)
474 SendMessage(m_hwndToolbar
, TB_SETHOTITEM
, index
, 0);
475 return m_menuBand
->_OnHotItemChanged(this, m_hotItem
);
480 if (dwSelectType
== VK_UP
)
484 else if (dwSelectType
== VK_DOWN
)
492 if (prev
!= m_hotItem
)
494 SendMessage(m_hwndToolbar
, TB_SETHOTITEM
, -1, 0);
495 m_menuBand
->_OnHotItemChanged(NULL
, -1);
501 AllocAndGetMenuString(HMENU hMenu
, UINT ItemIDByPosition
, WCHAR
** String
)
505 Length
= GetMenuStringW(hMenu
, ItemIDByPosition
, NULL
, 0, MF_BYPOSITION
);
510 /* Also allocate space for the terminating NULL character */
512 *String
= (PWSTR
) HeapAlloc(GetProcessHeap(), 0, Length
* sizeof(WCHAR
));
514 GetMenuStringW(hMenu
, ItemIDByPosition
, *String
, Length
, MF_BYPOSITION
);
519 CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand
*menuBand
) :
520 CMenuToolbarBase(menuBand
, FALSE
),
525 HRESULT
CMenuStaticToolbar::GetMenu(
532 *pdwFlags
= m_dwMenuFlags
;
537 HRESULT
CMenuStaticToolbar::SetMenu(
543 m_dwMenuFlags
= dwFlags
;
548 HRESULT
CMenuStaticToolbar::FillToolbar()
551 int ic
= GetMenuItemCount(m_hmenu
);
553 for (i
= 0; i
< ic
; i
++)
556 TBBUTTON tbb
= { 0 };
557 PWSTR MenuString
= NULL
;
559 tbb
.fsState
= TBSTATE_ENABLED
;
562 info
.cbSize
= sizeof(info
);
563 info
.fMask
= MIIM_FTYPE
| MIIM_ID
;
565 GetMenuItemInfoW(m_hmenu
, i
, TRUE
, &info
);
567 if (info
.fType
== MFT_STRING
)
569 if (!AllocAndGetMenuString(m_hmenu
, i
, &MenuString
))
570 return E_OUTOFMEMORY
;
571 if (::GetSubMenu(m_hmenu
, i
) != NULL
)
572 tbb
.fsStyle
|= BTNS_DROPDOWN
;
573 tbb
.iString
= (INT_PTR
) MenuString
;
574 tbb
.idCommand
= info
.wID
;
576 SMINFO
* sminfo
= new SMINFO();
577 sminfo
->dwMask
= SMIM_ICON
| SMIM_FLAGS
;
578 if (SUCCEEDED(m_menuBand
->_CallCBWithItemId(info
.wID
, SMC_GETINFO
, 0, reinterpret_cast<LPARAM
>(sminfo
))))
580 tbb
.iBitmap
= sminfo
->iIcon
;
581 tbb
.dwData
= reinterpret_cast<DWORD_PTR
>(sminfo
);
582 // FIXME: remove before deleting the toolbar or it will leak
587 tbb
.fsStyle
|= BTNS_SEP
;
590 SendMessageW(m_hwndToolbar
, TB_ADDBUTTONS
, 1, reinterpret_cast<LPARAM
>(&tbb
));
593 HeapFree(GetProcessHeap(), 0, MenuString
);
599 HRESULT
CMenuStaticToolbar::OnContextMenu(NMMOUSE
* rclick
)
601 CComPtr
<IContextMenu
> contextMenu
;
602 HRESULT hr
= m_menuBand
->_CallCBWithItemId(rclick
->dwItemSpec
, SMC_GETOBJECT
, reinterpret_cast<WPARAM
>(&IID_IContextMenu
), reinterpret_cast<LPARAM
>(&contextMenu
));
606 return DoContextMenu(contextMenu
);
609 HRESULT
CMenuStaticToolbar::OnCommand(WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
612 hr
= CMenuToolbarBase::OnCommand(wParam
, lParam
, theResult
);
616 // in case the clicked item has a submenu, we do not need to execute the item
620 return m_menuBand
->_CallCBWithItemId(wParam
, SMC_EXEC
, 0, 0);
623 HRESULT
CMenuStaticToolbar::PopupItem(UINT uItem
)
625 TBBUTTONINFO info
= { 0 };
626 info
.cbSize
= sizeof(TBBUTTONINFO
);
628 int index
= SendMessage(m_hwndToolbar
, TB_GETBUTTONINFO
, uItem
, reinterpret_cast<LPARAM
>(&info
));
632 TBBUTTON btn
= { 0 };
633 SendMessage(m_hwndToolbar
, TB_GETBUTTON
, index
, reinterpret_cast<LPARAM
>(&btn
));
635 SMINFO
* nfo
= reinterpret_cast<SMINFO
*>(btn
.dwData
);
639 if (nfo
->dwFlags
&SMIF_TRACKPOPUP
)
641 return PopupSubMenu(index
, m_hmenu
);
645 CComPtr
<IShellMenu
> shellMenu
;
646 HRESULT hr
= m_menuBand
->_CallCBWithItemId(uItem
, SMC_GETOBJECT
, reinterpret_cast<WPARAM
>(&IID_IShellMenu
), reinterpret_cast<LPARAM
>(&shellMenu
));
650 return PopupSubMenu(uItem
, index
, shellMenu
);
654 HRESULT
CMenuStaticToolbar::HasSubMenu(UINT uItem
)
656 TBBUTTONINFO info
= { 0 };
657 info
.cbSize
= sizeof(TBBUTTONINFO
);
659 int index
= SendMessage(m_hwndToolbar
, TB_GETBUTTONINFO
, uItem
, reinterpret_cast<LPARAM
>(&info
));
662 return ::GetSubMenu(m_hmenu
, index
) ? S_OK
: S_FALSE
;
665 CMenuSFToolbar::CMenuSFToolbar(CMenuBand
* menuBand
) :
666 CMenuToolbarBase(menuBand
, TRUE
),
671 CMenuSFToolbar::~CMenuSFToolbar()
675 HRESULT
CMenuSFToolbar::FillToolbar()
682 m_shellFolder
->EnumObjects(m_hwndToolbar
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &eidl
);
684 LPITEMIDLIST item
= static_cast<LPITEMIDLIST
>(CoTaskMemAlloc(sizeof(ITEMIDLIST
)));
686 while ((hr
= eidl
->Next(1, &item
, &fetched
)) == S_OK
)
691 TBBUTTON tbb
= { 0 };
692 tbb
.fsState
= TBSTATE_ENABLED
;
695 CComPtr
<IShellItem
> psi
;
696 hr
= SHCreateShellItem(NULL
, m_shellFolder
, item
, &psi
);
700 hr
= psi
->GetDisplayName(SIGDN_NORMALDISPLAY
, &MenuString
);
704 index
= SHMapPIDLToSystemImageListIndex(m_shellFolder
, item
, &indexOpen
);
707 hr
= psi
->GetAttributes(SFGAO_FOLDER
, &attrs
);
711 tbb
.fsStyle
|= BTNS_DROPDOWN
;
715 tbb
.iString
= (INT_PTR
) MenuString
;
717 tbb
.dwData
= reinterpret_cast<DWORD_PTR
>(ILClone(item
));
718 // FIXME: remove before deleting the toolbar or it will leak
720 SendMessageW(m_hwndToolbar
, TB_ADDBUTTONS
, 1, reinterpret_cast<LPARAM
>(&tbb
));
721 HeapFree(GetProcessHeap(), 0, MenuString
);
726 // If no items were added, show the "empty" placeholder
729 TBBUTTON tbb
= { 0 };
730 PCWSTR MenuString
= L
"(Empty)";
732 tbb
.fsState
= 0/*TBSTATE_DISABLED*/;
734 tbb
.iString
= (INT_PTR
) MenuString
;
737 SendMessageW(m_hwndToolbar
, TB_ADDBUTTONS
, 1, reinterpret_cast<LPARAM
>(&tbb
));
745 HRESULT
CMenuSFToolbar::SetShellFolder(IShellFolder
*psf
, LPCITEMIDLIST pidlFolder
, HKEY hKey
, DWORD dwFlags
)
748 m_idList
= pidlFolder
;
750 m_dwMenuFlags
= dwFlags
;
754 HRESULT
CMenuSFToolbar::GetShellFolder(DWORD
*pdwFlags
, LPITEMIDLIST
*ppidl
, REFIID riid
, void **ppv
)
758 hr
= m_shellFolder
->QueryInterface(riid
, ppv
);
763 *pdwFlags
= m_dwMenuFlags
;
767 LPITEMIDLIST pidl
= NULL
;
771 pidl
= ILClone(m_idList
);
774 (*(IUnknown
**) ppv
)->Release();
785 LPITEMIDLIST
CMenuSFToolbar::GetPidlFromId(UINT uItem
, INT
* pIndex
)
787 TBBUTTONINFO info
= { 0 };
788 info
.cbSize
= sizeof(TBBUTTONINFO
);
790 int index
= SendMessage(m_hwndToolbar
, TB_GETBUTTONINFO
, uItem
, reinterpret_cast<LPARAM
>(&info
));
797 TBBUTTON btn
= { 0 };
798 if (!SendMessage(m_hwndToolbar
, TB_GETBUTTON
, index
, reinterpret_cast<LPARAM
>(&btn
)))
801 return reinterpret_cast<LPITEMIDLIST
>(btn
.dwData
);
804 HRESULT
CMenuSFToolbar::OnContextMenu(NMMOUSE
* rclick
)
807 CComPtr
<IContextMenu
> contextMenu
;
808 LPCITEMIDLIST pidl
= reinterpret_cast<LPCITEMIDLIST
>(rclick
->dwItemData
);
810 hr
= m_shellFolder
->GetUIObjectOf(m_hwndToolbar
, 1, &pidl
, IID_IContextMenu
, NULL
, reinterpret_cast<VOID
**>(&contextMenu
));
814 return DoContextMenu(contextMenu
);
817 HRESULT
CMenuSFToolbar::OnCommand(WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
820 hr
= CMenuToolbarBase::OnCommand(wParam
, lParam
, theResult
);
824 // in case the clicked item has a submenu, we do not need to execute the item
828 return m_menuBand
->_CallCBWithItemPidl(GetPidlFromId(wParam
), SMC_SFEXEC
, 0, 0);
831 HRESULT
CMenuSFToolbar::PopupItem(UINT uItem
)
838 CComPtr
<IShellMenuCallback
> psmc
;
839 CComPtr
<IShellMenu
> shellMenu
;
841 LPITEMIDLIST pidl
= GetPidlFromId(uItem
, &index
);
846 #if USE_SYSTEM_MENUBAND
847 hr
= CoCreateInstance(CLSID_MenuBand
,
849 CLSCTX_INPROC_SERVER
,
850 IID_PPV_ARG(IShellMenu
, &shellMenu
));
852 hr
= CMenuBand_Constructor(IID_PPV_ARG(IShellMenu
, &shellMenu
));
857 hr
= CMenuBand_Wrapper(shellMenu
, IID_PPV_ARG(IShellMenu
, &shellMenu
));
862 m_menuBand
->GetMenuInfo(&psmc
, &uId
, &uIdAncestor
, &flags
);
864 // FIXME: not sure what to use as uId/uIdAncestor here
865 hr
= shellMenu
->Initialize(psmc
, 0, uId
, SMINIT_VERTICAL
);
869 CComPtr
<IShellFolder
> childFolder
;
870 hr
= m_shellFolder
->BindToObject(pidl
, NULL
, IID_PPV_ARG(IShellFolder
, &childFolder
));
874 hr
= shellMenu
->SetShellFolder(childFolder
, NULL
, NULL
, 0);
878 return PopupSubMenu(uItem
, index
, shellMenu
);
881 HRESULT
CMenuSFToolbar::HasSubMenu(UINT uItem
)
884 CComPtr
<IShellItem
> psi
;
885 hr
= SHCreateShellItem(NULL
, m_shellFolder
, GetPidlFromId(uItem
), &psi
);
890 hr
= psi
->GetAttributes(SFGAO_FOLDER
, &attrs
);
894 return (attrs
!= 0) ? S_OK
: S_FALSE
;