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