Sync with trunk r62529.
[reactos.git] / base / shell / rshell / CMenuBand.cpp
1 /*
2 * Shell Menu Band
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 <windowsx.h>
22 #include <CommonControls.h>
23 #include <shlwapi_undoc.h>
24
25 #include "CMenuBand.h"
26 #include "CMenuToolbars.h"
27 #include "CMenuFocusManager.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(CMenuBand);
30
31 #undef UNIMPLEMENTED
32
33 #define UNIMPLEMENTED DbgPrint("%s is UNIMPLEMENTED!\n", __FUNCTION__)
34
35 extern "C"
36 HRESULT WINAPI CMenuBand_Constructor(REFIID riid, LPVOID *ppv)
37 {
38 *ppv = NULL;
39
40 CMenuBand * site = new CComObject<CMenuBand>();
41
42 if (!site)
43 return E_OUTOFMEMORY;
44
45 HRESULT hr = site->QueryInterface(riid, ppv);
46
47 if (FAILED_UNEXPECTEDLY(hr))
48 site->Release();
49
50 return hr;
51 }
52
53 CMenuBand::CMenuBand() :
54 m_staticToolbar(NULL),
55 m_SFToolbar(NULL),
56 m_site(NULL),
57 m_psmc(NULL),
58 m_subMenuChild(NULL),
59 m_hmenu(NULL),
60 m_menuOwner(NULL),
61 m_useBigIcons(FALSE),
62 m_topLevelWindow(NULL),
63 m_hotBar(NULL),
64 m_hotItem(-1),
65 m_trackingPopup(FALSE)
66 {
67 m_focusManager = CMenuFocusManager::AcquireManager();
68 }
69
70 CMenuBand::~CMenuBand()
71 {
72 CMenuFocusManager::ReleaseManager(m_focusManager);
73
74 if (m_staticToolbar)
75 delete m_staticToolbar;
76
77 if (m_SFToolbar)
78 delete m_SFToolbar;
79 }
80
81 HRESULT STDMETHODCALLTYPE CMenuBand::Initialize(
82 IShellMenuCallback *psmc,
83 UINT uId,
84 UINT uIdAncestor,
85 DWORD dwFlags)
86 {
87 if (m_psmc != psmc)
88 m_psmc = psmc;
89 m_uId = uId;
90 m_uIdAncestor = uIdAncestor;
91 m_dwFlags = dwFlags;
92
93 if (m_psmc)
94 {
95 _CallCB(SMC_CREATE, 0, reinterpret_cast<LPARAM>(&m_UserData));
96 }
97
98 return S_OK;
99 }
100
101 HRESULT STDMETHODCALLTYPE CMenuBand::GetMenuInfo(
102 IShellMenuCallback **ppsmc,
103 UINT *puId,
104 UINT *puIdAncestor,
105 DWORD *pdwFlags)
106 {
107 if (!pdwFlags) // maybe?
108 return E_INVALIDARG;
109
110 if (ppsmc)
111 *ppsmc = m_psmc;
112
113 if (puId)
114 *puId = m_uId;
115
116 if (puIdAncestor)
117 *puIdAncestor = m_uIdAncestor;
118
119 *pdwFlags = m_dwFlags;
120
121 return S_OK;
122 }
123
124 HRESULT STDMETHODCALLTYPE CMenuBand::SetMenu(
125 HMENU hmenu,
126 HWND hwnd,
127 DWORD dwFlags)
128 {
129 DbgPrint("CMenuBand::SetMenu called, hmenu=%p; hwnd=%p, flags=%x\n", hmenu, hwnd, dwFlags);
130
131 BOOL created = FALSE;
132
133 if (m_staticToolbar == NULL)
134 {
135 m_staticToolbar = new CMenuStaticToolbar(this);
136 created = true;
137 }
138 m_hmenu = hmenu;
139 m_menuOwner = hwnd;
140
141 HRESULT hr = m_staticToolbar->SetMenu(hmenu, hwnd, dwFlags);
142 if (FAILED_UNEXPECTEDLY(hr))
143 return hr;
144
145 if (m_site)
146 {
147 HWND hwndParent;
148
149 hr = m_site->GetWindow(&hwndParent);
150 if (FAILED_UNEXPECTEDLY(hr))
151 return hr;
152
153 if (created)
154 {
155 hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
156 if (FAILED_UNEXPECTEDLY(hr))
157 return hr;
158
159 hr = m_staticToolbar->FillToolbar();
160 }
161 else
162 {
163 hr = m_staticToolbar->FillToolbar(TRUE);
164 }
165 }
166
167 return hr;
168 }
169
170 HRESULT STDMETHODCALLTYPE CMenuBand::GetMenu(
171 HMENU *phmenu,
172 HWND *phwnd,
173 DWORD *pdwFlags)
174 {
175 if (m_staticToolbar == NULL)
176 return E_FAIL;
177
178 return m_staticToolbar->GetMenu(phmenu, phwnd, pdwFlags);
179 }
180
181 HRESULT STDMETHODCALLTYPE CMenuBand::SetSite(IUnknown *pUnkSite)
182 {
183 HWND hwndParent;
184 HRESULT hr;
185
186 m_site = NULL;
187
188 if (pUnkSite == NULL)
189 return S_OK;
190
191 hwndParent = NULL;
192 hr = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &m_site));
193 if (FAILED_UNEXPECTEDLY(hr))
194 return hr;
195
196 hr = m_site->GetWindow(&hwndParent);
197 if (FAILED_UNEXPECTEDLY(hr))
198 return hr;
199
200 if (!::IsWindow(hwndParent))
201 return E_FAIL;
202
203 if (m_staticToolbar != NULL)
204 {
205 hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
206 if (FAILED_UNEXPECTEDLY(hr))
207 return hr;
208
209 hr = m_staticToolbar->FillToolbar();
210 if (FAILED_UNEXPECTEDLY(hr))
211 return hr;
212 }
213
214 if (m_SFToolbar != NULL)
215 {
216 hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
217 if (FAILED_UNEXPECTEDLY(hr))
218 return hr;
219
220 hr = m_SFToolbar->FillToolbar();
221 if (FAILED_UNEXPECTEDLY(hr))
222 return hr;
223 }
224
225 hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &m_subMenuParent));
226 if (hr != E_NOINTERFACE && FAILED_UNEXPECTEDLY(hr))
227 return hr;
228
229 CComPtr<IOleWindow> pTopLevelWindow;
230 hr = IUnknown_QueryService(m_site, SID_STopLevelBrowser, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
231 if (FAILED_UNEXPECTEDLY(hr))
232 return hr;
233
234 return pTopLevelWindow->GetWindow(&m_topLevelWindow);
235 }
236
237 HRESULT STDMETHODCALLTYPE CMenuBand::GetSite(REFIID riid, PVOID *ppvSite)
238 {
239 if (m_site == NULL)
240 return E_FAIL;
241
242 return m_site->QueryInterface(riid, ppvSite);
243 }
244
245 HRESULT STDMETHODCALLTYPE CMenuBand::GetWindow(
246 HWND *phwnd)
247 {
248 if (m_SFToolbar != NULL)
249 return m_SFToolbar->GetWindow(phwnd);
250
251 if (m_staticToolbar != NULL)
252 return m_staticToolbar->GetWindow(phwnd);
253
254 return E_FAIL;
255 }
256
257 HRESULT STDMETHODCALLTYPE CMenuBand::OnPosRectChangeDB(RECT *prc)
258 {
259 SIZE sizeStatic = { 0 };
260 SIZE sizeShlFld = { 0 };
261 HRESULT hr = S_OK;
262
263 if (m_staticToolbar != NULL)
264 hr = m_staticToolbar->GetIdealSize(sizeStatic);
265 if (FAILED_UNEXPECTEDLY(hr))
266 return hr;
267
268 if (m_SFToolbar != NULL)
269 hr = m_SFToolbar->GetIdealSize(sizeShlFld);
270 if (FAILED_UNEXPECTEDLY(hr))
271 return hr;
272
273 if (m_staticToolbar == NULL && m_SFToolbar == NULL)
274 return E_FAIL;
275
276 int sy = min(prc->bottom - prc->top, sizeStatic.cy + sizeShlFld.cy);
277
278 int syStatic = sizeStatic.cy;
279 int syShlFld = sy - syStatic;
280
281 if (m_SFToolbar)
282 {
283 m_SFToolbar->SetPosSize(
284 prc->left,
285 prc->top,
286 prc->right - prc->left,
287 syShlFld);
288 }
289 if (m_staticToolbar)
290 {
291 m_staticToolbar->SetPosSize(
292 prc->left,
293 prc->top + syShlFld,
294 prc->right - prc->left,
295 syStatic);
296 }
297
298 return S_OK;
299 }
300 HRESULT STDMETHODCALLTYPE CMenuBand::GetBandInfo(
301 DWORD dwBandID,
302 DWORD dwViewMode,
303 DESKBANDINFO *pdbi)
304 {
305 SIZE sizeStatic = { 0 };
306 SIZE sizeShlFld = { 0 };
307
308 HRESULT hr = S_OK;
309
310 if (m_staticToolbar != NULL)
311 hr = m_staticToolbar->GetIdealSize(sizeStatic);
312 if (FAILED_UNEXPECTEDLY(hr))
313 return hr;
314
315 if (m_SFToolbar != NULL)
316 hr = m_SFToolbar->GetIdealSize(sizeShlFld);
317 if (FAILED_UNEXPECTEDLY(hr))
318 return hr;
319
320 if (m_staticToolbar == NULL && m_SFToolbar == NULL)
321 return E_FAIL;
322
323 pdbi->ptMinSize.x = max(sizeStatic.cx, sizeShlFld.cx) + 20;
324 pdbi->ptMinSize.y = sizeStatic.cy + sizeShlFld.cy;
325 pdbi->ptMaxSize.x = max(sizeStatic.cx, sizeShlFld.cx) + 20;
326 pdbi->ptMaxSize.y = sizeStatic.cy + sizeShlFld.cy;
327
328 return S_OK;
329 }
330
331 HRESULT STDMETHODCALLTYPE CMenuBand::ShowDW(BOOL fShow)
332 {
333 HRESULT hr = S_OK;
334
335 if (m_staticToolbar != NULL)
336 hr = m_staticToolbar->ShowWindow(fShow);
337 if (FAILED_UNEXPECTEDLY(hr))
338 return hr;
339 if (m_SFToolbar != NULL)
340 hr = m_SFToolbar->ShowWindow(fShow);
341 if (FAILED_UNEXPECTEDLY(hr))
342 return hr;
343
344 if (fShow)
345 {
346 hr = _CallCB(SMC_INITMENU, 0, 0);
347 if (FAILED_UNEXPECTEDLY(hr))
348 return hr;
349 }
350
351 CComPtr<IServiceProvider> sp;
352 CComPtr<IUnknown> unk0;
353 CComPtr<IDeskBar> db0, db, db1;
354 if (SUCCEEDED(IUnknown_GetSite(m_subMenuParent, IID_PPV_ARG(IServiceProvider, &sp))) &&
355 SUCCEEDED(sp->QueryInterface(IID_PPV_ARG(IDeskBar, &db0))) &&
356 SUCCEEDED(db0->GetClient(&unk0)) &&
357 SUCCEEDED(IUnknown_QueryService(unk0, SID_SMenuBandChild, IID_PPV_ARG(IDeskBar, &db))) &&
358 SUCCEEDED(IUnknown_QueryService(m_site, SID_SMenuBandParent, IID_PPV_ARG(IDeskBar, &db1))))
359 {
360 if (fShow)
361 db->SetClient(db1);
362 else
363 db->SetClient(NULL);
364 }
365
366 if (m_dwFlags & SMINIT_VERTICAL)
367 {
368 if (fShow)
369 hr = m_focusManager->PushMenu(this);
370 else
371 hr = m_focusManager->PopMenu(this);
372 }
373
374 return S_OK;
375 }
376
377 HRESULT STDMETHODCALLTYPE CMenuBand::CloseDW(DWORD dwReserved)
378 {
379 ShowDW(FALSE);
380
381 if (m_staticToolbar != NULL)
382 return m_staticToolbar->Close();
383
384 if (m_SFToolbar != NULL)
385 return m_SFToolbar->Close();
386
387 return S_OK;
388 }
389 HRESULT STDMETHODCALLTYPE CMenuBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
390 {
391 UNIMPLEMENTED;
392 return S_OK;
393 }
394
395 HRESULT STDMETHODCALLTYPE CMenuBand::ContextSensitiveHelp(BOOL fEnterMode)
396 {
397 UNIMPLEMENTED;
398 return S_OK;
399 }
400
401 HRESULT STDMETHODCALLTYPE CMenuBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
402 {
403 HRESULT hr;
404
405 if (m_subMenuParent)
406 {
407 hr = m_subMenuParent->SetSubMenu(this, fActivate);
408 if (FAILED_UNEXPECTEDLY(hr))
409 return hr;
410 }
411
412 if (fActivate)
413 {
414 CComPtr<IOleWindow> pTopLevelWindow;
415 hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
416 if (FAILED_UNEXPECTEDLY(hr))
417 return hr;
418
419 hr = pTopLevelWindow->GetWindow(&m_topLevelWindow);
420 if (FAILED_UNEXPECTEDLY(hr))
421 return hr;
422 }
423 else
424 {
425 m_topLevelWindow = NULL;
426 }
427
428 return S_FALSE;
429 }
430
431 HRESULT STDMETHODCALLTYPE CMenuBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
432 {
433 if (!pguidCmdGroup)
434 return E_FAIL;
435
436 if (IsEqualGUID(*pguidCmdGroup, CLSID_MenuBand))
437 {
438 if (nCmdID == 16) // set (big) icon size
439 {
440 this->m_useBigIcons = nCmdexecopt == 2;
441 return S_OK;
442 }
443 else if (nCmdID == 19) // popup-related
444 {
445 return S_FALSE;
446 }
447
448 return S_FALSE;
449 }
450
451 UNIMPLEMENTED;
452 return S_OK;
453 }
454
455 HRESULT STDMETHODCALLTYPE CMenuBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
456 {
457 if (IsEqualIID(guidService, SID_SMenuBandChild) ||
458 IsEqualIID(guidService, SID_SMenuBandBottom) ||
459 IsEqualIID(guidService, SID_SMenuBandBottomSelected))
460 return this->QueryInterface(riid, ppvObject);
461 WARN("Unknown service requested %s\n", wine_dbgstr_guid(&guidService));
462 return E_NOINTERFACE;
463 }
464
465 HRESULT STDMETHODCALLTYPE CMenuBand::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
466 {
467 UNIMPLEMENTED;
468 return S_OK;
469 }
470
471 HRESULT STDMETHODCALLTYPE CMenuBand::OnSelect(DWORD dwSelectType)
472 {
473 switch (dwSelectType)
474 {
475 case MPOS_CHILDTRACKING:
476 if (!m_subMenuParent)
477 break;
478 // TODO: Cancel timers?
479 return m_subMenuParent->OnSelect(dwSelectType);
480 case MPOS_SELECTLEFT:
481 if (m_subMenuChild)
482 m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
483 if (!m_subMenuParent)
484 break;
485 return m_subMenuParent->OnSelect(dwSelectType);
486 case MPOS_SELECTRIGHT:
487 if (!m_subMenuParent)
488 break;
489 return m_subMenuParent->OnSelect(dwSelectType);
490 case MPOS_EXECUTE:
491 case MPOS_FULLCANCEL:
492 if (m_subMenuChild)
493 m_subMenuChild->OnSelect(dwSelectType);
494 if (!m_subMenuParent)
495 break;
496 return m_subMenuParent->OnSelect(dwSelectType);
497 case MPOS_CANCELLEVEL:
498 if (m_subMenuChild)
499 m_subMenuChild->OnSelect(dwSelectType);
500 break;
501 }
502 return S_FALSE;
503 }
504
505 HRESULT STDMETHODCALLTYPE CMenuBand::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
506 {
507 UNIMPLEMENTED;
508 return S_OK;
509 }
510
511 HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient)
512 {
513 if (m_subMenuChild)
514 m_subMenuChild = NULL;
515 if (!punkClient)
516 return S_OK;
517 HRESULT hr = punkClient->QueryInterface(IID_PPV_ARG(IMenuPopup, &m_subMenuChild));
518 m_trackingPopup = m_subMenuChild != NULL;
519 if (!m_trackingPopup)
520 {
521 if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(NULL, -1);
522 if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(NULL, -1);
523 }
524 return hr;
525 }
526
527 HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
528 {
529 // HACK, so I can test for a submenu in the DeskBar
530 //UNIMPLEMENTED;
531 if (ppunkClient)
532 {
533 if (m_subMenuChild)
534 *ppunkClient = m_subMenuChild;
535 else
536 *ppunkClient = NULL;
537 }
538 return S_OK;
539 }
540
541 HRESULT STDMETHODCALLTYPE CMenuBand::IsMenuMessage(MSG *pmsg)
542 {
543 //UNIMPLEMENTED;
544 //return S_OK;
545 return S_FALSE;
546 //return E_NOTIMPL;
547 }
548
549 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateMenuMessage(MSG *pmsg, LRESULT *plRet)
550 {
551 //UNIMPLEMENTED;
552 return S_FALSE;
553 }
554
555 HRESULT STDMETHODCALLTYPE CMenuBand::SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags)
556 {
557 if (m_SFToolbar == NULL)
558 {
559 m_SFToolbar = new CMenuSFToolbar(this);
560 }
561
562 HRESULT hr = m_SFToolbar->SetShellFolder(psf, pidlFolder, hKey, dwFlags);
563 if (FAILED_UNEXPECTEDLY(hr))
564 return hr;
565
566 if (m_site)
567 {
568 HWND hwndParent;
569
570 hr = m_site->GetWindow(&hwndParent);
571 if (FAILED_UNEXPECTEDLY(hr))
572 return hr;
573
574 hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
575 if (FAILED_UNEXPECTEDLY(hr))
576 return hr;
577
578 hr = m_SFToolbar->FillToolbar();
579 }
580
581 return hr;
582 }
583
584 HRESULT STDMETHODCALLTYPE CMenuBand::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv)
585 {
586 if (m_SFToolbar)
587 return m_SFToolbar->GetShellFolder(pdwFlags, ppidl, riid, ppv);
588 return E_FAIL;
589 }
590
591 HRESULT STDMETHODCALLTYPE CMenuBand::InvalidateItem(LPSMDATA psmd, DWORD dwFlags)
592 {
593 UNIMPLEMENTED;
594 return S_OK;
595 }
596
597 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(LPSMDATA psmd)
598 {
599 UNIMPLEMENTED;
600 return S_OK;
601 }
602
603 HRESULT STDMETHODCALLTYPE CMenuBand::SetMenuToolbar(IUnknown *punk, DWORD dwFlags)
604 {
605 UNIMPLEMENTED;
606 return S_OK;
607 }
608
609 HRESULT STDMETHODCALLTYPE CMenuBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
610 {
611 *theResult = 0;
612
613 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
614 {
615 return m_staticToolbar->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
616 }
617
618 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
619 {
620 return m_SFToolbar->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
621 }
622
623 return S_FALSE;
624 }
625
626 HRESULT STDMETHODCALLTYPE CMenuBand::IsWindowOwner(HWND hWnd)
627 {
628 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
629 return S_OK;
630
631 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
632 return S_OK;
633
634 return S_FALSE;
635 }
636
637 HRESULT CMenuBand::_CallCBWithItemId(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam)
638 {
639 return _CallCB(uMsg, wParam, lParam, id);
640 }
641
642 HRESULT CMenuBand::_CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam)
643 {
644 return _CallCB(uMsg, wParam, lParam, 0, pidl);
645 }
646
647 HRESULT CMenuBand::_CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id, LPITEMIDLIST pidl)
648 {
649 if (!m_psmc)
650 return S_FALSE;
651
652 HWND hwnd;
653 GetWindow(&hwnd);
654
655 SMDATA smData = { 0 };
656 smData.punk = static_cast<IShellMenu2*>(this);
657 smData.uId = id;
658 smData.uIdParent = m_uId;
659 smData.uIdAncestor = m_uIdAncestor;
660 smData.hwnd = hwnd;
661 smData.pidlItem = pidl;
662 if (m_staticToolbar)
663 {
664 smData.hmenu = m_hmenu;
665 }
666 smData.pvUserData = NULL;
667 if (m_SFToolbar)
668 m_SFToolbar->GetShellFolder(NULL, &smData.pidlFolder, IID_PPV_ARG(IShellFolder, &smData.psf));
669 HRESULT hr = m_psmc->CallbackSM(&smData, uMsg, wParam, lParam);
670 ILFree(smData.pidlFolder);
671 if (smData.psf)
672 smData.psf->Release();
673 return hr;
674 }
675
676 HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, RECT& rcExclude)
677 {
678 TPMPARAMS params = { sizeof(TPMPARAMS), rcExclude };
679
680 UINT flags = TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_LEFTALIGN;
681
682 m_trackingPopup = TRUE;
683 m_focusManager->PushTrackedPopup(this, popup);
684 if (m_menuOwner)
685 {
686 ::TrackPopupMenuEx(popup, flags, x, y, m_menuOwner, &params);
687 }
688 else
689 {
690 ::TrackPopupMenuEx(popup, flags, x, y, m_topLevelWindow, &params);
691 }
692 m_trackingPopup = FALSE;
693 m_focusManager->PopTrackedPopup(this, popup);
694
695 return S_OK;
696 }
697
698 HRESULT CMenuBand::_GetTopLevelWindow(HWND*topLevel)
699 {
700 *topLevel = m_topLevelWindow;
701 return S_OK;
702 }
703
704 HRESULT CMenuBand::_OnHotItemChanged(CMenuToolbarBase * tb, INT id)
705 {
706 if (m_trackingPopup && id == -1)
707 {
708 return S_FALSE;
709 }
710 m_hotBar = tb;
711 m_hotItem = id;
712 if (m_staticToolbar) m_staticToolbar->OnHotItemChanged(tb, id);
713 if (m_SFToolbar) m_SFToolbar->OnHotItemChanged(tb, id);
714 return S_OK;
715 }
716
717 HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
718 {
719 HRESULT hr;
720
721 if (!(m_dwFlags & SMINIT_VERTICAL))
722 {
723 if (changeType == MPOS_SELECTRIGHT)
724 {
725 SendMessageW(m_menuOwner, WM_CANCELMODE, 0, 0);
726 if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
727 {
728 DbgPrint("SF Toolbars in Horizontal menus is not implemented.\n");
729 return S_FALSE;
730 }
731 else if (m_staticToolbar && m_hotBar == m_staticToolbar)
732 {
733 hr = m_staticToolbar->ChangeHotItem(VK_DOWN);
734 if (hr == S_FALSE)
735 {
736 if (m_SFToolbar)
737 return m_SFToolbar->ChangeHotItem(VK_HOME);
738 else
739 return m_staticToolbar->ChangeHotItem(VK_HOME);
740 }
741 return hr;
742 }
743 }
744 else if (changeType == MPOS_SELECTLEFT)
745 {
746 SendMessageW(m_menuOwner, WM_CANCELMODE, 0, 0);
747 if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar == NULL))
748 {
749 hr = m_staticToolbar->ChangeHotItem(VK_UP);
750 if (hr == S_FALSE)
751 {
752 if (m_SFToolbar)
753 return m_SFToolbar->ChangeHotItem(VK_END);
754 else
755 return m_staticToolbar->ChangeHotItem(VK_END);
756 }
757 return hr;
758 }
759 else if (m_SFToolbar && m_hotBar == m_SFToolbar)
760 {
761 DbgPrint("SF Toolbars in Horizontal menus is not implemented.\n");
762 return S_FALSE;
763 }
764 }
765 }
766 else if (changeType == VK_DOWN)
767 {
768 if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
769 {
770 hr = m_SFToolbar->ChangeHotItem(VK_DOWN);
771 if (hr == S_FALSE)
772 {
773 if (m_staticToolbar)
774 return m_staticToolbar->ChangeHotItem(VK_HOME);
775 else
776 return m_SFToolbar->ChangeHotItem(VK_HOME);
777 }
778 return hr;
779 }
780 else if (m_staticToolbar && m_hotBar == m_staticToolbar)
781 {
782 hr = m_staticToolbar->ChangeHotItem(VK_DOWN);
783 if (hr == S_FALSE)
784 {
785 if (m_SFToolbar)
786 return m_SFToolbar->ChangeHotItem(VK_HOME);
787 else
788 return m_staticToolbar->ChangeHotItem(VK_HOME);
789 }
790 return hr;
791 }
792 }
793 else if (changeType == VK_UP)
794 {
795 if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar == NULL))
796 {
797 hr = m_staticToolbar->ChangeHotItem(VK_UP);
798 if (hr == S_FALSE)
799 {
800 if (m_SFToolbar)
801 return m_SFToolbar->ChangeHotItem(VK_END);
802 else
803 return m_staticToolbar->ChangeHotItem(VK_END);
804 }
805 return hr;
806 }
807 else if (m_SFToolbar && m_hotBar == m_SFToolbar)
808 {
809 hr = m_SFToolbar->ChangeHotItem(VK_UP);
810 if (hr == S_FALSE)
811 {
812 if (m_staticToolbar)
813 return m_staticToolbar->ChangeHotItem(VK_END);
814 else
815 return m_SFToolbar->ChangeHotItem(VK_END);
816 }
817 return hr;
818 }
819 }
820 else if (changeType == MPOS_SELECTLEFT)
821 {
822 if (m_subMenuChild)
823 m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
824 if (!m_subMenuParent)
825 return S_OK;
826 return m_subMenuParent->OnSelect(MPOS_CANCELLEVEL);
827 }
828 else if (changeType == MPOS_SELECTRIGHT)
829 {
830 if (m_hotBar && m_hotItem >= 0)
831 {
832 if (m_hotBar->HasSubMenu(m_hotItem)==S_OK)
833 {
834 m_hotBar->PopupItem(m_hotItem);
835 return S_FALSE;
836 }
837 }
838 if (!m_subMenuParent)
839 return S_OK;
840 return m_subMenuParent->OnSelect(changeType);
841 }
842 else
843 {
844 if (!m_subMenuParent)
845 return S_OK;
846 return m_subMenuParent->OnSelect(changeType);
847 }
848 return S_OK;
849 }
850
851 HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude, CMenuToolbarBase * toolbar, INT item)
852 {
853 if (m_subMenuChild)
854 {
855 HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
856 if (FAILED_UNEXPECTEDLY(hr))
857 return hr;
858 }
859 if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(toolbar, item);
860 if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(toolbar, item);
861 m_trackingPopup = popup != NULL;
862 if (popup)
863 {
864 if (m_subMenuParent)
865 IUnknown_SetSite(popup, m_subMenuParent);
866 else
867 IUnknown_SetSite(popup, m_site);
868
869 popup->Popup(pAt, pExclude, MPPF_RIGHT);
870 }
871 return S_OK;
872 }
873
874 HRESULT CMenuBand::_DisableMouseTrack(BOOL bDisable)
875 {
876 if (m_staticToolbar)
877 m_staticToolbar->DisableMouseTrack(bDisable);
878 if (m_SFToolbar)
879 m_SFToolbar->DisableMouseTrack(bDisable);
880 return S_OK;
881 }
882
883 HRESULT STDMETHODCALLTYPE CMenuBand::GetSubMenu(THIS)
884 {
885 UNIMPLEMENTED;
886 return S_OK;
887 }
888
889 HRESULT STDMETHODCALLTYPE CMenuBand::SetToolbar(THIS)
890 {
891 UNIMPLEMENTED;
892 return S_OK;
893 }
894
895 HRESULT STDMETHODCALLTYPE CMenuBand::SetMinWidth(THIS)
896 {
897 UNIMPLEMENTED;
898 return S_OK;
899 }
900
901 HRESULT STDMETHODCALLTYPE CMenuBand::SetNoBorder(THIS)
902 {
903 UNIMPLEMENTED;
904 return S_OK;
905 }
906
907 HRESULT STDMETHODCALLTYPE CMenuBand::SetTheme(THIS)
908 {
909 UNIMPLEMENTED;
910 return S_OK;
911 }
912
913 HRESULT STDMETHODCALLTYPE CMenuBand::GetTop(THIS)
914 {
915 UNIMPLEMENTED;
916 return S_OK;
917 }
918
919 HRESULT STDMETHODCALLTYPE CMenuBand::GetBottom(THIS)
920 {
921 UNIMPLEMENTED;
922 return S_OK;
923 }
924
925 HRESULT STDMETHODCALLTYPE CMenuBand::GetTracked(THIS)
926 {
927 UNIMPLEMENTED;
928 return S_OK;
929 }
930
931 HRESULT STDMETHODCALLTYPE CMenuBand::GetParentSite(THIS)
932 {
933 UNIMPLEMENTED;
934 return S_OK;
935 }
936
937 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(THIS)
938 {
939 UNIMPLEMENTED;
940 return S_OK;
941 }
942
943 HRESULT STDMETHODCALLTYPE CMenuBand::DoDefaultAction(THIS)
944 {
945 UNIMPLEMENTED;
946 return S_OK;
947 }
948
949 HRESULT STDMETHODCALLTYPE CMenuBand::IsEmpty(THIS)
950 {
951 UNIMPLEMENTED;
952 return S_OK;
953 }
954
955 HRESULT STDMETHODCALLTYPE CMenuBand::HasFocusIO()
956 {
957 UNIMPLEMENTED;
958 return S_OK;
959 }
960
961 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateAcceleratorIO(LPMSG lpMsg)
962 {
963 UNIMPLEMENTED;
964 return S_OK;
965 }
966
967 HRESULT STDMETHODCALLTYPE CMenuBand::IsDirty()
968 {
969 UNIMPLEMENTED;
970 return S_OK;
971 }
972
973 HRESULT STDMETHODCALLTYPE CMenuBand::Load(IStream *pStm)
974 {
975 UNIMPLEMENTED;
976 return S_OK;
977 }
978
979 HRESULT STDMETHODCALLTYPE CMenuBand::Save(IStream *pStm, BOOL fClearDirty)
980 {
981 UNIMPLEMENTED;
982 return S_OK;
983 }
984
985 HRESULT STDMETHODCALLTYPE CMenuBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
986 {
987 UNIMPLEMENTED;
988 return S_OK;
989 }
990
991 HRESULT STDMETHODCALLTYPE CMenuBand::GetClassID(CLSID *pClassID)
992 {
993 UNIMPLEMENTED;
994 return S_OK;
995 }
996
997 HRESULT STDMETHODCALLTYPE CMenuBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
998 {
999 UNIMPLEMENTED;
1000 return S_OK;
1001 }