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 <shlwapi_undoc.h>
24 WINE_DEFAULT_DEBUG_CHANNEL(CMenuDeskBar
);
26 const static GUID CGID_MenuDeskBar
= { 0x5C9F0A12, 0x959E, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x08, 0x26, 0x36 } };
29 WS_POPUP
| WS_DLGFRAME
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
,
30 WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
| WS_EX_PALETTEWINDOW
34 public CWindowImpl
<CMenuDeskBar
, CWindow
, CMenuWinTraits
>,
35 public CComCoClass
<CMenuDeskBar
>,
36 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
37 public IOleCommandTarget
,
38 public IServiceProvider
,
39 public IInputObjectSite
,
42 public IObjectWithSite
,
44 public IInitializeObject
51 CComPtr
<IUnknown
> m_Site
;
52 CComPtr
<IUnknown
> m_Client
;
53 CComPtr
<IMenuPopup
> m_SubMenuParent
;
61 // *** IMenuPopup methods ***
62 virtual HRESULT STDMETHODCALLTYPE
Popup(POINTL
*ppt
, RECTL
*prcExclude
, MP_POPUPFLAGS dwFlags
);
63 virtual HRESULT STDMETHODCALLTYPE
OnSelect(DWORD dwSelectType
);
64 virtual HRESULT STDMETHODCALLTYPE
SetSubMenu(IMenuPopup
*pmp
, BOOL fSet
);
66 // *** IOleWindow methods ***
67 virtual HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*phwnd
);
68 virtual HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
);
70 // *** IObjectWithSite methods ***
71 virtual HRESULT STDMETHODCALLTYPE
SetSite(IUnknown
*pUnkSite
);
72 virtual HRESULT STDMETHODCALLTYPE
GetSite(REFIID riid
, PVOID
*ppvSite
);
74 // *** IBanneredBar methods ***
75 virtual HRESULT STDMETHODCALLTYPE
SetIconSize(DWORD iIcon
);
76 virtual HRESULT STDMETHODCALLTYPE
GetIconSize(DWORD
* piIcon
);
77 virtual HRESULT STDMETHODCALLTYPE
SetBitmap(HBITMAP hBitmap
);
78 virtual HRESULT STDMETHODCALLTYPE
GetBitmap(HBITMAP
* phBitmap
);
80 // *** IInitializeObject methods ***
81 virtual HRESULT STDMETHODCALLTYPE
Initialize(THIS
);
83 // *** IOleCommandTarget methods ***
84 virtual HRESULT STDMETHODCALLTYPE
QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
);
85 virtual HRESULT STDMETHODCALLTYPE
Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
);
87 // *** IServiceProvider methods ***
88 virtual HRESULT STDMETHODCALLTYPE
QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
);
90 // *** IInputObjectSite methods ***
91 virtual HRESULT STDMETHODCALLTYPE
OnFocusChangeIS(LPUNKNOWN lpUnknown
, BOOL bFocus
);
93 // *** IInputObject methods ***
94 virtual HRESULT STDMETHODCALLTYPE
UIActivateIO(BOOL bActivating
, LPMSG lpMsg
);
95 virtual HRESULT STDMETHODCALLTYPE
HasFocusIO(THIS
);
96 virtual HRESULT STDMETHODCALLTYPE
TranslateAcceleratorIO(LPMSG lpMsg
);
98 // *** IDeskBar methods ***
99 virtual HRESULT STDMETHODCALLTYPE
SetClient(IUnknown
*punkClient
);
100 virtual HRESULT STDMETHODCALLTYPE
GetClient(IUnknown
**ppunkClient
);
101 virtual HRESULT STDMETHODCALLTYPE
OnPosRectChangeDB(LPRECT prc
);
103 DECLARE_NOT_AGGREGATABLE(CMenuDeskBar
)
104 DECLARE_PROTECT_FINAL_CONSTRUCT()
106 DECLARE_WND_CLASS_EX(_T("BaseBar"), CS_SAVEBITS
| CS_DROPSHADOW
, COLOR_3DFACE
)
108 BEGIN_MSG_MAP(CMenuDeskBar
)
109 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
110 MESSAGE_HANDLER(WM_NOTIFY
, OnNotify
)
111 MESSAGE_HANDLER(WM_WINDOWPOSCHANGED
, OnWindowPosChanged
)
112 MESSAGE_HANDLER(WM_PAINT
, OnPaint
)
115 BEGIN_COM_MAP(CMenuDeskBar
)
116 COM_INTERFACE_ENTRY_IID(IID_IMenuPopup
, IMenuPopup
)
117 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget
, IOleCommandTarget
)
118 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider
, IServiceProvider
)
119 COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite
, IInputObjectSite
)
120 COM_INTERFACE_ENTRY_IID(IID_IInputObject
, IInputObject
)
121 COM_INTERFACE_ENTRY_IID(IID_IDeskBar
, IMenuPopup
)
122 COM_INTERFACE_ENTRY_IID(IID_IOleWindow
, IMenuPopup
)
123 COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite
, IObjectWithSite
)
124 COM_INTERFACE_ENTRY_IID(IID_IBanneredBar
, IBanneredBar
)
125 COM_INTERFACE_ENTRY_IID(IID_IInitializeObject
, IInitializeObject
)
131 LRESULT
OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
132 LRESULT
OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
133 LRESULT
OnWindowPosChanged(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
134 LRESULT
OnPaint(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
138 HRESULT
CMenuDeskBar_Constructor(REFIID riid
, LPVOID
*ppv
)
142 CMenuDeskBar
* deskbar
= new CComObject
<CMenuDeskBar
>();
145 return E_OUTOFMEMORY
;
147 HRESULT hr
= deskbar
->QueryInterface(riid
, ppv
);
155 CMenuDeskBar::CMenuDeskBar() :
161 CMenuDeskBar::~CMenuDeskBar()
165 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::GetWindow(HWND
*lphwnd
)
173 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::ContextSensitiveHelp(BOOL fEnterMode
)
178 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::OnFocusChangeIS(IUnknown
*punkObj
, BOOL fSetFocus
)
180 CComPtr
<IInputObjectSite
> ios
;
182 HRESULT hr
= m_Client
->QueryInterface(IID_PPV_ARG(IInputObjectSite
, &ios
));
186 return ios
->OnFocusChangeIS(punkObj
, fSetFocus
);
189 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
,
190 OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
195 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
,
196 DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
198 if (IsEqualIID(*pguidCmdGroup
, CGID_MenuDeskBar
))
204 case 3: // load complete
206 case 4: // set font metrics
210 if (IsEqualIID(*pguidCmdGroup
, CGID_Explorer
))
213 else if (IsEqualIID(*pguidCmdGroup
, IID_IDeskBarClient
))
229 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
234 if (IsEqualGUID(guidService
, SID_SMenuPopup
) ||
235 IsEqualGUID(guidService
, SID_SMenuBandParent
) ||
236 IsEqualGUID(guidService
, SID_STopLevelBrowser
))
238 return this->QueryInterface(riid
, ppvObject
);
241 return IUnknown_QueryService(m_Site
, guidService
, riid
, ppvObject
);
244 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::UIActivateIO(BOOL fActivate
, LPMSG lpMsg
)
246 return IUnknown_UIActivateIO(m_Client
, fActivate
, lpMsg
);
249 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::HasFocusIO()
251 CComPtr
<IInputObject
> io
;
253 HRESULT hr
= m_Client
->QueryInterface(IID_PPV_ARG(IInputObject
, &io
));
257 return io
->HasFocusIO();
260 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::TranslateAcceleratorIO(LPMSG lpMsg
)
262 CComPtr
<IInputObject
> io
;
264 HRESULT hr
= m_Client
->QueryInterface(IID_PPV_ARG(IInputObject
, &io
));
268 return io
->TranslateAcceleratorIO(lpMsg
);
271 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::SetClient(IUnknown
*punkClient
)
273 CComPtr
<IDeskBarClient
> pDeskBandClient
;
278 if (punkClient
== NULL
)
286 hr
= punkClient
->QueryInterface(IID_PPV_ARG(IUnknown
, &m_Client
));
290 hr
= m_Client
->QueryInterface(IID_PPV_ARG(IDeskBarClient
, &pDeskBandClient
));
294 hr
= pDeskBandClient
->SetDeskBarSite(static_cast<IDeskBar
*>(this));
298 return IUnknown_GetWindow(m_Client
, &m_ClientWindow
);
301 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::GetClient(IUnknown
**ppunkClient
)
303 if (ppunkClient
== NULL
)
309 return m_Client
->QueryInterface(IID_PPV_ARG(IUnknown
, ppunkClient
));
312 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::OnPosRectChangeDB(LPRECT prc
)
319 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::SetSite(IUnknown
*pUnkSite
)
326 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::GetSite(REFIID riid
, void **ppvSite
)
331 return m_Site
->QueryInterface(riid
, ppvSite
);
334 LRESULT
CMenuDeskBar::OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
344 if (m_Banner
!= NULL
)
347 ::GetObject(m_Banner
, sizeof(bm
), &bm
);
348 rc
.left
+= bm
.bmWidth
;
351 ::SetWindowPos(m_ClientWindow
, NULL
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, 0);
357 LRESULT
CMenuDeskBar::OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
359 CComPtr
<IWinEventHandler
> winEventHandler
;
364 if (m_Client
.p
!= NULL
)
366 hr
= m_Client
->QueryInterface(IID_PPV_ARG(IWinEventHandler
, &winEventHandler
));
367 if (SUCCEEDED(hr
) && winEventHandler
.p
!= NULL
)
368 hr
= winEventHandler
->OnWinEvent(NULL
, uMsg
, wParam
, lParam
, &result
);
373 LRESULT
CMenuDeskBar::OnWindowPosChanged(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
378 LRESULT
CMenuDeskBar::OnPaint(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
382 if (m_Banner
&& !m_IconSize
)
386 HDC hdc
= BeginPaint(&ps
);
388 HDC hdcMem
= ::CreateCompatibleDC(hdc
);
389 HGDIOBJ hbmOld
= ::SelectObject(hdcMem
, m_Banner
);
391 ::GetObject(m_Banner
, sizeof(bm
), &bm
);
394 if (!GetClientRect(&rc
))
395 WARN("GetClientRect failed\n");
397 const int bx
= bm
.bmWidth
;
398 const int by
= bm
.bmHeight
;
399 const int cy
= rc
.bottom
;
401 TRACE("Painting banner: %d by %d\n", bm
.bmWidth
, bm
.bmHeight
);
403 if (!::StretchBlt(hdc
, 0, 0, bx
, cy
- by
, hdcMem
, 0, 0, bx
, 1, SRCCOPY
))
404 WARN("StretchBlt failed\n");
406 if (!::BitBlt(hdc
, 0, cy
- by
, bx
, by
, hdcMem
, 0, 0, SRCCOPY
))
407 WARN("BitBlt failed\n");
409 ::SelectObject(hdcMem
, hbmOld
);
418 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::Popup(POINTL
*ppt
, RECTL
*prcExclude
, MP_POPUPFLAGS dwFlags
)
421 CComPtr
<IOleCommandTarget
> oct
;
422 CComPtr
<IInputObject
> io
;
423 CComPtr
<IDeskBand
> band
;
424 CComPtr
<IDeskBarClient
> dbc
;
429 hr
= IUnknown_QueryService(m_Client
, SID_SMenuBandChild
, IID_PPV_ARG(IOleCommandTarget
, &oct
));
433 hr
= m_Client
->QueryInterface(IID_PPV_ARG(IDeskBarClient
, &dbc
));
437 hr
= dbc
->SetModeDBC(1);
438 // Allow it to fail with E_NOTIMPL.
440 // No clue about the arg, using anything != 0
441 hr
= dbc
->UIActivateDBC(TRUE
);
446 hr
= dbc
->GetSize(0, &rc
);
452 const int CMD_EXEC_OPT
= 0;
454 hr
= IUnknown_QueryServiceExec(m_Client
, SID_SMenuBandChild
, &CLSID_MenuBand
, CMD
, CMD_EXEC_OPT
, NULL
, NULL
);
458 ::AdjustWindowRect(&rc
, ::GetWindowLong(m_hWnd
, GWL_STYLE
), FALSE
);
462 if (m_Banner
!= NULL
)
465 ::GetObject(m_Banner
, sizeof(bm
), &bm
);
466 rc
.right
+= bm
.bmWidth
;
470 int y
= ppt
->y
- rc
.bottom
;
479 // if (y+cy > work area height) cy = work area height - y
481 this->SetWindowPos(HWND_TOPMOST
, x
, y
, cx
, cy
, SWP_SHOWWINDOW
);
483 // HACK: The bar needs to be notified of the size AFTER it is shown.
484 // Quick & dirty way of getting it done.
486 OnSize(WM_SIZE
, 0, 0, bHandled
);
488 UIActivateIO(TRUE
, NULL
);
493 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::SetIconSize(THIS_ DWORD iIcon
)
498 // Unknown meaning (set flags? set icon size?)
500 const int CMD_EXEC_OPT
= iIcon
? 0 : 2; // seems to work
502 hr
= IUnknown_QueryServiceExec(m_Client
, SID_SMenuBandChild
, &CLSID_MenuBand
, CMD
, CMD_EXEC_OPT
, NULL
, NULL
);
507 OnSize(WM_SIZE
, 0, 0, bHandled
);
512 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::GetIconSize(THIS_ DWORD
* piIcon
)
515 *piIcon
= m_IconSize
;
519 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::SetBitmap(THIS_ HBITMAP hBitmap
)
524 OnSize(WM_SIZE
, 0, 0, bHandled
);
529 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::GetBitmap(THIS_ HBITMAP
* phBitmap
)
532 *phBitmap
= m_Banner
;
536 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::OnSelect(
539 CComPtr
<IDeskBarClient
> dbc
;
542 bool bubbleUp
= false;
545 switch (dwSelectType
)
547 case MPOS_FULLCANCEL
:
552 case MPOS_CANCELLEVEL
:
555 case MPOS_SELECTLEFT
:
556 case MPOS_SELECTRIGHT
:
557 // if unhandled, spread upwards?
560 case MPOS_CHILDTRACKING
:
566 hr
= m_Client
->QueryInterface(IID_PPV_ARG(IDeskBarClient
, &dbc
));
570 hr
= dbc
->UIActivateDBC(FALSE
);
574 SetWindowPos(m_hWnd
, 0, 0, 0, 0, SWP_HIDEWINDOW
| SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOZORDER
);
576 UIActivateIO(FALSE
, NULL
);
579 //if (bubbleUp && m_Site)
581 // CComPtr<IMenuPopup> pmp;
582 // HRESULT hr = IUnknown_QueryService(m_Site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &pmp));
585 // pmp->OnSelect(dwSelectType);
591 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::SetSubMenu(
597 m_SubMenuParent
= pmp
;
603 if (SHIsSameObject(pmp
, m_SubMenuParent
))
605 m_SubMenuParent
= NULL
;
613 HRESULT STDMETHODCALLTYPE
CMenuDeskBar::Initialize(THIS
)