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