791377db2850a64d3896cfd40f8bb2237bfd7205
[reactos.git] / base / shell / rshell / CMenuSite.cpp
1 /*
2 * Shell Menu Site
3 *
4 * Copyright 2014 David Quintana
5 *
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.
10 *
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.
15 *
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
19 */
20 #include "precomp.h"
21 #include <atlwin.h>
22 #include <shlwapi_undoc.h>
23
24 #include "CMenuSite.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(menusite);
27
28 extern "C"
29 HRESULT WINAPI CMenuSite_Constructor(REFIID riid, LPVOID *ppv)
30 {
31 HRESULT hr;
32 #if USE_SYSTEM_MENUSITE
33 hr = CoCreateInstance(CLSID_MenuBandSite,
34 NULL,
35 CLSCTX_INPROC_SERVER,
36 riid, ppv);
37 #else
38 *ppv = NULL;
39
40 CMenuSite * site = new CComObject<CMenuSite>();
41
42 if (!site)
43 return E_OUTOFMEMORY;
44
45 hr = site->QueryInterface(riid, ppv);
46
47 if (FAILED_UNEXPECTEDLY(hr))
48 site->Release();
49 #endif
50
51 return hr;
52 }
53
54 CMenuSite::CMenuSite() :
55 m_DeskBarSite(NULL),
56 m_BandObject(NULL),
57 m_DeskBand(NULL),
58 m_WinEventHandler(NULL),
59 m_hWndBand(NULL)
60 {
61 }
62
63 HRESULT STDMETHODCALLTYPE CMenuSite::ContextSensitiveHelp(BOOL fEnterMode)
64 {
65 return E_NOTIMPL;
66 }
67
68 HRESULT STDMETHODCALLTYPE CMenuSite::GetBandSiteInfo(BANDSITEINFO *pbsinfo)
69 {
70 return E_NOTIMPL;
71 }
72
73 HRESULT STDMETHODCALLTYPE CMenuSite::RemoveBand(DWORD dwBandID)
74 {
75 return E_NOTIMPL;
76 }
77
78 HRESULT STDMETHODCALLTYPE CMenuSite::SetBandSiteInfo(const BANDSITEINFO *pbsinfo)
79 {
80 return E_NOTIMPL;
81 }
82
83 HRESULT STDMETHODCALLTYPE CMenuSite::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState)
84 {
85 return E_NOTIMPL;
86 }
87
88 HRESULT STDMETHODCALLTYPE CMenuSite::SetModeDBC(DWORD dwMode)
89 {
90 return E_NOTIMPL;
91 }
92
93 HRESULT STDMETHODCALLTYPE CMenuSite::TranslateAcceleratorIO(LPMSG lpMsg)
94 {
95 return S_FALSE;
96 }
97
98 HRESULT STDMETHODCALLTYPE CMenuSite::HasFocusIO()
99 {
100 return S_FALSE;
101 }
102
103 HRESULT STDMETHODCALLTYPE CMenuSite::OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus)
104 {
105 return S_OK;
106 }
107
108 HRESULT STDMETHODCALLTYPE CMenuSite::AddBand(IUnknown * punk)
109 {
110 HRESULT hr;
111
112 #define TO_HRESULT(x) ((HRESULT)(S_OK+(x)))
113
114 CComPtr<IUnknown> pUnknown;
115
116 punk->QueryInterface(IID_PPV_ARG(IUnknown, &pUnknown));
117
118 if (pUnknown == m_BandObject)
119 return TO_HRESULT(0);
120
121 if (m_BandObject)
122 {
123 hr = IUnknown_SetSite(m_BandObject, NULL);
124 if (FAILED_UNEXPECTEDLY(hr))
125 return hr;
126 }
127
128 m_BandObject = NULL;
129 m_DeskBand = NULL;
130 m_WinEventHandler = NULL;
131 m_hWndBand = NULL;
132
133 if (!pUnknown)
134 return TO_HRESULT(0);
135
136 hr = pUnknown->QueryInterface(IID_PPV_ARG(IDeskBand, &m_DeskBand));
137 if (FAILED_UNEXPECTEDLY(hr))
138 return hr;
139
140 hr = pUnknown->QueryInterface(IID_PPV_ARG(IWinEventHandler, &m_WinEventHandler));
141 if (FAILED_UNEXPECTEDLY(hr))
142 return hr;
143
144 hr = IUnknown_SetSite(pUnknown, this->ToIUnknown());
145 if (FAILED_UNEXPECTEDLY(hr))
146 return hr;
147
148 hr = IUnknown_GetWindow(pUnknown, &m_hWndBand);
149 if (FAILED_UNEXPECTEDLY(hr))
150 return hr;
151
152 m_BandObject = pUnknown;
153
154 return TO_HRESULT(0);
155 }
156
157 HRESULT STDMETHODCALLTYPE CMenuSite::EnumBands(UINT uBand, DWORD* pdwBandID)
158 {
159 if (uBand != 0)
160 return E_FAIL;
161
162 *pdwBandID = 0;
163
164 return S_OK;
165 }
166
167 HRESULT STDMETHODCALLTYPE CMenuSite::Exec(const GUID * pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
168 {
169 return IUnknown_Exec(m_DeskBarSite, *pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
170 }
171
172 HRESULT STDMETHODCALLTYPE CMenuSite::GetBandObject(DWORD dwBandID, REFIID riid, VOID **ppv)
173 {
174 if (dwBandID != 0 || m_BandObject == NULL)
175 {
176 *ppv = NULL;
177 return E_NOINTERFACE;
178 }
179
180 return m_BandObject->QueryInterface(riid, ppv);
181 }
182
183 HRESULT STDMETHODCALLTYPE CMenuSite::GetSize(DWORD dwWhich, LPRECT prc)
184 {
185 memset(prc, 0, sizeof(*prc));
186
187 if (dwWhich != 0)
188 return S_OK;
189
190 if (m_DeskBand == NULL)
191 return S_OK;
192
193 DESKBANDINFO info = { 0 };
194 info.dwMask = DBIM_MAXSIZE;
195
196 m_DeskBand->GetBandInfo(0, 0, &info);
197
198 prc->right = info.ptMaxSize.x;
199 prc->bottom = info.ptMaxSize.y;
200
201 return S_OK;
202 }
203
204 HRESULT STDMETHODCALLTYPE CMenuSite::GetWindow(HWND *phwnd)
205 {
206 if (!IsWindow())
207 return E_FAIL;
208
209 *phwnd = m_hWnd;
210
211 return S_OK;
212 }
213
214 HRESULT STDMETHODCALLTYPE CMenuSite::IsWindowOwner(HWND hWnd)
215 {
216 if (hWnd == m_hWnd)
217 return S_OK;
218
219 if (!m_WinEventHandler)
220 return S_FALSE;
221
222 return m_WinEventHandler->IsWindowOwner(hWnd);
223 }
224
225 HRESULT STDMETHODCALLTYPE CMenuSite::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
226 {
227 if (!m_WinEventHandler)
228 return S_OK;
229
230 return m_WinEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
231 }
232
233 HRESULT STDMETHODCALLTYPE CMenuSite::QueryBand(DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState, LPWSTR pszName, int cchName)
234 {
235 if (dwBandID != 0)
236 return E_FAIL;
237
238 if (!m_BandObject)
239 {
240 *ppstb = NULL;
241 return E_NOINTERFACE;
242 }
243
244 HRESULT hr = m_BandObject->QueryInterface(IID_PPV_ARG(IDeskBand, ppstb));
245
246 *pdwState = 1;
247
248 if (cchName > 0)
249 pszName[0] = 0;
250
251 return hr;
252 }
253
254 HRESULT STDMETHODCALLTYPE CMenuSite::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
255 {
256 *ppvObject = NULL;
257
258 if (IsEqualGUID(guidService, SID_SMenuBandBottom) ||
259 IsEqualGUID(guidService, SID_SMenuBandBottomSelected) ||
260 IsEqualGUID(guidService, SID_SMenuBandChild))
261 {
262 if (m_BandObject == NULL)
263 return E_NOINTERFACE;
264
265 return IUnknown_QueryService(m_BandObject, guidService, riid, ppvObject);
266 }
267
268 if (!m_DeskBarSite)
269 return E_NOINTERFACE;
270
271 return IUnknown_QueryService(m_DeskBarSite, guidService, riid, ppvObject);
272 }
273
274 HRESULT STDMETHODCALLTYPE CMenuSite::QueryStatus(const GUID * pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
275 {
276 if (!m_DeskBarSite)
277 return E_FAIL;
278
279 return IUnknown_QueryStatus(m_DeskBarSite, *pguidCmdGroup, cCmds, prgCmds, pCmdText);
280 }
281
282 HRESULT STDMETHODCALLTYPE CMenuSite::SetDeskBarSite(IUnknown *punkSite)
283 {
284 HRESULT hr;
285
286 CComPtr<IUnknown> protectThis(this->ToIUnknown());
287
288 if (punkSite)
289 {
290 HWND hWndSite;
291
292 m_DeskBarSite = NULL;
293
294 hr = IUnknown_GetWindow(punkSite, &hWndSite);
295
296 if (FAILED(hr) || !hWndSite)
297 return E_FAIL;
298
299 if (!m_hWnd)
300 {
301 Create(hWndSite, NULL, L"MenuSite");
302 }
303
304 m_DeskBarSite = punkSite;
305
306 return S_OK;
307 }
308
309 if (m_DeskBand)
310 {
311 m_DeskBand->CloseDW(0);
312 }
313
314 hr = IUnknown_SetSite(m_BandObject, NULL);
315
316 m_BandObject = NULL;
317 m_DeskBand = NULL;
318 m_WinEventHandler = NULL;
319 m_hWndBand = NULL;
320 m_hWnd = NULL;
321 m_DeskBarSite = NULL;
322
323 return S_OK;
324 }
325
326 HRESULT STDMETHODCALLTYPE CMenuSite::UIActivateDBC(DWORD dwState)
327 {
328 if (!m_DeskBand)
329 return S_OK;
330
331 return m_DeskBand->ShowDW(dwState != 0);
332 }
333
334 HRESULT STDMETHODCALLTYPE CMenuSite::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
335 {
336 if (lpMsg)
337 return E_FAIL;
338
339 return IUnknown_UIActivateIO(m_BandObject, fActivate, lpMsg);
340 }
341
342 BOOL CMenuSite::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD mapId)
343 {
344 HWND hWndTarget = NULL;
345 CComPtr<IUnknown> protectThis(this->ToIUnknown());
346
347 switch (uMsg)
348 {
349 case WM_SIZE:
350 if (m_BandObject)
351 {
352 CComPtr<IMenuPopup> pMenuPopup;
353 if (SUCCEEDED(m_BandObject->QueryInterface(IID_PPV_ARG(IMenuPopup, &pMenuPopup))))
354 {
355 RECT Rect = { 0 };
356 GetClientRect(&Rect);
357 Rect.right = Rect.right;
358 pMenuPopup->OnPosRectChangeDB(&Rect);
359 }
360 }
361 hWndTarget = hWnd;
362 lResult = 1;
363 break;
364 case WM_NOTIFY:
365 hWndTarget = reinterpret_cast<LPNMHDR>(lParam)->hwndFrom;
366 break;
367 case WM_COMMAND:
368 hWndTarget = (HWND) lParam;
369 break;
370 default:
371 return FALSE;
372 }
373
374 if (hWndTarget && m_WinEventHandler &&
375 m_WinEventHandler->IsWindowOwner(hWndTarget) == S_OK)
376 {
377 if (SUCCEEDED(m_WinEventHandler->OnWinEvent(hWndTarget, uMsg, wParam, lParam, &lResult)))
378 return TRUE;
379 }
380
381 return FALSE;
382 }