[RSHELL]
[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 {
352 if (fShow)
353 hr = m_focusManager->PushMenu(this);
354 else
355 hr = m_focusManager->PopMenu(this);
356 }
357
358 return S_OK;
359 }
360
361 HRESULT STDMETHODCALLTYPE CMenuBand::CloseDW(DWORD dwReserved)
362 {
363 ShowDW(FALSE);
364
365 if (m_staticToolbar != NULL)
366 return m_staticToolbar->Close();
367
368 if (m_SFToolbar != NULL)
369 return m_SFToolbar->Close();
370
371 return S_OK;
372 }
373 HRESULT STDMETHODCALLTYPE CMenuBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
374 {
375 UNIMPLEMENTED;
376 return S_OK;
377 }
378
379 HRESULT STDMETHODCALLTYPE CMenuBand::ContextSensitiveHelp(BOOL fEnterMode)
380 {
381 UNIMPLEMENTED;
382 return S_OK;
383 }
384
385 HRESULT STDMETHODCALLTYPE CMenuBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
386 {
387 HRESULT hr;
388
389 if (m_subMenuParent)
390 {
391 hr = m_subMenuParent->SetSubMenu(this, fActivate);
392 if (FAILED_UNEXPECTEDLY(hr))
393 return hr;
394 }
395
396 if (fActivate)
397 {
398 CComPtr<IOleWindow> pTopLevelWindow;
399 hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
400 if (FAILED_UNEXPECTEDLY(hr))
401 return hr;
402
403 hr = pTopLevelWindow->GetWindow(&m_topLevelWindow);
404 if (FAILED_UNEXPECTEDLY(hr))
405 return hr;
406 }
407 else
408 {
409 m_topLevelWindow = NULL;
410 }
411
412 return S_FALSE;
413 }
414
415 HRESULT STDMETHODCALLTYPE CMenuBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
416 {
417 if (!pguidCmdGroup)
418 return E_FAIL;
419
420 if (IsEqualGUID(*pguidCmdGroup, CLSID_MenuBand))
421 {
422 if (nCmdID == 16) // set (big) icon size
423 {
424 this->m_useBigIcons = nCmdexecopt == 2;
425 return S_OK;
426 }
427 else if (nCmdID == 19) // popup-related
428 {
429 return S_FALSE;
430 }
431
432 return S_FALSE;
433 }
434
435 UNIMPLEMENTED;
436 return S_OK;
437 }
438
439 HRESULT STDMETHODCALLTYPE CMenuBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
440 {
441 if (IsEqualIID(guidService, SID_SMenuBandChild) ||
442 IsEqualIID(guidService, SID_SMenuBandBottom) ||
443 IsEqualIID(guidService, SID_SMenuBandBottomSelected))
444 return this->QueryInterface(riid, ppvObject);
445 WARN("Unknown service requested %s\n", wine_dbgstr_guid(&guidService));
446 return E_NOINTERFACE;
447 }
448
449 HRESULT STDMETHODCALLTYPE CMenuBand::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
450 {
451 UNIMPLEMENTED;
452 return S_OK;
453 }
454
455 HRESULT STDMETHODCALLTYPE CMenuBand::OnSelect(DWORD dwSelectType)
456 {
457 switch (dwSelectType)
458 {
459 case MPOS_CHILDTRACKING:
460 if (!m_subMenuParent)
461 break;
462 // TODO: Cancel timers?
463 return m_subMenuParent->OnSelect(dwSelectType);
464 case MPOS_SELECTLEFT:
465 if (m_subMenuChild)
466 m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
467 if (!m_subMenuParent)
468 break;
469 return m_subMenuParent->OnSelect(dwSelectType);
470 case MPOS_SELECTRIGHT:
471 if (!m_subMenuParent)
472 break;
473 return m_subMenuParent->OnSelect(dwSelectType);
474 case MPOS_EXECUTE:
475 case MPOS_FULLCANCEL:
476 if (m_subMenuChild)
477 m_subMenuChild->OnSelect(dwSelectType);
478 if (!m_subMenuParent)
479 break;
480 return m_subMenuParent->OnSelect(dwSelectType);
481 case MPOS_CANCELLEVEL:
482 if (m_subMenuChild)
483 m_subMenuChild->OnSelect(dwSelectType);
484 break;
485 }
486 return S_FALSE;
487 }
488
489 HRESULT STDMETHODCALLTYPE CMenuBand::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
490 {
491 UNIMPLEMENTED;
492 return S_OK;
493 }
494
495 HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient)
496 {
497 if (m_subMenuChild)
498 m_subMenuChild = NULL;
499 if (!punkClient)
500 {
501 if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(NULL, -1);
502 if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(NULL, -1);
503 return S_OK;
504 }
505 HRESULT hr = punkClient->QueryInterface(IID_PPV_ARG(IMenuPopup, &m_subMenuChild));
506 m_trackingPopup = m_subMenuChild != NULL;
507 return hr;
508 }
509
510 HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
511 {
512 // HACK, so I can test for a submenu in the DeskBar
513 //UNIMPLEMENTED;
514 if (ppunkClient)
515 {
516 if (m_subMenuChild)
517 *ppunkClient = m_subMenuChild;
518 else
519 *ppunkClient = NULL;
520 }
521 return S_OK;
522 }
523
524 HRESULT STDMETHODCALLTYPE CMenuBand::IsMenuMessage(MSG *pmsg)
525 {
526 //UNIMPLEMENTED;
527 //return S_OK;
528 return S_FALSE;
529 //return E_NOTIMPL;
530 }
531
532 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateMenuMessage(MSG *pmsg, LRESULT *plRet)
533 {
534 //UNIMPLEMENTED;
535 return S_FALSE;
536 }
537
538 HRESULT STDMETHODCALLTYPE CMenuBand::SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags)
539 {
540 if (m_SFToolbar == NULL)
541 {
542 m_SFToolbar = new CMenuSFToolbar(this);
543 }
544
545 HRESULT hr = m_SFToolbar->SetShellFolder(psf, pidlFolder, hKey, dwFlags);
546 if (FAILED_UNEXPECTEDLY(hr))
547 return hr;
548
549 if (m_site)
550 {
551 HWND hwndParent;
552
553 hr = m_site->GetWindow(&hwndParent);
554 if (FAILED_UNEXPECTEDLY(hr))
555 return hr;
556
557 hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
558 if (FAILED_UNEXPECTEDLY(hr))
559 return hr;
560
561 hr = m_SFToolbar->FillToolbar();
562 }
563
564 return hr;
565 }
566
567 HRESULT STDMETHODCALLTYPE CMenuBand::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv)
568 {
569 if (m_SFToolbar)
570 return m_SFToolbar->GetShellFolder(pdwFlags, ppidl, riid, ppv);
571 return E_FAIL;
572 }
573
574 HRESULT STDMETHODCALLTYPE CMenuBand::InvalidateItem(LPSMDATA psmd, DWORD dwFlags)
575 {
576 UNIMPLEMENTED;
577 return S_OK;
578 }
579
580 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(LPSMDATA psmd)
581 {
582 UNIMPLEMENTED;
583 return S_OK;
584 }
585
586 HRESULT STDMETHODCALLTYPE CMenuBand::SetMenuToolbar(IUnknown *punk, DWORD dwFlags)
587 {
588 UNIMPLEMENTED;
589 return S_OK;
590 }
591
592 HRESULT STDMETHODCALLTYPE CMenuBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
593 {
594 *theResult = 0;
595
596 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
597 {
598 return m_staticToolbar->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
599 }
600
601 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
602 {
603 return m_SFToolbar->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
604 }
605
606 return S_FALSE;
607 }
608
609 HRESULT STDMETHODCALLTYPE CMenuBand::IsWindowOwner(HWND hWnd)
610 {
611 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
612 return S_OK;
613
614 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
615 return S_OK;
616
617 return S_FALSE;
618 }
619
620 HRESULT CMenuBand::_CallCBWithItemId(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam)
621 {
622 return _CallCB(uMsg, wParam, lParam, id);
623 }
624
625 HRESULT CMenuBand::_CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam)
626 {
627 return _CallCB(uMsg, wParam, lParam, 0, pidl);
628 }
629
630 HRESULT CMenuBand::_CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id, LPITEMIDLIST pidl)
631 {
632 if (!m_psmc)
633 return S_FALSE;
634
635 HWND hwnd;
636 GetWindow(&hwnd);
637
638 SMDATA smData = { 0 };
639 smData.punk = static_cast<IShellMenu2*>(this);
640 smData.uId = id;
641 smData.uIdParent = m_uId;
642 smData.uIdAncestor = m_uIdAncestor;
643 smData.hwnd = hwnd;
644 smData.pidlItem = pidl;
645 if (m_staticToolbar)
646 {
647 smData.hmenu = m_hmenu;
648 }
649 smData.pvUserData = NULL;
650 if (m_SFToolbar)
651 m_SFToolbar->GetShellFolder(NULL, &smData.pidlFolder, IID_PPV_ARG(IShellFolder, &smData.psf));
652 HRESULT hr = m_psmc->CallbackSM(&smData, uMsg, wParam, lParam);
653 ILFree(smData.pidlFolder);
654 if (smData.psf)
655 smData.psf->Release();
656 return hr;
657 }
658
659 HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y, RECT& rcExclude)
660 {
661 TPMPARAMS params = { sizeof(TPMPARAMS), rcExclude };
662
663 UINT flags = TPM_VERPOSANIMATION | TPM_VERTICAL | TPM_LEFTALIGN;
664
665 m_trackingPopup = TRUE;
666 m_focusManager->PushTrackedPopup(this, popup);
667 if (m_menuOwner)
668 {
669 ::TrackPopupMenuEx(popup, flags, x, y, m_menuOwner, &params);
670 }
671 else
672 {
673 ::TrackPopupMenuEx(popup, flags, x, y, m_topLevelWindow, &params);
674 }
675 m_trackingPopup = FALSE;
676 m_focusManager->PopTrackedPopup(this, popup);
677
678 return S_OK;
679 }
680
681 HRESULT CMenuBand::_GetTopLevelWindow(HWND*topLevel)
682 {
683 *topLevel = m_topLevelWindow;
684 return S_OK;
685 }
686
687 HRESULT CMenuBand::_OnHotItemChanged(CMenuToolbarBase * tb, INT id)
688 {
689 if (m_trackingPopup && id == -1)
690 {
691 return S_FALSE;
692 }
693 m_hotBar = tb;
694 m_hotItem = id;
695 if (m_staticToolbar) m_staticToolbar->OnHotItemChanged(tb, id);
696 if (m_SFToolbar) m_SFToolbar->OnHotItemChanged(tb, id);
697 return S_OK;
698 }
699
700 HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
701 {
702 HRESULT hr;
703
704 if (!(m_dwFlags & SMINIT_VERTICAL))
705 {
706 if (changeType == MPOS_SELECTRIGHT)
707 {
708 SendMessageW(m_menuOwner, WM_CANCELMODE, 0, 0);
709 if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
710 {
711 DbgPrint("SF Toolbars in Horizontal menus is not implemented.\n");
712 return S_FALSE;
713 }
714 else if (m_staticToolbar && m_hotBar == m_staticToolbar)
715 {
716 hr = m_staticToolbar->ChangeHotItem(VK_DOWN);
717 if (hr == S_FALSE)
718 {
719 if (m_SFToolbar)
720 return m_SFToolbar->ChangeHotItem(VK_HOME);
721 else
722 return m_staticToolbar->ChangeHotItem(VK_HOME);
723 }
724 return hr;
725 }
726 }
727 else if (changeType == MPOS_SELECTLEFT)
728 {
729 SendMessageW(m_menuOwner, WM_CANCELMODE, 0, 0);
730 if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar == NULL))
731 {
732 hr = m_staticToolbar->ChangeHotItem(VK_UP);
733 if (hr == S_FALSE)
734 {
735 if (m_SFToolbar)
736 return m_SFToolbar->ChangeHotItem(VK_END);
737 else
738 return m_staticToolbar->ChangeHotItem(VK_END);
739 }
740 return hr;
741 }
742 else if (m_SFToolbar && m_hotBar == m_SFToolbar)
743 {
744 DbgPrint("SF Toolbars in Horizontal menus is not implemented.\n");
745 return S_FALSE;
746 }
747 }
748 }
749 else if (changeType == VK_DOWN)
750 {
751 if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
752 {
753 hr = m_SFToolbar->ChangeHotItem(VK_DOWN);
754 if (hr == S_FALSE)
755 {
756 if (m_staticToolbar)
757 return m_staticToolbar->ChangeHotItem(VK_HOME);
758 else
759 return m_SFToolbar->ChangeHotItem(VK_HOME);
760 }
761 return hr;
762 }
763 else if (m_staticToolbar && m_hotBar == m_staticToolbar)
764 {
765 hr = m_staticToolbar->ChangeHotItem(VK_DOWN);
766 if (hr == S_FALSE)
767 {
768 if (m_SFToolbar)
769 return m_SFToolbar->ChangeHotItem(VK_HOME);
770 else
771 return m_staticToolbar->ChangeHotItem(VK_HOME);
772 }
773 return hr;
774 }
775 }
776 else if (changeType == VK_UP)
777 {
778 if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar == NULL))
779 {
780 hr = m_staticToolbar->ChangeHotItem(VK_UP);
781 if (hr == S_FALSE)
782 {
783 if (m_SFToolbar)
784 return m_SFToolbar->ChangeHotItem(VK_END);
785 else
786 return m_staticToolbar->ChangeHotItem(VK_END);
787 }
788 return hr;
789 }
790 else if (m_SFToolbar && m_hotBar == m_SFToolbar)
791 {
792 hr = m_SFToolbar->ChangeHotItem(VK_UP);
793 if (hr == S_FALSE)
794 {
795 if (m_staticToolbar)
796 return m_staticToolbar->ChangeHotItem(VK_END);
797 else
798 return m_SFToolbar->ChangeHotItem(VK_END);
799 }
800 return hr;
801 }
802 }
803 else if (changeType == MPOS_SELECTLEFT)
804 {
805 if (m_subMenuChild)
806 m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
807 if (!m_subMenuParent)
808 return S_OK;
809 return m_subMenuParent->OnSelect(MPOS_CANCELLEVEL);
810 }
811 else if (changeType == MPOS_SELECTRIGHT)
812 {
813 if (m_hotBar && m_hotItem >= 0)
814 {
815 if (m_hotBar->HasSubMenu(m_hotItem)==S_OK)
816 {
817 m_hotBar->PopupItem(m_hotItem);
818 return S_FALSE;
819 }
820 }
821 if (!m_subMenuParent)
822 return S_OK;
823 return m_subMenuParent->OnSelect(changeType);
824 }
825 else
826 {
827 if (!m_subMenuParent)
828 return S_OK;
829 return m_subMenuParent->OnSelect(changeType);
830 }
831 return S_OK;
832 }
833
834 HRESULT CMenuBand::_OnPopupSubMenu(IMenuPopup * popup, POINTL * pAt, RECTL * pExclude, CMenuToolbarBase * toolbar, INT item)
835 {
836 if (m_subMenuChild)
837 {
838 HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
839 if (FAILED_UNEXPECTEDLY(hr))
840 return hr;
841 }
842 if (m_staticToolbar) m_staticToolbar->OnPopupItemChanged(toolbar, item);
843 if (m_SFToolbar) m_SFToolbar->OnPopupItemChanged(toolbar, item);
844 m_trackingPopup = popup != NULL;
845 if (popup)
846 {
847 if (m_subMenuParent)
848 IUnknown_SetSite(popup, m_subMenuParent);
849 else
850 IUnknown_SetSite(popup, m_site);
851
852 popup->Popup(pAt, pExclude, MPPF_RIGHT);
853 }
854 return S_OK;
855 }
856
857 HRESULT CMenuBand::_DisableMouseTrack(BOOL bDisable)
858 {
859 if (m_staticToolbar)
860 m_staticToolbar->DisableMouseTrack(bDisable);
861 if (m_SFToolbar)
862 m_SFToolbar->DisableMouseTrack(bDisable);
863 return S_OK;
864 }
865
866 HRESULT STDMETHODCALLTYPE CMenuBand::GetSubMenu(THIS)
867 {
868 UNIMPLEMENTED;
869 return S_OK;
870 }
871
872 HRESULT STDMETHODCALLTYPE CMenuBand::SetToolbar(THIS)
873 {
874 UNIMPLEMENTED;
875 return S_OK;
876 }
877
878 HRESULT STDMETHODCALLTYPE CMenuBand::SetMinWidth(THIS)
879 {
880 UNIMPLEMENTED;
881 return S_OK;
882 }
883
884 HRESULT STDMETHODCALLTYPE CMenuBand::SetNoBorder(THIS)
885 {
886 UNIMPLEMENTED;
887 return S_OK;
888 }
889
890 HRESULT STDMETHODCALLTYPE CMenuBand::SetTheme(THIS)
891 {
892 UNIMPLEMENTED;
893 return S_OK;
894 }
895
896 HRESULT STDMETHODCALLTYPE CMenuBand::GetTop(THIS)
897 {
898 UNIMPLEMENTED;
899 return S_OK;
900 }
901
902 HRESULT STDMETHODCALLTYPE CMenuBand::GetBottom(THIS)
903 {
904 UNIMPLEMENTED;
905 return S_OK;
906 }
907
908 HRESULT STDMETHODCALLTYPE CMenuBand::GetTracked(THIS)
909 {
910 UNIMPLEMENTED;
911 return S_OK;
912 }
913
914 HRESULT STDMETHODCALLTYPE CMenuBand::GetParentSite(THIS)
915 {
916 UNIMPLEMENTED;
917 return S_OK;
918 }
919
920 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(THIS)
921 {
922 UNIMPLEMENTED;
923 return S_OK;
924 }
925
926 HRESULT STDMETHODCALLTYPE CMenuBand::DoDefaultAction(THIS)
927 {
928 UNIMPLEMENTED;
929 return S_OK;
930 }
931
932 HRESULT STDMETHODCALLTYPE CMenuBand::IsEmpty(THIS)
933 {
934 UNIMPLEMENTED;
935 return S_OK;
936 }
937
938 HRESULT STDMETHODCALLTYPE CMenuBand::HasFocusIO()
939 {
940 UNIMPLEMENTED;
941 return S_OK;
942 }
943
944 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateAcceleratorIO(LPMSG lpMsg)
945 {
946 UNIMPLEMENTED;
947 return S_OK;
948 }
949
950 HRESULT STDMETHODCALLTYPE CMenuBand::IsDirty()
951 {
952 UNIMPLEMENTED;
953 return S_OK;
954 }
955
956 HRESULT STDMETHODCALLTYPE CMenuBand::Load(IStream *pStm)
957 {
958 UNIMPLEMENTED;
959 return S_OK;
960 }
961
962 HRESULT STDMETHODCALLTYPE CMenuBand::Save(IStream *pStm, BOOL fClearDirty)
963 {
964 UNIMPLEMENTED;
965 return S_OK;
966 }
967
968 HRESULT STDMETHODCALLTYPE CMenuBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
969 {
970 UNIMPLEMENTED;
971 return S_OK;
972 }
973
974 HRESULT STDMETHODCALLTYPE CMenuBand::GetClassID(CLSID *pClassID)
975 {
976 UNIMPLEMENTED;
977 return S_OK;
978 }
979
980 HRESULT STDMETHODCALLTYPE CMenuBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
981 {
982 UNIMPLEMENTED;
983 return S_OK;
984 }