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
23 #include <shlwapi_undoc.h>
25 WINE_DEFAULT_DEBUG_CHANNEL(menusite
);
27 bool _assert(bool cond
, LPCSTR expr
, LPCSTR file
, DWORD line
, LPCSTR func
)
32 wine_dbg_printf("%s(%d): Assertion failed '%s', at %s", file
, line
, expr
, func
);
38 #define DBGASSERT(x) _assert(!!(x), #x, __FILE__, __LINE__, __FUNCSIG__)
41 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
42 public CWindowImpl
<CMenuSite
, CWindow
, CControlWinTraits
>,
44 public IDeskBarClient
,
45 public IOleCommandTarget
,
47 public IInputObjectSite
,
48 public IWinEventHandler
,
49 public IServiceProvider
51 IUnknown
* m_DeskBarSite
;
52 IUnknown
* m_BandObject
;
53 IDeskBand
* m_DeskBand
;
54 IWinEventHandler
* m_WinEventHandler
;
61 DECLARE_WND_CLASS_EX(_T("MenuSite"), 0, COLOR_WINDOW
)
63 DECLARE_NOT_AGGREGATABLE(CMenuSite
)
64 DECLARE_PROTECT_FINAL_CONSTRUCT()
65 BEGIN_COM_MAP(CMenuSite
)
66 COM_INTERFACE_ENTRY_IID(IID_IBandSite
, IBandSite
)
67 COM_INTERFACE_ENTRY_IID(IID_IDeskBarClient
, IDeskBarClient
)
68 COM_INTERFACE_ENTRY_IID(IID_IOleWindow
, IOleWindow
)
69 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget
, IOleCommandTarget
)
70 COM_INTERFACE_ENTRY_IID(IID_IInputObject
, IInputObject
)
71 COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite
, IInputObjectSite
)
72 COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler
, IWinEventHandler
)
73 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider
, IServiceProvider
)
77 virtual HRESULT STDMETHODCALLTYPE
AddBand(IUnknown
* punk
);
78 virtual HRESULT STDMETHODCALLTYPE
EnumBands(UINT uBand
, DWORD
* pdwBandID
);
79 virtual HRESULT STDMETHODCALLTYPE
QueryBand(DWORD dwBandID
, IDeskBand
**ppstb
, DWORD
*pdwState
, LPWSTR pszName
, int cchName
);
80 virtual HRESULT STDMETHODCALLTYPE
GetBandObject(DWORD dwBandID
, REFIID riid
, VOID
**ppv
);
83 virtual HRESULT STDMETHODCALLTYPE
SetDeskBarSite(IUnknown
*punkSite
);
84 virtual HRESULT STDMETHODCALLTYPE
GetSize(DWORD dwWhich
, LPRECT prc
);
85 virtual HRESULT STDMETHODCALLTYPE
UIActivateDBC(DWORD dwState
);
88 virtual HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*phwnd
);
91 virtual HRESULT STDMETHODCALLTYPE
QueryStatus(const GUID
* pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
);
92 virtual HRESULT STDMETHODCALLTYPE
Exec(const GUID
* pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
);
95 virtual HRESULT STDMETHODCALLTYPE
UIActivateIO(BOOL fActivate
, LPMSG lpMsg
);
96 virtual HRESULT STDMETHODCALLTYPE
HasFocusIO();
97 virtual HRESULT STDMETHODCALLTYPE
TranslateAcceleratorIO(LPMSG lpMsg
);
100 virtual HRESULT STDMETHODCALLTYPE
OnFocusChangeIS(IUnknown
*punkObj
, BOOL fSetFocus
);
103 virtual HRESULT STDMETHODCALLTYPE
IsWindowOwner(HWND hWnd
);
104 virtual HRESULT STDMETHODCALLTYPE
OnWinEvent(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
);
107 virtual HRESULT STDMETHODCALLTYPE
QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
);
110 // Using custom message map instead
111 virtual BOOL
ProcessWindowMessage(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&lResult
, DWORD mapId
= 0);
114 virtual HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
);
115 virtual HRESULT STDMETHODCALLTYPE
GetBandSiteInfo(BANDSITEINFO
*pbsinfo
);
116 virtual HRESULT STDMETHODCALLTYPE
RemoveBand(DWORD dwBandID
);
117 virtual HRESULT STDMETHODCALLTYPE
SetBandSiteInfo(const BANDSITEINFO
*pbsinfo
);
118 virtual HRESULT STDMETHODCALLTYPE
SetBandState(DWORD dwBandID
, DWORD dwMask
, DWORD dwState
);
119 virtual HRESULT STDMETHODCALLTYPE
SetModeDBC(DWORD dwMode
);
122 BOOL
CreateSiteWindow(HWND hWndParent
);
126 HRESULT
CMenuSite_Constructor(REFIID riid
, LPVOID
*ppv
)
130 CMenuSite
* site
= new CComObject
<CMenuSite
>();
133 return E_OUTOFMEMORY
;
135 HRESULT hr
= site
->QueryInterface(riid
, ppv
);
143 CMenuSite::CMenuSite() :
147 m_WinEventHandler(NULL
),
152 HRESULT STDMETHODCALLTYPE
CMenuSite::ContextSensitiveHelp(BOOL fEnterMode
)
157 HRESULT STDMETHODCALLTYPE
CMenuSite::GetBandSiteInfo(BANDSITEINFO
*pbsinfo
)
162 HRESULT STDMETHODCALLTYPE
CMenuSite::RemoveBand(DWORD dwBandID
)
167 HRESULT STDMETHODCALLTYPE
CMenuSite::SetBandSiteInfo(const BANDSITEINFO
*pbsinfo
)
172 HRESULT STDMETHODCALLTYPE
CMenuSite::SetBandState(DWORD dwBandID
, DWORD dwMask
, DWORD dwState
)
177 HRESULT STDMETHODCALLTYPE
CMenuSite::SetModeDBC(DWORD dwMode
)
182 HRESULT STDMETHODCALLTYPE
CMenuSite::TranslateAcceleratorIO(LPMSG lpMsg
)
187 HRESULT STDMETHODCALLTYPE
CMenuSite::HasFocusIO()
192 HRESULT STDMETHODCALLTYPE
CMenuSite::OnFocusChangeIS(IUnknown
*punkObj
, BOOL fSetFocus
)
197 HRESULT STDMETHODCALLTYPE
CMenuSite::AddBand(IUnknown
* punk
)
199 if (SHIsSameObject(punk
, m_BandObject
))
202 IUnknown_SetSite(m_BandObject
, NULL
);
206 m_BandObject
->Release();
212 m_DeskBand
->Release();
216 if (m_WinEventHandler
)
218 m_WinEventHandler
->Release();
219 m_WinEventHandler
= NULL
;
222 BOOL result
= m_hWndBand
!= NULL
;
227 return result
? S_OK
+ 0 : E_FAIL
;
229 DBGASSERT(SUCCEEDED(punk
->QueryInterface(IID_PPV_ARG(IDeskBand
, &m_DeskBand
))));
230 DBGASSERT(SUCCEEDED(punk
->QueryInterface(IID_PPV_ARG(IWinEventHandler
, &m_WinEventHandler
))));
232 IUnknown_SetSite(punk
, (IDeskBarClient
*)this);
233 IUnknown_GetWindow(punk
, &m_hWndBand
);
242 HRESULT STDMETHODCALLTYPE
CMenuSite::EnumBands(UINT uBand
, DWORD
* pdwBandID
)
252 HRESULT STDMETHODCALLTYPE
CMenuSite::Exec(const GUID
* pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
254 return IUnknown_Exec(m_DeskBarSite
, *pguidCmdGroup
, nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
257 HRESULT STDMETHODCALLTYPE
CMenuSite::GetBandObject(DWORD dwBandID
, REFIID riid
, VOID
**ppv
)
259 if (!DBGASSERT(dwBandID
== 0) || m_BandObject
== NULL
)
262 return E_NOINTERFACE
;
265 return m_BandObject
->QueryInterface(riid
, ppv
);
268 HRESULT STDMETHODCALLTYPE
CMenuSite::GetSize(DWORD dwWhich
, LPRECT prc
)
270 memset(prc
, 0, sizeof(*prc
));
275 if (m_DeskBand
== NULL
)
278 DESKBANDINFO info
= { 0 };
279 info
.dwMask
= DBIM_MAXSIZE
;
281 m_DeskBand
->GetBandInfo(0, 0, &info
);
283 prc
->right
= info
.ptMaxSize
.x
;
284 prc
->bottom
= info
.ptMaxSize
.y
;
289 HRESULT STDMETHODCALLTYPE
CMenuSite::GetWindow(HWND
*phwnd
)
291 DBGASSERT(IsWindow());
298 HRESULT STDMETHODCALLTYPE
CMenuSite::IsWindowOwner(HWND hWnd
)
303 if (!m_WinEventHandler
)
306 return m_WinEventHandler
->IsWindowOwner(hWnd
);
309 HRESULT STDMETHODCALLTYPE
CMenuSite::OnWinEvent(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*theResult
)
311 if (!m_WinEventHandler
)
314 return m_WinEventHandler
->OnWinEvent(hWnd
, uMsg
, wParam
, lParam
, theResult
);
317 HRESULT STDMETHODCALLTYPE
CMenuSite::QueryBand(DWORD dwBandID
, IDeskBand
**ppstb
, DWORD
*pdwState
, LPWSTR pszName
, int cchName
)
319 DBGASSERT(dwBandID
== 0);
320 DBGASSERT(!IsBadWritePtr(ppstb
, sizeof(*ppstb
)));
325 return E_NOINTERFACE
;
328 HRESULT hr
= m_BandObject
->QueryInterface(IID_PPV_ARG(IDeskBand
, ppstb
));
338 HRESULT STDMETHODCALLTYPE
CMenuSite::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
342 if (IsEqualGUID(guidService
, SID_SMenuBandBottom
) ||
343 IsEqualGUID(guidService
, SID_SMenuBandBottomSelected
) ||
344 IsEqualGUID(guidService
, SID_SMenuBandChild
))
346 if (m_BandObject
== NULL
)
349 return IUnknown_QueryService(m_BandObject
, guidService
, riid
, ppvObject
);
352 DBGASSERT(m_DeskBarSite
);
354 return IUnknown_QueryService(m_DeskBarSite
, guidService
, riid
, ppvObject
);
357 HRESULT STDMETHODCALLTYPE
CMenuSite::QueryStatus(const GUID
* pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
)
359 if (!DBGASSERT(m_DeskBarSite
))
361 return IUnknown_QueryStatus(m_DeskBarSite
, *pguidCmdGroup
, cCmds
, prgCmds
, pCmdText
);
364 HRESULT STDMETHODCALLTYPE
CMenuSite::SetDeskBarSite(IUnknown
*punkSite
)
368 ((IDeskBarClient
*)this)->AddRef();
374 m_DeskBarSite
->Release();
375 m_DeskBarSite
= NULL
;
378 IUnknown_GetWindow(punkSite
, &hWndSite
);
382 CreateSiteWindow(hWndSite
);
384 m_DeskBarSite
= punkSite
;
393 m_DeskBand
->CloseDW(0);
396 IUnknown_SetSite(m_BandObject
, NULL
);
400 m_BandObject
->Release();
406 m_DeskBand
->Release();
410 if (m_WinEventHandler
)
412 m_WinEventHandler
->Release();
413 m_WinEventHandler
= NULL
;
425 m_DeskBarSite
->Release();
427 m_DeskBarSite
= NULL
;
430 ((IDeskBarClient
*)this)->Release();
438 HRESULT STDMETHODCALLTYPE
CMenuSite::UIActivateDBC(DWORD dwState
)
440 if (!DBGASSERT(m_DeskBand
))
443 return m_DeskBand
->ShowDW(dwState
!= 0);
446 HRESULT STDMETHODCALLTYPE
CMenuSite::UIActivateIO(BOOL fActivate
, LPMSG lpMsg
)
448 if (lpMsg
&& DBGASSERT(IsBadWritePtr(lpMsg
, sizeof(*lpMsg
))))
451 return IUnknown_UIActivateIO(m_BandObject
, fActivate
, lpMsg
);
454 BOOL
CMenuSite::CreateSiteWindow(HWND hWndParent
)
458 return DBGASSERT(IsWindow());
461 Create(hWndParent
, NULL
, L
"MenuSite");
463 return m_hWnd
!= NULL
;
466 BOOL
CMenuSite::ProcessWindowMessage(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
, LRESULT
&lResult
, DWORD mapId
)
469 IMenuPopup
* pMenuPopup
;
471 ((IDeskBarClient
*)this)->AddRef();
478 if (SUCCEEDED(m_BandObject
->QueryInterface(IID_PPV_ARG(IMenuPopup
, &pMenuPopup
))))
481 GetClientRect(&Rect
);
482 pMenuPopup
->OnPosRectChangeDB(&Rect
);
483 pMenuPopup
->Release();
490 hWndToCall
= *(HWND
*) lParam
;
493 hWndToCall
= (HWND
) lParam
;
496 ((IDeskBarClient
*)this)->Release();
502 if (m_WinEventHandler
)
504 if (m_WinEventHandler
->IsWindowOwner(hWndToCall
) == S_OK
)
506 HRESULT hr
= m_WinEventHandler
->OnWinEvent(hWndToCall
, uMsg
, wParam
, lParam
, &lResult
);
507 ((IDeskBarClient
*)this)->Release();
513 ((IDeskBarClient
*)this)->Release();