1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Shell Menu Desk Bar
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2014 David Quintana
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c2c66affSColin Finck  * Lesser General Public License for more details.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck  */
20c2c66affSColin Finck #include "shellmenu.h"
21c2c66affSColin Finck #include <atlwin.h>
22c2c66affSColin Finck #include <shlwapi_undoc.h>
23c2c66affSColin Finck 
24c2c66affSColin Finck #include "CMenuDeskBar.h"
25c2c66affSColin Finck 
26c2c66affSColin Finck /* As far as I can tell, the submenu hierarchy looks like this:
27c2c66affSColin Finck *
28c2c66affSColin Finck * The DeskBar's Child is the Band it contains.
29c2c66affSColin Finck * The DeskBar's Parent is the SID_SMenuPopup of the Site.
30c2c66affSColin Finck *
31c2c66affSColin Finck * The Band's Child is the IMenuPopup of the child submenu.
32c2c66affSColin Finck * The Band's Parent is the SID_SMenuPopup of the Site (the DeskBar).
33c2c66affSColin Finck *
34c2c66affSColin Finck * When the DeskBar receives a selection event:
35c2c66affSColin Finck * If it requires closing the window, it will notify the Child (Band) using CancelLevel.
36c2c66affSColin Finck * If it has to spread upwards (everything but CancelLevel), it will notify the Parent.
37c2c66affSColin Finck *
38c2c66affSColin Finck * When the Band receives a selection event, this is where it gets fuzzy:
39c2c66affSColin Finck * In which cases does it call the Parent? Probably not CancelLevel.
40c2c66affSColin Finck * In which cases does it call the Child?
41c2c66affSColin Finck * How does it react to calls?
42c2c66affSColin Finck *
43c2c66affSColin Finck */
44c2c66affSColin Finck 
45c2c66affSColin Finck 
46c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(CMenuDeskBar);
47c2c66affSColin Finck 
CMenuDeskBar()48c2c66affSColin Finck CMenuDeskBar::CMenuDeskBar() :
49c2c66affSColin Finck     m_Client(NULL),
50c2c66affSColin Finck     m_ClientWindow(NULL),
51c2c66affSColin Finck     m_IconSize(0),
52c2c66affSColin Finck     m_Banner(NULL),
53c2c66affSColin Finck     m_Shown(FALSE),
54c2c66affSColin Finck     m_ShowFlags(0),
55c2c66affSColin Finck     m_didAddRef(FALSE)
56c2c66affSColin Finck {
57c2c66affSColin Finck }
58c2c66affSColin Finck 
~CMenuDeskBar()59c2c66affSColin Finck CMenuDeskBar::~CMenuDeskBar()
60c2c66affSColin Finck {
61c2c66affSColin Finck }
62c2c66affSColin Finck 
_OnCreate(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)63c2c66affSColin Finck LRESULT CMenuDeskBar::_OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
64c2c66affSColin Finck {
65c2c66affSColin Finck     if (!m_didAddRef)
66c2c66affSColin Finck     {
67c2c66affSColin Finck         this->AddRef();
68c2c66affSColin Finck         m_didAddRef = TRUE;
69c2c66affSColin Finck     }
70c2c66affSColin Finck 
71c2c66affSColin Finck     bHandled = FALSE;
72c2c66affSColin Finck     return 0;
73c2c66affSColin Finck }
74c2c66affSColin Finck 
OnFinalMessage(HWND)75c2c66affSColin Finck void CMenuDeskBar::OnFinalMessage(HWND /* hWnd */)
76c2c66affSColin Finck {
77c2c66affSColin Finck     if (m_didAddRef)
78c2c66affSColin Finck     {
79c2c66affSColin Finck         this->Release();
80c2c66affSColin Finck         m_didAddRef = FALSE;
81c2c66affSColin Finck     }
82c2c66affSColin Finck }
83c2c66affSColin Finck 
Initialize(THIS)84c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::Initialize(THIS)
85c2c66affSColin Finck {
86c2c66affSColin Finck     return S_OK;
87c2c66affSColin Finck }
88c2c66affSColin Finck 
GetWindow(HWND * lphwnd)89c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetWindow(HWND *lphwnd)
90c2c66affSColin Finck {
91c2c66affSColin Finck     if (lphwnd == NULL)
92c2c66affSColin Finck         return E_POINTER;
93c2c66affSColin Finck     *lphwnd = m_hWnd;
94c2c66affSColin Finck     return S_OK;
95c2c66affSColin Finck }
96c2c66affSColin Finck 
ContextSensitiveHelp(BOOL fEnterMode)97c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::ContextSensitiveHelp(BOOL fEnterMode)
98c2c66affSColin Finck {
99c2c66affSColin Finck     return E_NOTIMPL;
100c2c66affSColin Finck }
101c2c66affSColin Finck 
OnFocusChangeIS(IUnknown * punkObj,BOOL fSetFocus)102c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus)
103c2c66affSColin Finck {
104c2c66affSColin Finck     return IUnknown_OnFocusChangeIS(m_Client, punkObj, fSetFocus);
105c2c66affSColin Finck }
106c2c66affSColin Finck 
QueryStatus(const GUID * pguidCmdGroup,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT * pCmdText)107c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
108c2c66affSColin Finck     OLECMD prgCmds [], OLECMDTEXT *pCmdText)
109c2c66affSColin Finck {
110c2c66affSColin Finck     return E_NOTIMPL;
111c2c66affSColin Finck }
112c2c66affSColin Finck 
Exec(const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)113c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
114c2c66affSColin Finck     DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
115c2c66affSColin Finck {
116c2c66affSColin Finck     if (IsEqualIID(*pguidCmdGroup, CGID_MenuDeskBar))
117c2c66affSColin Finck     {
118c2c66affSColin Finck         switch (nCmdID)
119c2c66affSColin Finck         {
120c2c66affSColin Finck         case 2: // refresh
121c2c66affSColin Finck             return S_OK;
122c2c66affSColin Finck         case 3: // load complete
123c2c66affSColin Finck             return S_OK;
124c2c66affSColin Finck         case 4: // set font metrics
125c2c66affSColin Finck             return _AdjustForTheme(nCmdexecopt);
126c2c66affSColin Finck         }
127c2c66affSColin Finck     }
128c2c66affSColin Finck     if (IsEqualIID(*pguidCmdGroup, CGID_Explorer))
129c2c66affSColin Finck     {
130c2c66affSColin Finck     }
131c2c66affSColin Finck     else if (IsEqualIID(*pguidCmdGroup, IID_IDeskBarClient))
132c2c66affSColin Finck     {
133c2c66affSColin Finck         switch (nCmdID)
134c2c66affSColin Finck         {
135c2c66affSColin Finck         case 0:
136c2c66affSColin Finck             // hide current band
137c2c66affSColin Finck             break;
138c2c66affSColin Finck         case 2:
139c2c66affSColin Finck             break;
140c2c66affSColin Finck         case 3:
141c2c66affSColin Finck             break;
142c2c66affSColin Finck         }
143c2c66affSColin Finck     }
144c2c66affSColin Finck     return E_NOTIMPL;
145c2c66affSColin Finck }
146c2c66affSColin Finck 
QueryService(REFGUID guidService,REFIID riid,void ** ppvObject)147c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
148c2c66affSColin Finck {
149c2c66affSColin Finck     HRESULT hr;
150c2c66affSColin Finck 
151c2c66affSColin Finck     if (IsEqualGUID(guidService, SID_SMenuPopup) ||
152c2c66affSColin Finck         IsEqualGUID(guidService, SID_SMenuBandParent) ||
153c2c66affSColin Finck         IsEqualGUID(guidService, SID_STopLevelBrowser))
154c2c66affSColin Finck     {
155c2c66affSColin Finck         hr = this->QueryInterface(riid, ppvObject);
156c2c66affSColin Finck         if (SUCCEEDED(hr))
157c2c66affSColin Finck             return hr;
158c2c66affSColin Finck     }
159c2c66affSColin Finck 
160c2c66affSColin Finck     if (IsEqualGUID(guidService, SID_SMenuBandBottom) ||
161c2c66affSColin Finck         IsEqualGUID(guidService, SID_SMenuBandBottomSelected) ||
162c2c66affSColin Finck         IsEqualGUID(guidService, SID_SMenuBandChild))
163c2c66affSColin Finck     {
164c2c66affSColin Finck         if (m_Client == NULL)
165c2c66affSColin Finck             return E_NOINTERFACE;
166c2c66affSColin Finck 
167c2c66affSColin Finck         hr = IUnknown_QueryService(m_Client, guidService, riid, ppvObject);
168c2c66affSColin Finck         if (SUCCEEDED(hr))
169c2c66affSColin Finck             return hr;
170c2c66affSColin Finck     }
171c2c66affSColin Finck 
172c2c66affSColin Finck 
173c2c66affSColin Finck     if (m_Site == NULL)
174c2c66affSColin Finck         return E_NOINTERFACE;
175c2c66affSColin Finck 
176c2c66affSColin Finck     return IUnknown_QueryService(m_Site, guidService, riid, ppvObject);
177c2c66affSColin Finck }
178c2c66affSColin Finck 
UIActivateIO(BOOL fActivate,LPMSG lpMsg)179c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
180c2c66affSColin Finck {
181c2c66affSColin Finck     return IUnknown_UIActivateIO(m_Client, fActivate, lpMsg);
182c2c66affSColin Finck }
183c2c66affSColin Finck 
HasFocusIO()184c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::HasFocusIO()
185c2c66affSColin Finck {
186c2c66affSColin Finck     return IUnknown_HasFocusIO(m_Client);
187c2c66affSColin Finck }
188c2c66affSColin Finck 
TranslateAcceleratorIO(LPMSG lpMsg)189c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::TranslateAcceleratorIO(LPMSG lpMsg)
190c2c66affSColin Finck {
191c2c66affSColin Finck     return IUnknown_TranslateAcceleratorIO(m_Client, lpMsg);
192c2c66affSColin Finck }
193c2c66affSColin Finck 
SetClient(IUnknown * punkClient)194c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetClient(IUnknown *punkClient)
195c2c66affSColin Finck {
196c2c66affSColin Finck     CComPtr<IDeskBarClient> pDeskBandClient;
197c2c66affSColin Finck     HRESULT hr;
198c2c66affSColin Finck 
199c2c66affSColin Finck     if (m_Client)
200c2c66affSColin Finck     {
201c2c66affSColin Finck         hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDeskBandClient));
202c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hr))
203c2c66affSColin Finck             return hr;
204c2c66affSColin Finck 
205c2c66affSColin Finck         pDeskBandClient->SetDeskBarSite(NULL);
206c2c66affSColin Finck 
207c2c66affSColin Finck         pDeskBandClient = NULL;
208c2c66affSColin Finck         m_Client = NULL;
209c2c66affSColin Finck     }
210c2c66affSColin Finck 
211c2c66affSColin Finck     if (punkClient == NULL)
212c2c66affSColin Finck         return S_OK;
213c2c66affSColin Finck 
214c2c66affSColin Finck     if (m_hWnd == NULL)
215c2c66affSColin Finck     {
216c2c66affSColin Finck         Create(NULL);
217c2c66affSColin Finck     }
218c2c66affSColin Finck 
219c2c66affSColin Finck     hr = punkClient->QueryInterface(IID_PPV_ARG(IUnknown, &m_Client));
220c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
221c2c66affSColin Finck         return hr;
222c2c66affSColin Finck 
223c2c66affSColin Finck     hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDeskBandClient));
224c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
225c2c66affSColin Finck         return hr;
226c2c66affSColin Finck 
227c2c66affSColin Finck     hr = pDeskBandClient->SetDeskBarSite(static_cast<IDeskBar*>(this));
228c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
229c2c66affSColin Finck         return hr;
230c2c66affSColin Finck 
231c2c66affSColin Finck     return IUnknown_GetWindow(m_Client, &m_ClientWindow);
232c2c66affSColin Finck }
233c2c66affSColin Finck 
GetClient(IUnknown ** ppunkClient)234c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetClient(IUnknown **ppunkClient)
235c2c66affSColin Finck {
236c2c66affSColin Finck     if (ppunkClient == NULL)
237c2c66affSColin Finck         return E_POINTER;
238c2c66affSColin Finck 
239c2c66affSColin Finck     if (!m_Client)
240c2c66affSColin Finck         return E_FAIL;
241c2c66affSColin Finck 
242c2c66affSColin Finck     return m_Client->QueryInterface(IID_PPV_ARG(IUnknown, ppunkClient));
243c2c66affSColin Finck }
244c2c66affSColin Finck 
OnPosRectChangeDB(LPRECT prc)245c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnPosRectChangeDB(LPRECT prc)
246c2c66affSColin Finck {
247c2c66affSColin Finck     if (prc == NULL)
248c2c66affSColin Finck         return E_POINTER;
249c2c66affSColin Finck 
250c2c66affSColin Finck     return S_OK;
251c2c66affSColin Finck }
252c2c66affSColin Finck 
SetSite(IUnknown * pUnkSite)253c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSite(IUnknown *pUnkSite)
254c2c66affSColin Finck {
255c2c66affSColin Finck     // Windows closes the bar if this is called when the bar is shown
256c2c66affSColin Finck 
257c2c66affSColin Finck     if (m_Shown)
258c2c66affSColin Finck         _CloseBar();
259c2c66affSColin Finck 
260c2c66affSColin Finck     m_SubMenuParent = NULL;
261c2c66affSColin Finck 
262c2c66affSColin Finck     m_Site = pUnkSite;
263c2c66affSColin Finck 
264c2c66affSColin Finck     if (m_Site)
265c2c66affSColin Finck     {
266c2c66affSColin Finck         IUnknown_QueryService(m_Site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &m_SubMenuParent));
267c2c66affSColin Finck     }
268c2c66affSColin Finck     else
269c2c66affSColin Finck     {
270c2c66affSColin Finck         SetClient(NULL);
271c2c66affSColin Finck         DestroyWindow();
272c2c66affSColin Finck     }
273c2c66affSColin Finck 
274c2c66affSColin Finck     return S_OK;
275c2c66affSColin Finck }
276c2c66affSColin Finck 
GetSite(REFIID riid,void ** ppvSite)277c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetSite(REFIID riid, void **ppvSite)
278c2c66affSColin Finck {
279c2c66affSColin Finck     if (m_Site == NULL)
280c2c66affSColin Finck         return E_FAIL;
281c2c66affSColin Finck 
282c2c66affSColin Finck     return m_Site->QueryInterface(riid, ppvSite);
283c2c66affSColin Finck }
284c2c66affSColin Finck 
AdjustForExcludeArea(BOOL alignLeft,BOOL alignTop,BOOL preferVertical,PINT px,PINT py,INT cx,INT cy,RECTL rcExclude)285c2c66affSColin Finck static void AdjustForExcludeArea(BOOL alignLeft, BOOL alignTop, BOOL preferVertical, PINT px, PINT py, INT cx, INT cy, RECTL rcExclude) {
286c2c66affSColin Finck     RECT rcWindow = { *px, *py, *px + cx, *py + cy };
287c2c66affSColin Finck 
288c2c66affSColin Finck     if (rcWindow.right > rcExclude.left && rcWindow.left < rcExclude.right &&
289c2c66affSColin Finck         rcWindow.bottom > rcExclude.top && rcWindow.top < rcExclude.bottom)
290c2c66affSColin Finck     {
291c2c66affSColin Finck         if (preferVertical)
292c2c66affSColin Finck         {
293c2c66affSColin Finck             if (alignTop && rcWindow.bottom > rcExclude.top)
294c2c66affSColin Finck                 *py = rcExclude.top - cy;
295c2c66affSColin Finck             else if (!alignTop && rcWindow.top < rcExclude.bottom)
296c2c66affSColin Finck                 *py = rcExclude.bottom;
297c2c66affSColin Finck             else if (alignLeft && rcWindow.right > rcExclude.left)
298c2c66affSColin Finck                 *px = rcExclude.left - cx;
299c2c66affSColin Finck             else if (!alignLeft && rcWindow.left < rcExclude.right)
300c2c66affSColin Finck                 *px = rcExclude.right;
301c2c66affSColin Finck         }
302c2c66affSColin Finck         else
303c2c66affSColin Finck         {
304c2c66affSColin Finck             if (alignLeft && rcWindow.right > rcExclude.left)
305c2c66affSColin Finck                 *px = rcExclude.left - cx;
306c2c66affSColin Finck             else if (!alignLeft && rcWindow.left < rcExclude.right)
307c2c66affSColin Finck                 *px = rcExclude.right;
308c2c66affSColin Finck             else if (alignTop && rcWindow.bottom > rcExclude.top)
309c2c66affSColin Finck                 *py = rcExclude.top - cy;
310c2c66affSColin Finck             else if (!alignTop && rcWindow.top < rcExclude.bottom)
311c2c66affSColin Finck                 *py = rcExclude.bottom;
312c2c66affSColin Finck         }
313c2c66affSColin Finck     }
314c2c66affSColin Finck }
315c2c66affSColin Finck 
Popup(POINTL * ppt,RECTL * prcExclude,MP_POPUPFLAGS dwFlags)316c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
317c2c66affSColin Finck {
318c2c66affSColin Finck     HRESULT hr;
319c2c66affSColin Finck     CComPtr<IOleCommandTarget> oct;
320c2c66affSColin Finck     CComPtr<IInputObject> io;
321c2c66affSColin Finck     CComPtr<IDeskBand> band;
322c2c66affSColin Finck     CComPtr<IDeskBarClient> dbc;
323c2c66affSColin Finck 
324c2c66affSColin Finck     if (m_hWnd == NULL)
325c2c66affSColin Finck         return E_FAIL;
326c2c66affSColin Finck 
327c2c66affSColin Finck     hr = IUnknown_QueryService(m_Client, SID_SMenuBandChild, IID_PPV_ARG(IOleCommandTarget, &oct));
328c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
329c2c66affSColin Finck         return hr;
330c2c66affSColin Finck 
331c2c66affSColin Finck     hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &dbc));
332c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
333c2c66affSColin Finck         return hr;
334c2c66affSColin Finck 
335c2c66affSColin Finck     // Windows calls this, but it appears to be unimplemented?
336c2c66affSColin Finck     hr = dbc->SetModeDBC(1);
337c2c66affSColin Finck     // Allow it to fail with E_NOTIMPL.
338c2c66affSColin Finck 
339c2c66affSColin Finck     // No clue about the arg, using anything != 0
340c2c66affSColin Finck     hr = dbc->UIActivateDBC(TRUE);
341c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
342c2c66affSColin Finck         return hr;
343c2c66affSColin Finck 
344c2c66affSColin Finck     RECT rc = { 0 };
345c2c66affSColin Finck     hr = dbc->GetSize(0, &rc);
346c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
347c2c66affSColin Finck         return hr;
348c2c66affSColin Finck 
349c2c66affSColin Finck     // Unknown meaning
350c2c66affSColin Finck     const int CMD = 19;
351c2c66affSColin Finck     const int CMD_EXEC_OPT = 0;
352c2c66affSColin Finck 
353c2c66affSColin Finck     hr = IUnknown_QueryServiceExec(m_Client, SID_SMenuBandChild, &CLSID_MenuBand, CMD, CMD_EXEC_OPT, NULL, NULL);
354c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
355c2c66affSColin Finck         return hr;
356c2c66affSColin Finck 
357c2c66affSColin Finck     ::AdjustWindowRect(&rc, ::GetWindowLong(m_hWnd, GWL_STYLE), FALSE);
358c2c66affSColin Finck     ::OffsetRect(&rc, -rc.left, -rc.top);
359c2c66affSColin Finck 
360c2c66affSColin Finck     if (m_Banner != NULL)
361c2c66affSColin Finck     {
362c2c66affSColin Finck         BITMAP bm;
363c2c66affSColin Finck         ::GetObject(m_Banner, sizeof(bm), &bm);
364c2c66affSColin Finck         rc.right += bm.bmWidth;
365c2c66affSColin Finck     }
366c2c66affSColin Finck 
367c2c66affSColin Finck     RECT rcWorkArea;
368c2c66affSColin Finck     ::GetWindowRect(GetDesktopWindow(), &rcWorkArea);
369c2c66affSColin Finck     int cxWorkArea = rcWorkArea.right - rcWorkArea.left;
370c2c66affSColin Finck     int cyWorkArea = rcWorkArea.bottom - rcWorkArea.top;
371c2c66affSColin Finck 
372c2c66affSColin Finck     int x = ppt->x;
373c2c66affSColin Finck     int y = ppt->y;
374c2c66affSColin Finck     int cx = rc.right - rc.left;
375c2c66affSColin Finck     int cy = rc.bottom - rc.top;
376c2c66affSColin Finck 
377c2c66affSColin Finck     // TODO: Make alignLeft default to TRUE in LTR systems or whenever necessary.
378c2c66affSColin Finck     BOOL alignLeft = FALSE;
379c2c66affSColin Finck     BOOL alignTop = FALSE;
380c2c66affSColin Finck     BOOL preferVertical = FALSE;
381c2c66affSColin Finck     switch (dwFlags & MPPF_POS_MASK)
382c2c66affSColin Finck     {
383c2c66affSColin Finck     case MPPF_TOP:
384c2c66affSColin Finck         alignTop = TRUE;
385c2c66affSColin Finck         preferVertical = TRUE;
386c2c66affSColin Finck         break;
387c2c66affSColin Finck     case MPPF_LEFT:
388c2c66affSColin Finck         alignLeft = TRUE;
389c2c66affSColin Finck         break;
390c2c66affSColin Finck     case MPPF_BOTTOM:
391c2c66affSColin Finck         alignTop = FALSE;
392c2c66affSColin Finck         preferVertical = TRUE;
393c2c66affSColin Finck         break;
394c2c66affSColin Finck     case MPPF_RIGHT:
395c2c66affSColin Finck         alignLeft = FALSE;
396c2c66affSColin Finck         break;
397c2c66affSColin Finck     }
398c2c66affSColin Finck 
399c2c66affSColin Finck     // Try the selected alignment and verify that it doesn't escape the work area.
400c2c66affSColin Finck     if (alignLeft)
401c2c66affSColin Finck     {
402c2c66affSColin Finck         x = ppt->x - cx;
403c2c66affSColin Finck     }
404c2c66affSColin Finck     else
405c2c66affSColin Finck     {
406c2c66affSColin Finck         x = ppt->x;
407c2c66affSColin Finck     }
408c2c66affSColin Finck 
409c2c66affSColin Finck     if (alignTop)
410c2c66affSColin Finck     {
411c2c66affSColin Finck         y = ppt->y - cy;
412c2c66affSColin Finck     }
413c2c66affSColin Finck     else
414c2c66affSColin Finck     {
415c2c66affSColin Finck         y = ppt->y;
416c2c66affSColin Finck     }
417c2c66affSColin Finck 
418c2c66affSColin Finck     if (prcExclude)
419c2c66affSColin Finck         AdjustForExcludeArea(alignLeft, alignTop, preferVertical, &x, &y, cx, cy, *prcExclude);
420c2c66affSColin Finck 
421c2c66affSColin Finck     // Verify that it doesn't escape the work area, and flip.
422c2c66affSColin Finck     if (alignLeft)
423c2c66affSColin Finck     {
424c2c66affSColin Finck         if (x < rcWorkArea.left && (ppt->x+cx) <= rcWorkArea.right)
425c2c66affSColin Finck         {
426c2c66affSColin Finck             alignLeft = FALSE;
427c2c66affSColin Finck             if (prcExclude)
428c2c66affSColin Finck                 x = prcExclude->right - ((x + cx) - prcExclude->left);
429c2c66affSColin Finck             else
430c2c66affSColin Finck                 x = ppt->x;
431c2c66affSColin Finck         }
432c2c66affSColin Finck     }
433c2c66affSColin Finck     else
434c2c66affSColin Finck     {
435c2c66affSColin Finck         if ((ppt->x + cx) > rcWorkArea.right && x >= rcWorkArea.left)
436c2c66affSColin Finck         {
437c2c66affSColin Finck             alignLeft = TRUE;
438c2c66affSColin Finck             if (prcExclude)
439c2c66affSColin Finck                 x = prcExclude->left - cx + (prcExclude->right - x);
440c2c66affSColin Finck             else
441c2c66affSColin Finck                 x = ppt->x - cx;
442c2c66affSColin Finck         }
443c2c66affSColin Finck     }
444c2c66affSColin Finck 
445c2c66affSColin Finck     BOOL flipV = FALSE;
446c2c66affSColin Finck     if (alignTop)
447c2c66affSColin Finck     {
448c2c66affSColin Finck         if (y < rcWorkArea.top && (ppt->y + cy) <= rcWorkArea.bottom)
449c2c66affSColin Finck         {
450c2c66affSColin Finck             alignTop = FALSE;
451c2c66affSColin Finck             if (prcExclude)
452c2c66affSColin Finck                 y = prcExclude->bottom - ((y + cy) - prcExclude->top);
453c2c66affSColin Finck             else
454c2c66affSColin Finck                 y = ppt->y;
455c2c66affSColin Finck 
456c2c66affSColin Finck             flipV = true;
457c2c66affSColin Finck         }
458c2c66affSColin Finck     }
459c2c66affSColin Finck     else
460c2c66affSColin Finck     {
461c2c66affSColin Finck         if ((ppt->y + cy) > rcWorkArea.bottom && y >= rcWorkArea.top)
462c2c66affSColin Finck         {
463c2c66affSColin Finck             alignTop = TRUE;
464c2c66affSColin Finck             if (prcExclude)
465c2c66affSColin Finck                 y = prcExclude->top - cy + (prcExclude->bottom - y);
466c2c66affSColin Finck             else
467c2c66affSColin Finck                 y = ppt->y - cy;
468c2c66affSColin Finck 
469c2c66affSColin Finck             flipV = true;
470c2c66affSColin Finck         }
471c2c66affSColin Finck     }
472c2c66affSColin Finck 
473c2c66affSColin Finck     if (prcExclude)
474c2c66affSColin Finck         AdjustForExcludeArea(alignLeft, alignTop, preferVertical, &x, &y, cx, cy, *prcExclude);
475c2c66affSColin Finck 
476c2c66affSColin Finck     if (x < rcWorkArea.left)
477c2c66affSColin Finck         x = rcWorkArea.left;
478c2c66affSColin Finck 
479c2c66affSColin Finck     if (cx > cxWorkArea)
480c2c66affSColin Finck         cx = cxWorkArea;
481c2c66affSColin Finck 
482c2c66affSColin Finck     if (x + cx > rcWorkArea.right)
483c2c66affSColin Finck         x = rcWorkArea.right - cx;
484c2c66affSColin Finck 
485c2c66affSColin Finck     if (y < rcWorkArea.top)
486c2c66affSColin Finck         y = rcWorkArea.top;
487c2c66affSColin Finck 
488c2c66affSColin Finck     if (cy > cyWorkArea)
489c2c66affSColin Finck         cy = cyWorkArea;
490c2c66affSColin Finck 
491c2c66affSColin Finck     if (y + cy > rcWorkArea.bottom)
492c2c66affSColin Finck         y = rcWorkArea.bottom - cy;
493c2c66affSColin Finck 
494c2c66affSColin Finck     int flags = SWP_SHOWWINDOW | SWP_NOACTIVATE;
495c2c66affSColin Finck 
496c2c66affSColin Finck     this->SetWindowPos(HWND_TOPMOST, x, y, cx, cy, flags);
497c2c66affSColin Finck 
498c2c66affSColin Finck     if (flipV)
499c2c66affSColin Finck     {
500c2c66affSColin Finck         if (dwFlags & MPPF_INITIALSELECT)
501c2c66affSColin Finck             dwFlags = (dwFlags ^ MPPF_INITIALSELECT) | MPPF_FINALSELECT;
502c2c66affSColin Finck         else if (dwFlags & MPPF_FINALSELECT)
503c2c66affSColin Finck             dwFlags = (dwFlags ^ MPPF_FINALSELECT) | MPPF_INITIALSELECT;
504c2c66affSColin Finck     }
505c2c66affSColin Finck 
506c2c66affSColin Finck     m_ShowFlags = dwFlags;
507c2c66affSColin Finck     m_Shown = true;
508c2c66affSColin Finck 
509c2c66affSColin Finck     // HACK: The bar needs to be notified of the size AFTER it is shown.
510c2c66affSColin Finck     // Quick & dirty way of getting it done.
511c2c66affSColin Finck     BOOL bHandled;
512c2c66affSColin Finck     _OnSize(WM_SIZE, 0, 0, bHandled);
513c2c66affSColin Finck 
514c2c66affSColin Finck     UIActivateIO(TRUE, NULL);
515c2c66affSColin Finck 
516c2c66affSColin Finck     if (dwFlags & (MPPF_INITIALSELECT | MPPF_FINALSELECT))
517c2c66affSColin Finck     {
518c2c66affSColin Finck         const int CMD_SELECT = 5;
519c2c66affSColin Finck         int CMD_SELECT_OPTS = dwFlags & MPPF_INITIALSELECT ? 0 : -2;
520c2c66affSColin Finck         IUnknown_QueryServiceExec(m_Client, SID_SMenuBandChild, &CLSID_MenuBand, CMD_SELECT, CMD_SELECT_OPTS, NULL, NULL);
521c2c66affSColin Finck     }
522c2c66affSColin Finck 
523c2c66affSColin Finck     return S_OK;
524c2c66affSColin Finck }
525c2c66affSColin Finck 
SetIconSize(THIS_ DWORD iIcon)526c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetIconSize(THIS_ DWORD iIcon)
527c2c66affSColin Finck {
528c2c66affSColin Finck     HRESULT hr;
529c2c66affSColin Finck     m_IconSize = iIcon;
530c2c66affSColin Finck 
531c2c66affSColin Finck     // Unknown meaning (set flags? set icon size?)
532c2c66affSColin Finck     const int CMD = 16;
533c2c66affSColin Finck     const int CMD_EXEC_OPT = iIcon ? 0 : 2; // seems to work
534c2c66affSColin Finck 
535c2c66affSColin Finck     hr = IUnknown_QueryServiceExec(m_Client, SID_SMenuBandChild, &CLSID_MenuBand, CMD, CMD_EXEC_OPT, NULL, NULL);
536c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
537c2c66affSColin Finck         return hr;
538c2c66affSColin Finck 
539c2c66affSColin Finck     BOOL bHandled;
540c2c66affSColin Finck     _OnSize(WM_SIZE, 0, 0, bHandled);
541c2c66affSColin Finck 
542c2c66affSColin Finck     return hr;
543c2c66affSColin Finck }
544c2c66affSColin Finck 
GetIconSize(THIS_ DWORD * piIcon)545c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetIconSize(THIS_ DWORD* piIcon)
546c2c66affSColin Finck {
547c2c66affSColin Finck     if (piIcon)
548c2c66affSColin Finck         *piIcon = m_IconSize;
549c2c66affSColin Finck     return S_OK;
550c2c66affSColin Finck }
551c2c66affSColin Finck 
SetBitmap(THIS_ HBITMAP hBitmap)552c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetBitmap(THIS_ HBITMAP hBitmap)
553c2c66affSColin Finck {
554*ad748b0bSKatayama Hirofumi MZ     if (m_Banner && m_Banner != hBitmap)
555*ad748b0bSKatayama Hirofumi MZ         ::DeleteObject(m_Banner);
556*ad748b0bSKatayama Hirofumi MZ 
557c2c66affSColin Finck     m_Banner = hBitmap;
558c2c66affSColin Finck 
559c2c66affSColin Finck     BOOL bHandled;
560c2c66affSColin Finck     _OnSize(WM_SIZE, 0, 0, bHandled);
561c2c66affSColin Finck 
562c2c66affSColin Finck     return S_OK;
563c2c66affSColin Finck }
564c2c66affSColin Finck 
GetBitmap(THIS_ HBITMAP * phBitmap)565c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetBitmap(THIS_ HBITMAP* phBitmap)
566c2c66affSColin Finck {
567c2c66affSColin Finck     if (phBitmap)
568c2c66affSColin Finck         *phBitmap = m_Banner;
569c2c66affSColin Finck     return S_OK;
570c2c66affSColin Finck }
571c2c66affSColin Finck 
SetSubMenu(IMenuPopup * pmp,BOOL fSet)572c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
573c2c66affSColin Finck {
574c2c66affSColin Finck     // Called by the MenuBand to assign itself as the logical child of the DeskBar
575c2c66affSColin Finck 
576c2c66affSColin Finck     if (fSet)
577c2c66affSColin Finck     {
578c2c66affSColin Finck         m_SubMenuChild = pmp;
579c2c66affSColin Finck     }
580c2c66affSColin Finck     else
581c2c66affSColin Finck     {
582c2c66affSColin Finck         if (m_SubMenuChild)
583c2c66affSColin Finck         {
584c2c66affSColin Finck             if (pmp == m_SubMenuChild)
585c2c66affSColin Finck             {
586c2c66affSColin Finck                 m_SubMenuChild = NULL;
587c2c66affSColin Finck             }
588c2c66affSColin Finck         }
589c2c66affSColin Finck     }
590c2c66affSColin Finck     return S_OK;
591c2c66affSColin Finck }
592c2c66affSColin Finck 
OnSelect(DWORD dwSelectType)593c2c66affSColin Finck HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnSelect(DWORD dwSelectType)
594c2c66affSColin Finck {
595c2c66affSColin Finck     CComPtr<IDeskBar> safeThis = this;
596c2c66affSColin Finck     CComPtr<IMenuPopup> oldParent = m_SubMenuParent;
597c2c66affSColin Finck 
598c2c66affSColin Finck     TRACE("OnSelect dwSelectType=%d\n", this, dwSelectType);
599c2c66affSColin Finck     switch (dwSelectType)
600c2c66affSColin Finck     {
601c2c66affSColin Finck     case MPOS_EXECUTE:
602c2c66affSColin Finck     case MPOS_FULLCANCEL:
603c2c66affSColin Finck     case MPOS_CANCELLEVEL:
604c2c66affSColin Finck 
605c2c66affSColin Finck         _CloseBar();
606c2c66affSColin Finck 
607c2c66affSColin Finck         if (dwSelectType == MPOS_CANCELLEVEL)
608c2c66affSColin Finck             return S_OK;
609c2c66affSColin Finck 
610c2c66affSColin Finck     case MPOS_SELECTLEFT:
611c2c66affSColin Finck     case MPOS_SELECTRIGHT:
612c2c66affSColin Finck     case MPOS_CHILDTRACKING:
613c2c66affSColin Finck         if (oldParent)
614c2c66affSColin Finck             return oldParent->OnSelect(dwSelectType);
615c2c66affSColin Finck         break;
616c2c66affSColin Finck     }
617c2c66affSColin Finck 
618c2c66affSColin Finck     return S_OK;
619c2c66affSColin Finck }
620c2c66affSColin Finck 
_CloseBar()621c2c66affSColin Finck HRESULT CMenuDeskBar::_CloseBar()
622c2c66affSColin Finck {
623c2c66affSColin Finck     CComPtr<IDeskBarClient> dbc;
624c2c66affSColin Finck     HRESULT hr;
625c2c66affSColin Finck 
626c2c66affSColin Finck     // Ensure that our data isn't destroyed while we are working
627c2c66affSColin Finck     CComPtr<IDeskBar> safeThis = this;
628c2c66affSColin Finck 
629c2c66affSColin Finck     m_Shown = false;
630c2c66affSColin Finck 
631c2c66affSColin Finck     if (m_SubMenuParent)
632c2c66affSColin Finck     {
633c2c66affSColin Finck         m_SubMenuParent->SetSubMenu(this, FALSE);
634c2c66affSColin Finck     }
635c2c66affSColin Finck 
636c2c66affSColin Finck     if (m_SubMenuChild)
637c2c66affSColin Finck     {
638c2c66affSColin Finck         hr = m_SubMenuChild->OnSelect(MPOS_CANCELLEVEL);
639c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hr))
640c2c66affSColin Finck             return hr;
641c2c66affSColin Finck     }
642c2c66affSColin Finck 
643c2c66affSColin Finck     hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &dbc));
644c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
645c2c66affSColin Finck         return hr;
646c2c66affSColin Finck 
647c2c66affSColin Finck     hr = dbc->UIActivateDBC(FALSE);
648c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
649c2c66affSColin Finck         return hr;
650c2c66affSColin Finck 
65196e3c7bcSMark Jansen     if (m_hWnd)
652c2c66affSColin Finck         SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE);
653c2c66affSColin Finck 
654c2c66affSColin Finck     return UIActivateIO(FALSE, NULL);
655c2c66affSColin Finck }
656c2c66affSColin Finck 
_IsSubMenuParent(HWND hwnd)657c2c66affSColin Finck BOOL CMenuDeskBar::_IsSubMenuParent(HWND hwnd)
658c2c66affSColin Finck {
659c2c66affSColin Finck     CComPtr<IMenuPopup> popup = m_SubMenuParent;
660c2c66affSColin Finck 
661c2c66affSColin Finck     while (popup)
662c2c66affSColin Finck     {
663c2c66affSColin Finck         HRESULT hr;
664c2c66affSColin Finck         HWND parent;
665c2c66affSColin Finck 
666c2c66affSColin Finck         hr = IUnknown_GetWindow(popup, &parent);
667c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hr))
668c2c66affSColin Finck             return FALSE;
669c2c66affSColin Finck         if (hwnd == parent)
670c2c66affSColin Finck             return TRUE;
671c2c66affSColin Finck 
672c2c66affSColin Finck         hr = IUnknown_GetSite(popup, IID_PPV_ARG(IMenuPopup, &popup));
673c2c66affSColin Finck         if (FAILED(hr))
674c2c66affSColin Finck             return FALSE;
675c2c66affSColin Finck     }
676c2c66affSColin Finck 
677c2c66affSColin Finck     return FALSE;
678c2c66affSColin Finck }
679c2c66affSColin Finck 
_OnSize(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)680c2c66affSColin Finck LRESULT CMenuDeskBar::_OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
681c2c66affSColin Finck {
682c2c66affSColin Finck     if (m_Client)
683c2c66affSColin Finck     {
684c2c66affSColin Finck         RECT rc;
685c2c66affSColin Finck 
686c2c66affSColin Finck         GetClientRect(&rc);
687c2c66affSColin Finck 
688*ad748b0bSKatayama Hirofumi MZ         if (m_Banner && m_IconSize != BMICON_SMALL)
689c2c66affSColin Finck         {
690c2c66affSColin Finck             BITMAP bm;
691c2c66affSColin Finck             ::GetObject(m_Banner, sizeof(bm), &bm);
692c2c66affSColin Finck             rc.left += bm.bmWidth;
693c2c66affSColin Finck         }
694c2c66affSColin Finck 
695c2c66affSColin Finck         ::SetWindowPos(m_ClientWindow, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 0);
696c2c66affSColin Finck     }
697c2c66affSColin Finck 
698c2c66affSColin Finck     return 0;
699c2c66affSColin Finck }
700c2c66affSColin Finck 
_OnNotify(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)701c2c66affSColin Finck LRESULT CMenuDeskBar::_OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
702c2c66affSColin Finck {
703c2c66affSColin Finck     if (!m_Client)
704c2c66affSColin Finck         return 0;
705c2c66affSColin Finck 
706c2c66affSColin Finck     CComPtr<IWinEventHandler> winEventHandler;
707c2c66affSColin Finck     HRESULT hr = m_Client->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
708c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
709c2c66affSColin Finck         return 0;
710c2c66affSColin Finck 
711c2c66affSColin Finck     if (winEventHandler)
712c2c66affSColin Finck     {
713c2c66affSColin Finck         LRESULT result;
714c2c66affSColin Finck         hr = winEventHandler->OnWinEvent(NULL, uMsg, wParam, lParam, &result);
715c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hr))
716c2c66affSColin Finck             return 0;
717c2c66affSColin Finck         return result;
718c2c66affSColin Finck     }
719c2c66affSColin Finck 
720c2c66affSColin Finck     return 0;
721c2c66affSColin Finck }
722c2c66affSColin Finck 
_OnPaint(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)723c2c66affSColin Finck LRESULT CMenuDeskBar::_OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
724c2c66affSColin Finck {
725c2c66affSColin Finck     bHandled = FALSE;
726c2c66affSColin Finck 
727c2c66affSColin Finck     if (m_Banner && !m_IconSize)
728c2c66affSColin Finck     {
729c2c66affSColin Finck         BITMAP bm;
730c2c66affSColin Finck         PAINTSTRUCT ps;
731c2c66affSColin Finck         HDC hdc = BeginPaint(&ps);
732c2c66affSColin Finck 
733c2c66affSColin Finck         HDC hdcMem = ::CreateCompatibleDC(hdc);
734c2c66affSColin Finck         HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_Banner);
735c2c66affSColin Finck 
736c2c66affSColin Finck         ::GetObject(m_Banner, sizeof(bm), &bm);
737c2c66affSColin Finck 
738c2c66affSColin Finck         RECT rc;
739c2c66affSColin Finck         if (!GetClientRect(&rc))
740c2c66affSColin Finck             WARN("GetClientRect failed\n");
741c2c66affSColin Finck 
742c2c66affSColin Finck         const int bx = bm.bmWidth;
743c2c66affSColin Finck         const int by = bm.bmHeight;
744c2c66affSColin Finck         const int cy = rc.bottom;
745c2c66affSColin Finck 
746c2c66affSColin Finck         TRACE("Painting banner: %d by %d\n", bm.bmWidth, bm.bmHeight);
747c2c66affSColin Finck 
748c2c66affSColin Finck         if (!::StretchBlt(hdc, 0, 0, bx, cy - by, hdcMem, 0, 0, bx, 1, SRCCOPY))
749c2c66affSColin Finck             WARN("StretchBlt failed\n");
750c2c66affSColin Finck 
751c2c66affSColin Finck         if (!::BitBlt(hdc, 0, cy - by, bx, by, hdcMem, 0, 0, SRCCOPY))
752c2c66affSColin Finck             WARN("BitBlt failed\n");
753c2c66affSColin Finck 
754c2c66affSColin Finck         ::SelectObject(hdcMem, hbmOld);
755c2c66affSColin Finck         ::DeleteDC(hdcMem);
756c2c66affSColin Finck 
757c2c66affSColin Finck         EndPaint(&ps);
758c2c66affSColin Finck     }
759c2c66affSColin Finck 
760c2c66affSColin Finck     return TRUE;
761c2c66affSColin Finck }
762c2c66affSColin Finck 
_OnActivate(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)763c2c66affSColin Finck LRESULT CMenuDeskBar::_OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
764c2c66affSColin Finck {
765c2c66affSColin Finck     // BUG in ReactOS: WM_ACTIVATE/WA_INACTIVE makes no sense with lParam==hWnd
766c2c66affSColin Finck     if (LOWORD(wParam) != 0 || reinterpret_cast<HWND>(lParam) == m_hWnd)
767c2c66affSColin Finck     {
768c2c66affSColin Finck         return 0;
769c2c66affSColin Finck     }
770c2c66affSColin Finck 
771c2c66affSColin Finck     // HACK! I just want it to work !!!
772c2c66affSColin Finck     CComPtr<IDeskBar> db;
773c2c66affSColin Finck     HRESULT hr = IUnknown_QueryService(m_Client, SID_SMenuBandChild, IID_PPV_ARG(IDeskBar, &db));
774c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
775c2c66affSColin Finck         return 0;
776c2c66affSColin Finck 
777c2c66affSColin Finck     CComPtr<IUnknown> punk;
778c2c66affSColin Finck 
779c2c66affSColin Finck     hr = db->GetClient(&punk);
780c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
781c2c66affSColin Finck         return 0;
782c2c66affSColin Finck 
783c2c66affSColin Finck     if (!punk && m_Shown)
784c2c66affSColin Finck     {
785c2c66affSColin Finck         if (!_IsSubMenuParent(reinterpret_cast<HWND>(lParam)))
786c2c66affSColin Finck         {
787c2c66affSColin Finck             OnSelect(MPOS_FULLCANCEL);
788c2c66affSColin Finck         }
789c2c66affSColin Finck     }
790c2c66affSColin Finck 
791c2c66affSColin Finck     return 0;
792c2c66affSColin Finck }
793c2c66affSColin Finck 
_OnMouseActivate(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)794c2c66affSColin Finck LRESULT CMenuDeskBar::_OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
795c2c66affSColin Finck {
796c2c66affSColin Finck     return MA_NOACTIVATE;
797c2c66affSColin Finck }
798c2c66affSColin Finck 
_OnAppActivate(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)799c2c66affSColin Finck LRESULT CMenuDeskBar::_OnAppActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
800c2c66affSColin Finck {
801c2c66affSColin Finck #if 0
802c2c66affSColin Finck     if (wParam == 0 && m_Shown)
803c2c66affSColin Finck     {
804c2c66affSColin Finck         OnSelect(MPOS_FULLCANCEL);
805c2c66affSColin Finck     }
806c2c66affSColin Finck #endif
807c2c66affSColin Finck     return 0;
808c2c66affSColin Finck }
809c2c66affSColin Finck 
_OnWinIniChange(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)810c2c66affSColin Finck LRESULT CMenuDeskBar::_OnWinIniChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
811c2c66affSColin Finck {
812c2c66affSColin Finck     if (wParam == SPI_SETFLATMENU)
813c2c66affSColin Finck         return _OnNotify(uMsg, wParam, lParam, bHandled);
814c2c66affSColin Finck 
815c2c66affSColin Finck     return 0;
816c2c66affSColin Finck }
817c2c66affSColin Finck 
_OnNcPaint(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)818c2c66affSColin Finck LRESULT CMenuDeskBar::_OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
819c2c66affSColin Finck {
820c2c66affSColin Finck     /* If it is a flat style menu we need to handle WM_NCPAINT
821c2c66affSColin Finck      * and paint the border with the right colour */
822c2c66affSColin Finck     if ((GetStyle() & WS_BORDER) == 0)
823c2c66affSColin Finck     {
824c2c66affSColin Finck         /* This isn't a flat style menu. */
825c2c66affSColin Finck         bHandled = FALSE;
826c2c66affSColin Finck         return 0;
827c2c66affSColin Finck     }
828c2c66affSColin Finck 
829c2c66affSColin Finck     HDC hdc;
830c2c66affSColin Finck     RECT rcWindow;
831c2c66affSColin Finck 
832c2c66affSColin Finck     hdc = GetWindowDC();
833c2c66affSColin Finck     GetWindowRect(&rcWindow);
834c2c66affSColin Finck     OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
835c2c66affSColin Finck     FrameRect(hdc, &rcWindow, GetSysColorBrush(COLOR_BTNSHADOW));
836c2c66affSColin Finck     ReleaseDC(hdc);
837c2c66affSColin Finck     return 0;
838c2c66affSColin Finck }
839c2c66affSColin Finck 
_OnClose(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)840c2c66affSColin Finck LRESULT CMenuDeskBar::_OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
841c2c66affSColin Finck {
842c2c66affSColin Finck     /* Prevent the CMenuDeskBar from destroying on being sent a WM_CLOSE */
843c2c66affSColin Finck     return 0;
844c2c66affSColin Finck }
845c2c66affSColin Finck 
_AdjustForTheme(BOOL bFlatStyle)846c2c66affSColin Finck HRESULT CMenuDeskBar::_AdjustForTheme(BOOL bFlatStyle)
847c2c66affSColin Finck {
848c2c66affSColin Finck     DWORD style = bFlatStyle ? WS_BORDER : WS_CLIPCHILDREN|WS_DLGFRAME;
849c2c66affSColin Finck     DWORD mask = WS_BORDER|WS_CLIPCHILDREN|WS_DLGFRAME;
850c2c66affSColin Finck     SHSetWindowBits(m_hWnd, GWL_STYLE, mask, style);
851c2c66affSColin Finck     return S_OK;
852c2c66affSColin Finck }
853c2c66affSColin Finck 
854c2c66affSColin Finck extern "C"
RSHELL_CMenuDeskBar_CreateInstance(REFIID riid,LPVOID * ppv)855c2c66affSColin Finck HRESULT WINAPI RSHELL_CMenuDeskBar_CreateInstance(REFIID riid, LPVOID *ppv)
856c2c66affSColin Finck {
857c2c66affSColin Finck     return ShellObjectCreator<CMenuDeskBar>(riid, ppv);
858c2c66affSColin Finck }
859