a8bd91cb7e9725365981c2563bff228b2b6798d7
[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 <shlwapi_undoc.h>
23
24 WINE_DEFAULT_DEBUG_CHANNEL(CMenuBand);
25
26 #define TBSTYLE_EX_VERTICAL 4
27
28 #define TIMERID_HOTTRACK 1
29 #define SUBCLASS_ID_MENUBAND 1
30
31 extern "C" BOOL WINAPI Shell_GetImageLists(HIMAGELIST * lpBigList, HIMAGELIST * lpSmallList);
32
33 class CMenuBand;
34 class CMenuFocusManager;
35
36 class CMenuToolbarBase
37 {
38 public:
39 CMenuToolbarBase(CMenuBand *menuBand);
40 virtual ~CMenuToolbarBase() {}
41
42 HRESULT CreateToolbar(HWND hwndParent, DWORD dwFlags);
43 HRESULT GetWindow(HWND *phwnd);
44 HRESULT ShowWindow(BOOL fShow);
45 HRESULT Close();
46
47 BOOL IsWindowOwner(HWND hwnd) { return m_hwnd && m_hwnd == hwnd; }
48
49 virtual HRESULT FillToolbar() = 0;
50 virtual HRESULT PopupItem(UINT uItem) = 0;
51 virtual HRESULT HasSubMenu(UINT uItem) = 0;
52 virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
53 virtual HRESULT OnContextMenu(NMMOUSE * rclick) = 0;
54
55 HRESULT OnHotItemChange(const NMTBHOTITEM * hot);
56
57 HRESULT PopupSubMenu(UINT index, IShellMenu* childShellMenu);
58 HRESULT PopupSubMenu(UINT index, HMENU menu);
59 HRESULT DoContextMenu(IContextMenu* contextMenu);
60
61 static LRESULT CALLBACK s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
62 protected:
63
64 static const UINT WM_USER_SHOWPOPUPMENU = WM_USER + 1;
65
66 LRESULT CALLBACK SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
67
68 CMenuBand *m_menuBand;
69 HWND m_hwnd;
70 DWORD m_dwMenuFlags;
71 INT m_hotItem;
72 WNDPROC m_SubclassOld;
73 };
74
75 class CMenuStaticToolbar : public CMenuToolbarBase
76 {
77 public:
78 CMenuStaticToolbar(CMenuBand *menuBand);
79 virtual ~CMenuStaticToolbar() {}
80
81 HRESULT SetMenu(HMENU hmenu, HWND hwnd, DWORD dwFlags);
82 HRESULT GetMenu(HMENU *phmenu, HWND *phwnd, DWORD *pdwFlags);
83
84 virtual HRESULT FillToolbar();
85 virtual HRESULT PopupItem(UINT uItem);
86 virtual HRESULT HasSubMenu(UINT uItem);
87 virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
88 virtual HRESULT OnContextMenu(NMMOUSE * rclick);
89
90 private:
91 HMENU m_hmenu;
92 };
93
94 class CMenuSFToolbar : public CMenuToolbarBase
95 {
96 public:
97 CMenuSFToolbar(CMenuBand *menuBand);
98 virtual ~CMenuSFToolbar();
99
100 HRESULT SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags);
101 HRESULT GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv);
102
103 virtual HRESULT FillToolbar();
104 virtual HRESULT PopupItem(UINT uItem);
105 virtual HRESULT HasSubMenu(UINT uItem);
106 virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
107 virtual HRESULT OnContextMenu(NMMOUSE * rclick);
108
109 private:
110 LPITEMIDLIST GetPidlFromId(UINT uItem, INT* pIndex);
111
112 IShellFolder * m_shellFolder;
113 LPCITEMIDLIST m_idList;
114 HKEY m_hKey;
115 };
116
117 class CMenuBand :
118 public CComCoClass<CMenuBand>,
119 public CComObjectRootEx<CComMultiThreadModelNoCS>,
120 public IDeskBand,
121 public IObjectWithSite,
122 public IInputObject,
123 public IPersistStream,
124 public IOleCommandTarget,
125 public IServiceProvider,
126 public IMenuPopup,
127 public IMenuBand,
128 public IShellMenu2,
129 public IWinEventHandler,
130 public IShellMenuAcc
131 {
132 public:
133 CMenuBand();
134 ~CMenuBand();
135
136 private:
137 IOleWindow *m_site;
138 IShellMenuCallback *m_psmc;
139
140 CMenuStaticToolbar *m_staticToolbar;
141 CMenuSFToolbar *m_SFToolbar;
142
143 UINT m_uId;
144 UINT m_uIdAncestor;
145 DWORD m_dwFlags;
146 PVOID m_UserData;
147 HMENU m_hmenu;
148 HWND m_menuOwner;
149
150 BOOL m_useBigIcons;
151
152 HWND m_topLevelWindow;
153
154 CMenuFocusManager * m_focusManager;
155
156 public:
157
158 // *** IDeskBand methods ***
159 virtual HRESULT STDMETHODCALLTYPE GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi);
160
161 // *** IDockingWindow methods ***
162 virtual HRESULT STDMETHODCALLTYPE ShowDW(BOOL fShow);
163 virtual HRESULT STDMETHODCALLTYPE CloseDW(DWORD dwReserved);
164 virtual HRESULT STDMETHODCALLTYPE ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved);
165
166 // *** IOleWindow methods ***
167 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
168 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
169
170 // *** IObjectWithSite methods ***
171 virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
172 virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, PVOID *ppvSite);
173
174 // *** IInputObject methods ***
175 virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg);
176 virtual HRESULT STDMETHODCALLTYPE HasFocusIO();
177 virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg);
178
179 // *** IPersistStream methods ***
180 virtual HRESULT STDMETHODCALLTYPE IsDirty();
181 virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm);
182 virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
183 virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
184
185 // *** IPersist methods ***
186 virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
187
188 // *** IOleCommandTarget methods ***
189 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText);
190 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
191
192 // *** IServiceProvider methods ***
193 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
194
195 // *** IMenuPopup methods ***
196 virtual HRESULT STDMETHODCALLTYPE Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags);
197 virtual HRESULT STDMETHODCALLTYPE OnSelect(DWORD dwSelectType);
198 virtual HRESULT STDMETHODCALLTYPE SetSubMenu(IMenuPopup *pmp, BOOL fSet);
199
200 // *** IDeskBar methods ***
201 virtual HRESULT STDMETHODCALLTYPE SetClient(IUnknown *punkClient);
202 virtual HRESULT STDMETHODCALLTYPE GetClient(IUnknown **ppunkClient);
203 virtual HRESULT STDMETHODCALLTYPE OnPosRectChangeDB(RECT *prc);
204
205 // *** IMenuBand methods ***
206 virtual HRESULT STDMETHODCALLTYPE IsMenuMessage(MSG *pmsg);
207 virtual HRESULT STDMETHODCALLTYPE TranslateMenuMessage(MSG *pmsg, LRESULT *plRet);
208
209 // *** IShellMenu methods ***
210 virtual HRESULT STDMETHODCALLTYPE Initialize(IShellMenuCallback *psmc, UINT uId, UINT uIdAncestor, DWORD dwFlags);
211 virtual HRESULT STDMETHODCALLTYPE GetMenuInfo(IShellMenuCallback **ppsmc, UINT *puId, UINT *puIdAncestor, DWORD *pdwFlags);
212 virtual HRESULT STDMETHODCALLTYPE SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags);
213 virtual HRESULT STDMETHODCALLTYPE GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv);
214 virtual HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenu, HWND hwnd, DWORD dwFlags);
215 virtual HRESULT STDMETHODCALLTYPE GetMenu(HMENU *phmenu, HWND *phwnd, DWORD *pdwFlags);
216 virtual HRESULT STDMETHODCALLTYPE InvalidateItem(LPSMDATA psmd, DWORD dwFlags);
217 virtual HRESULT STDMETHODCALLTYPE GetState(LPSMDATA psmd);
218 virtual HRESULT STDMETHODCALLTYPE SetMenuToolbar(IUnknown *punk, DWORD dwFlags);
219
220 // *** IWinEventHandler methods ***
221 virtual HRESULT STDMETHODCALLTYPE OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult);
222 virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd);
223
224 // *** IShellMenu2 methods ***
225 virtual HRESULT STDMETHODCALLTYPE GetSubMenu(THIS);
226 virtual HRESULT STDMETHODCALLTYPE SetToolbar(THIS);
227 virtual HRESULT STDMETHODCALLTYPE SetMinWidth(THIS);
228 virtual HRESULT STDMETHODCALLTYPE SetNoBorder(THIS);
229 virtual HRESULT STDMETHODCALLTYPE SetTheme(THIS);
230
231 // *** IShellMenuAcc methods ***
232 virtual HRESULT STDMETHODCALLTYPE GetTop(THIS);
233 virtual HRESULT STDMETHODCALLTYPE GetBottom(THIS);
234 virtual HRESULT STDMETHODCALLTYPE GetTracked(THIS);
235 virtual HRESULT STDMETHODCALLTYPE GetParentSite(THIS);
236 virtual HRESULT STDMETHODCALLTYPE GetState(THIS);
237 virtual HRESULT STDMETHODCALLTYPE DoDefaultAction(THIS);
238 virtual HRESULT STDMETHODCALLTYPE IsEmpty(THIS);
239
240 HRESULT CallCBWithId(UINT Id, UINT uMsg, WPARAM wParam, LPARAM lParam);
241 HRESULT CallCBWithPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam);
242 HRESULT TrackPopup(HMENU popup, INT x, INT y);
243 HRESULT GetTopLevelWindow(HWND*topLevel);
244
245 BOOL UseBigIcons() {
246 return m_useBigIcons;
247 }
248
249 DECLARE_NOT_AGGREGATABLE(CMenuBand)
250 DECLARE_PROTECT_FINAL_CONSTRUCT()
251
252 BEGIN_COM_MAP(CMenuBand)
253 COM_INTERFACE_ENTRY_IID(IID_IDeskBar, IMenuPopup)
254 COM_INTERFACE_ENTRY_IID(IID_IShellMenu, IShellMenu)
255 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
256 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IDeskBand)
257 COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
258 COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
259 COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
260 COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
261 COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
262 COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersistStream)
263 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
264 COM_INTERFACE_ENTRY_IID(IID_IMenuPopup, IMenuPopup)
265 COM_INTERFACE_ENTRY_IID(IID_IMenuBand, IMenuBand)
266 COM_INTERFACE_ENTRY_IID(IID_IShellMenu2, IShellMenu2)
267 COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
268 COM_INTERFACE_ENTRY_IID(IID_IShellMenuAcc, IShellMenuAcc)
269 END_COM_MAP()
270
271 private:
272 HRESULT _CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id = 0, LPITEMIDLIST pidl = NULL);
273 };
274
275 class CMenuFocusManager :
276 public CComCoClass<CMenuFocusManager>,
277 public CComObjectRootEx<CComMultiThreadModelNoCS>
278 {
279 private:
280 static DWORD TlsIndex;
281
282 static CMenuFocusManager * GetManager()
283 {
284 return reinterpret_cast<CMenuFocusManager *>(TlsGetValue(TlsIndex));
285 }
286
287 public:
288 static CMenuFocusManager * AcquireManager()
289 {
290 CMenuFocusManager * obj = NULL;
291
292 if (!TlsIndex)
293 {
294 if ((TlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
295 return NULL;
296 }
297
298 obj = GetManager();
299
300 if (!obj)
301 {
302 obj = new CComObject<CMenuFocusManager>();
303 TlsSetValue(TlsIndex, obj);
304 }
305
306 obj->AddRef();
307
308 return obj;
309 }
310
311 static void ReleaseManager(CMenuFocusManager * obj)
312 {
313 if (!obj->Release())
314 {
315 TlsSetValue(TlsIndex, NULL);
316 }
317 }
318
319 private:
320 static LRESULT CALLBACK s_GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
321 {
322 return GetManager()->GetMsgHook(nCode, wParam, lParam);
323 }
324
325 private:
326 // TODO: make dynamic
327 #define MAX_RECURSE 100
328 CMenuBand* m_bandStack[MAX_RECURSE];
329 int m_bandCount;
330
331 HRESULT PushToArray(CMenuBand * item)
332 {
333 if (m_bandCount >= MAX_RECURSE)
334 return E_OUTOFMEMORY;
335
336 m_bandStack[m_bandCount++] = item;
337 return S_OK;
338 }
339
340 HRESULT PopFromArray(CMenuBand ** pItem)
341 {
342 if (pItem)
343 *pItem = NULL;
344
345 if (m_bandCount <= 0)
346 return E_FAIL;
347
348 m_bandCount--;
349
350 if (pItem)
351 *pItem = m_bandStack[m_bandCount];
352
353 return S_OK;
354 }
355
356 HRESULT PeekArray(CMenuBand ** pItem)
357 {
358 if (!pItem)
359 return E_FAIL;
360
361 *pItem = NULL;
362
363 if (m_bandCount <= 0)
364 return E_FAIL;
365
366 *pItem = m_bandStack[m_bandCount - 1];
367
368 return S_OK;
369 }
370
371 protected:
372 CMenuFocusManager() :
373 m_currentBand(NULL),
374 m_currentFocus(NULL),
375 m_bandCount(0)
376 {
377 m_threadId = GetCurrentThreadId();
378 }
379
380 ~CMenuFocusManager()
381 {
382 }
383
384 public:
385
386 DECLARE_NOT_AGGREGATABLE(CMenuFocusManager)
387 DECLARE_PROTECT_FINAL_CONSTRUCT()
388 BEGIN_COM_MAP(CMenuFocusManager)
389 END_COM_MAP()
390
391 private:
392 CMenuBand * m_currentBand;
393 HWND m_currentFocus;
394 HHOOK m_hHook;
395 DWORD m_threadId;
396
397 LRESULT GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
398 {
399 if (nCode < 0)
400 return CallNextHookEx(m_hHook, nCode, wParam, lParam);
401
402 BOOL callNext = TRUE;
403 BOOL fRemoved = wParam;
404 MSG* msg = reinterpret_cast<MSG*>(lParam);
405
406 if (nCode == HC_ACTION)
407 {
408 // Do whatever is necessary here
409
410 switch (msg->message)
411 {
412 case WM_CLOSE:
413 break;
414 case WM_SYSKEYDOWN:
415 case WM_KEYDOWN:
416 switch (msg->wParam)
417 {
418 case VK_MENU:
419 case VK_LMENU:
420 case VK_RMENU:
421 m_currentBand->OnSelect(MPOS_FULLCANCEL);
422 break;
423 case VK_LEFT:
424 m_currentBand->OnSelect(MPOS_SELECTLEFT);
425 break;
426 case VK_RIGHT:
427 m_currentBand->OnSelect(MPOS_SELECTRIGHT);
428 break;
429 case VK_UP:
430 //m_currentBand->ChildTrack(VK_UP);
431 break;
432 case VK_DOWN:
433 //m_currentBand->ChildTrack(VK_DOWN);
434 break;
435 }
436 break;
437 case WM_CHAR:
438 //if (msg->wParam >= 'a' && msg->wParam <= 'z')
439 //{
440 // callNext = FALSE;
441 // PostMessage(m_currentFocus, WM_SYSCHAR, wParam, lParam);
442 //}
443 break;
444 case WM_ACTIVATE:
445 break;
446
447 }
448
449 if (!callNext)
450 return 0;
451 }
452
453 return CallNextHookEx(m_hHook, nCode, wParam, lParam);
454 }
455
456 HRESULT PlaceHooks(HWND window)
457 {
458 //SetCapture(window);
459 m_hHook = SetWindowsHookEx(WH_GETMESSAGE, s_GetMsgHook, NULL, m_threadId);
460 return S_OK;
461 }
462
463 HRESULT RemoveHooks(HWND window)
464 {
465 UnhookWindowsHookEx(m_hHook);
466 //ReleaseCapture();
467 return S_OK;
468 }
469
470 HRESULT UpdateFocus(CMenuBand * newBand)
471 {
472 HRESULT hr;
473
474 hr = RemoveHooks(m_currentFocus);
475
476 if (FAILED(hr) || !newBand)
477 {
478 m_currentFocus = NULL;
479 m_currentBand = NULL;
480 return S_OK;
481 }
482
483 HWND newFocus;
484 hr = newBand->GetTopLevelWindow(&newFocus);
485 if (FAILED(hr))
486 return hr;
487
488 hr = PlaceHooks(m_currentFocus);
489 if (FAILED(hr))
490 return hr;
491
492 m_currentFocus = newFocus;
493 m_currentBand = newBand;
494
495 return S_OK;
496 }
497
498 public:
499 HRESULT PushMenu(CMenuBand * mb)
500 {
501 HRESULT hr;
502
503 hr = PushToArray(mb);
504 if (FAILED(hr))
505 return hr;
506
507 return UpdateFocus(mb);
508 }
509
510 HRESULT PopMenu(CMenuBand * mb)
511 {
512 CMenuBand * mbc;
513 HRESULT hr;
514
515 hr = PopFromArray(&mbc);
516 if (FAILED(hr))
517 return hr;
518
519 if (mb != mbc)
520 return E_FAIL;
521
522 hr = PeekArray(&mbc);
523
524 return UpdateFocus(mbc);
525 }
526 };
527
528 DWORD CMenuFocusManager::TlsIndex = 0;
529
530 extern "C"
531 HRESULT CMenuBand_Constructor(REFIID riid, LPVOID *ppv)
532 {
533 *ppv = NULL;
534
535 CMenuBand * site = new CComObject<CMenuBand>();
536
537 if (!site)
538 return E_OUTOFMEMORY;
539
540 HRESULT hr = site->QueryInterface(riid, ppv);
541
542 if (FAILED(hr))
543 site->Release();
544
545 return hr;
546 }
547
548 CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand) :
549 m_menuBand(menuBand),
550 m_hwnd(NULL),
551 m_dwMenuFlags(0)
552 {
553 }
554
555 HRESULT CMenuToolbarBase::ShowWindow(BOOL fShow)
556 {
557 ::ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
558
559 HIMAGELIST ilBig, ilSmall;
560 Shell_GetImageLists(&ilBig, &ilSmall);
561
562 if (m_menuBand->UseBigIcons())
563 {
564 SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(ilBig));
565 }
566 else
567 {
568 SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(ilSmall));
569 }
570
571 return S_OK;
572 }
573
574 HRESULT CMenuToolbarBase::Close()
575 {
576 DestroyWindow(m_hwnd);
577 m_hwnd = NULL;
578 return S_OK;
579 }
580
581 HRESULT CMenuToolbarBase::CreateToolbar(HWND hwndParent, DWORD dwFlags)
582 {
583 LONG tbStyles = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
584 TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT | TBSTYLE_CUSTOMERASE |
585 CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP;
586 LONG tbExStyles = TBSTYLE_EX_DOUBLEBUFFER;
587
588 if (dwFlags & SMINIT_VERTICAL)
589 {
590 tbStyles |= CCS_VERT;
591 tbExStyles |= TBSTYLE_EX_VERTICAL | WS_EX_TOOLWINDOW;
592 }
593
594 RECT rc;
595
596 if (!::GetClientRect(hwndParent, &rc) || (rc.left == rc.right) || (rc.top == rc.bottom))
597 {
598 rc.left = 0;
599 rc.top = 0;
600 rc.right = 1;
601 rc.bottom = 1;
602 }
603
604 HWND hwndToolbar = CreateWindowEx(
605 tbExStyles, TOOLBARCLASSNAMEW, NULL,
606 tbStyles, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
607 hwndParent, NULL, _AtlBaseModule.GetModuleInstance(), 0);
608
609 if (hwndToolbar == NULL)
610 return E_FAIL;
611
612 ::SetParent(hwndToolbar, hwndParent);
613
614 m_hwnd = hwndToolbar;
615
616 /* Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure */
617 SendMessageW(m_hwnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
618
619 HIMAGELIST ilBig, ilSmall;
620 Shell_GetImageLists(&ilBig, &ilSmall);
621
622 //if (dwFlags & SMINIT_TOPLEVEL)
623 //{
624 // /* Hide the placeholders for the button images */
625 // SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0);
626 //}
627 //else
628 if (m_menuBand->UseBigIcons())
629 {
630 SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(ilBig));
631 }
632 else
633 {
634 SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(ilSmall));
635 }
636
637 SetWindowLongPtr(m_hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
638 m_SubclassOld = (WNDPROC) SetWindowLongPtr(m_hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(CMenuToolbarBase::s_SubclassProc));
639
640 return S_OK;
641 }
642
643 HRESULT CMenuToolbarBase::GetWindow(HWND *phwnd)
644 {
645 if (!phwnd)
646 return E_FAIL;
647
648 *phwnd = m_hwnd;
649
650 return S_OK;
651 }
652
653 LRESULT CALLBACK CMenuToolbarBase::s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
654 {
655 CMenuToolbarBase * pthis = reinterpret_cast<CMenuToolbarBase *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
656 return pthis->SubclassProc(hWnd, uMsg, wParam, lParam);
657 }
658
659 LRESULT CMenuToolbarBase::SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
660 {
661 switch (uMsg)
662 {
663 case WM_TIMER:
664 if (wParam == TIMERID_HOTTRACK)
665 {
666 PopupItem(m_hotItem);
667 KillTimer(hWnd, TIMERID_HOTTRACK);
668 }
669 }
670
671 return m_SubclassOld(hWnd, uMsg, wParam, lParam);
672 }
673
674 HRESULT CMenuToolbarBase::OnHotItemChange(const NMTBHOTITEM * hot)
675 {
676 if (hot->dwFlags & HICF_LEAVING)
677 {
678 KillTimer(m_hwnd, TIMERID_HOTTRACK);
679 }
680 else if (m_hotItem != hot->idNew)
681 {
682 if (HasSubMenu(hot->idNew) == S_OK)
683 {
684 DWORD elapsed = 0;
685 SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0);
686
687 m_hotItem = hot->idNew;
688
689 SetTimer(m_hwnd, TIMERID_HOTTRACK, elapsed, NULL);
690 }
691 }
692
693 m_menuBand->OnSelect(MPOS_CHILDTRACKING);
694 return S_OK;
695 }
696
697 HRESULT CMenuToolbarBase::PopupSubMenu(UINT index, IShellMenu* childShellMenu)
698 {
699 IBandSite* pBandSite;
700 IDeskBar* pDeskBar;
701
702 HRESULT hr = 0;
703 RECT rc = { 0 };
704
705 if (!SendMessage(m_hwnd, TB_GETITEMRECT, index, reinterpret_cast<LPARAM>(&rc)))
706 return E_FAIL;
707
708 POINT a = { rc.left, rc.top };
709 POINT b = { rc.right, rc.bottom };
710
711 ClientToScreen(m_hwnd, &a);
712 ClientToScreen(m_hwnd, &b);
713
714 POINTL pt = { b.x, b.y };
715 RECTL rcl = { a.x, a.y, b.x, b.y }; // maybe-TODO: fetch client area of deskbar?
716
717
718 #if USE_SYSTEM_MENUSITE
719 hr = CoCreateInstance(CLSID_MenuBandSite,
720 NULL,
721 CLSCTX_INPROC_SERVER,
722 IID_PPV_ARG(IBandSite, &pBandSite));
723 #else
724 hr = CMenuSite_Constructor(IID_PPV_ARG(IBandSite, &pBandSite));
725 #endif
726 if (FAILED(hr))
727 return hr;
728 #if WRAP_MENUSITE
729 hr = CMenuSite_Wrapper(pBandSite, IID_PPV_ARG(IBandSite, &pBandSite));
730 if (FAILED(hr))
731 return hr;
732 #endif
733
734 #if USE_SYSTEM_MENUDESKBAR
735 hr = CoCreateInstance(CLSID_MenuDeskBar,
736 NULL,
737 CLSCTX_INPROC_SERVER,
738 IID_PPV_ARG(IDeskBar, &pDeskBar));
739 #else
740 hr = CMenuDeskBar_Constructor(IID_PPV_ARG(IDeskBar, &pDeskBar));
741 #endif
742 if (FAILED(hr))
743 return hr;
744 #if WRAP_MENUDESKBAR
745 hr = CMenuDeskBar_Wrapper(pDeskBar, IID_PPV_ARG(IDeskBar, &pDeskBar));
746 if (FAILED(hr))
747 return hr;
748 #endif
749
750 hr = pDeskBar->SetClient(pBandSite);
751 if (FAILED(hr))
752 return hr;
753
754 hr = pBandSite->AddBand(childShellMenu);
755 if (FAILED(hr))
756 return hr;
757
758 CComPtr<IMenuPopup> popup;
759 hr = pDeskBar->QueryInterface(IID_PPV_ARG(IMenuPopup, &popup));
760 if (FAILED(hr))
761 return hr;
762
763 popup->Popup(&pt, &rcl, MPPF_TOP | MPPF_RIGHT);
764
765 return S_OK;
766 }
767
768 HRESULT CMenuToolbarBase::PopupSubMenu(UINT index, HMENU menu)
769 {
770 RECT rc = { 0 };
771
772 if (!SendMessage(m_hwnd, TB_GETITEMRECT, index, reinterpret_cast<LPARAM>(&rc)))
773 return E_FAIL;
774
775 POINT b = { rc.right, rc.bottom };
776
777 ClientToScreen(m_hwnd, &b);
778
779 HMENU popup = GetSubMenu(menu, index);
780
781 m_menuBand->TrackPopup(popup, b.x, b.y);
782
783 return S_OK;
784 }
785
786 HRESULT CMenuToolbarBase::DoContextMenu(IContextMenu* contextMenu)
787 {
788 HRESULT hr;
789 HMENU hPopup = CreatePopupMenu();
790
791 if (hPopup == NULL)
792 return E_FAIL;
793
794 hr = contextMenu->QueryContextMenu(hPopup, 0, 0, UINT_MAX, CMF_NORMAL);
795 if (FAILED(hr))
796 {
797 DestroyMenu(hPopup);
798 return hr;
799 }
800
801 DWORD dwPos = GetMessagePos();
802 UINT uCommand = ::TrackPopupMenu(hPopup, TPM_RETURNCMD, GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos), 0, m_hwnd, NULL);
803 if (uCommand == 0)
804 return S_FALSE;
805
806 CMINVOKECOMMANDINFO cmi = { 0 };
807 cmi.cbSize = sizeof(cmi);
808 cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
809 cmi.hwnd = m_hwnd;
810 hr = contextMenu->InvokeCommand(&cmi);
811
812 DestroyMenu(hPopup);
813 return hr;
814 }
815
816 HRESULT CMenuToolbarBase::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
817 {
818 m_menuBand->OnSelect(MPOS_EXECUTE);
819 return S_OK;
820 }
821
822 BOOL
823 AllocAndGetMenuString(HMENU hMenu, UINT ItemIDByPosition, WCHAR** String)
824 {
825 int Length;
826
827 Length = GetMenuStringW(hMenu, ItemIDByPosition, NULL, 0, MF_BYPOSITION);
828
829 if (!Length)
830 return FALSE;
831
832 /* Also allocate space for the terminating NULL character */
833 ++Length;
834 *String = (PWSTR) HeapAlloc(GetProcessHeap(), 0, Length * sizeof(WCHAR));
835
836 GetMenuStringW(hMenu, ItemIDByPosition, *String, Length, MF_BYPOSITION);
837
838 return TRUE;
839 }
840
841 CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand *menuBand) :
842 CMenuToolbarBase(menuBand),
843 m_hmenu(NULL)
844 {
845 }
846
847 HRESULT CMenuStaticToolbar::GetMenu(
848 HMENU *phmenu,
849 HWND *phwnd,
850 DWORD *pdwFlags)
851 {
852 *phmenu = m_hmenu;
853 *phwnd = NULL;
854 *pdwFlags = m_dwMenuFlags;
855
856 return S_OK;
857 }
858
859 HRESULT CMenuStaticToolbar::SetMenu(
860 HMENU hmenu,
861 HWND hwnd,
862 DWORD dwFlags)
863 {
864 m_hmenu = hmenu;
865 m_dwMenuFlags = dwFlags;
866
867 return S_OK;
868 }
869
870 HRESULT CMenuStaticToolbar::FillToolbar()
871 {
872 int i;
873 int ic = GetMenuItemCount(m_hmenu);
874
875 for (i = 0; i < ic; i++)
876 {
877 MENUITEMINFOW info;
878 TBBUTTON tbb = { 0 };
879 PWSTR MenuString = NULL;
880
881 tbb.fsState = TBSTATE_ENABLED;
882 tbb.fsStyle = 0;
883
884 info.cbSize = sizeof(info);
885 info.fMask = MIIM_FTYPE | MIIM_ID;
886
887 GetMenuItemInfoW(m_hmenu, i, TRUE, &info);
888
889 if (info.fType == MFT_STRING)
890 {
891 if (!AllocAndGetMenuString(m_hmenu, i, &MenuString))
892 return E_OUTOFMEMORY;
893 if (::GetSubMenu(m_hmenu, i) != NULL)
894 tbb.fsStyle |= BTNS_DROPDOWN;
895 tbb.iString = (INT_PTR) MenuString;
896 tbb.idCommand = info.wID;
897
898 SMINFO * sminfo = new SMINFO();
899 sminfo->dwMask = SMIM_ICON | SMIM_FLAGS;
900 if (SUCCEEDED(m_menuBand->CallCBWithId(info.wID, SMC_GETINFO, 0, reinterpret_cast<LPARAM>(sminfo))))
901 {
902 tbb.iBitmap = sminfo->iIcon;
903 tbb.dwData = reinterpret_cast<DWORD_PTR>(sminfo);
904 // FIXME: remove before deleting the toolbar or it will leak
905 }
906 }
907 else
908 {
909 tbb.fsStyle |= BTNS_SEP;
910 }
911
912 SendMessageW(m_hwnd, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
913
914 if (MenuString)
915 HeapFree(GetProcessHeap(), 0, MenuString);
916 }
917
918 return S_OK;
919 }
920
921 HRESULT CMenuStaticToolbar::OnContextMenu(NMMOUSE * rclick)
922 {
923 CComPtr<IContextMenu> contextMenu;
924 HRESULT hr = m_menuBand->CallCBWithId(rclick->dwItemSpec, SMC_GETOBJECT, reinterpret_cast<WPARAM>(&IID_IContextMenu), reinterpret_cast<LPARAM>(&contextMenu));
925 if (hr != S_OK)
926 return hr;
927
928 return DoContextMenu(contextMenu);
929 }
930
931 HRESULT CMenuStaticToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
932 {
933 HRESULT hr = m_menuBand->CallCBWithId(wParam, SMC_EXEC, 0, 0);
934 if (FAILED(hr))
935 return hr;
936
937 return CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
938 }
939
940 HRESULT CMenuStaticToolbar::PopupItem(UINT uItem)
941 {
942 TBBUTTONINFO info = { 0 };
943 info.cbSize = sizeof(TBBUTTONINFO);
944 info.dwMask = 0;
945 int index = SendMessage(m_hwnd, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
946 if (index < 0)
947 return E_FAIL;
948
949 TBBUTTON btn = { 0 };
950 SendMessage(m_hwnd, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn));
951
952 SMINFO * nfo = reinterpret_cast<SMINFO*>(btn.dwData);
953 if (!nfo)
954 return E_FAIL;
955
956 if (nfo->dwFlags&SMIF_TRACKPOPUP)
957 {
958 return PopupSubMenu(index, m_hmenu);
959 }
960 else
961 {
962 CComPtr<IShellMenu> shellMenu;
963 HRESULT hr = m_menuBand->CallCBWithId(uItem, SMC_GETOBJECT, reinterpret_cast<WPARAM>(&IID_IShellMenu), reinterpret_cast<LPARAM>(&shellMenu));
964 if (FAILED(hr))
965 return hr;
966
967 return PopupSubMenu(index, shellMenu);
968 }
969 }
970
971 HRESULT CMenuStaticToolbar::HasSubMenu(UINT uItem)
972 {
973 TBBUTTONINFO info = { 0 };
974 info.cbSize = sizeof(TBBUTTONINFO);
975 info.dwMask = 0;
976 int index = SendMessage(m_hwnd, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
977 if (index < 0)
978 return E_FAIL;
979 return ::GetSubMenu(m_hmenu, index) ? S_OK : S_FALSE;
980 }
981
982 CMenuSFToolbar::CMenuSFToolbar(CMenuBand * menuBand) :
983 CMenuToolbarBase(menuBand),
984 m_shellFolder(NULL)
985 {
986 }
987
988 CMenuSFToolbar::~CMenuSFToolbar()
989 {
990 }
991
992 HRESULT CMenuSFToolbar::FillToolbar()
993 {
994 HRESULT hr;
995 TBBUTTON tbb = { 0 };
996 int i = 0;
997 PWSTR MenuString;
998
999 tbb.fsState = TBSTATE_ENABLED;
1000 tbb.fsStyle = 0;
1001
1002 IEnumIDList * eidl;
1003 m_shellFolder->EnumObjects(m_hwnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &eidl);
1004
1005 LPITEMIDLIST item = static_cast<LPITEMIDLIST>(CoTaskMemAlloc(sizeof(ITEMIDLIST)));
1006 ULONG fetched;
1007 while ((hr = eidl->Next(1, &item, &fetched)) == S_OK)
1008 {
1009 INT index = 0;
1010 INT indexOpen = 0;
1011
1012 CComPtr<IShellItem> psi;
1013 SHCreateShellItem(NULL, m_shellFolder, item, &psi);
1014
1015 hr = psi->GetDisplayName(SIGDN_NORMALDISPLAY, &MenuString);
1016 if (FAILED(hr))
1017 return hr;
1018
1019 index = SHMapPIDLToSystemImageListIndex(m_shellFolder, item, &indexOpen);
1020
1021 SFGAOF attrs;
1022 hr = psi->GetAttributes(SFGAO_FOLDER, &attrs);
1023
1024 if (attrs != 0)
1025 {
1026 tbb.fsStyle |= BTNS_DROPDOWN;
1027 }
1028
1029 tbb.idCommand = i++;
1030 tbb.iString = (INT_PTR) MenuString;
1031 tbb.iBitmap = index;
1032 tbb.dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
1033 // FIXME: remove before deleting the toolbar or it will leak
1034
1035 SendMessageW(m_hwnd, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
1036 HeapFree(GetProcessHeap(), 0, MenuString);
1037
1038 }
1039 CoTaskMemFree(item);
1040
1041 return hr;
1042 }
1043
1044 HRESULT CMenuSFToolbar::SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags)
1045 {
1046 m_shellFolder = psf;
1047 m_idList = pidlFolder;
1048 m_hKey = hKey;
1049 m_dwMenuFlags = dwFlags;
1050 return S_OK;
1051 }
1052
1053 HRESULT CMenuSFToolbar::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv)
1054 {
1055 HRESULT hr;
1056
1057 hr = m_shellFolder->QueryInterface(riid, ppv);
1058 if (FAILED(hr))
1059 return hr;
1060
1061 if (pdwFlags)
1062 *pdwFlags = m_dwMenuFlags;
1063
1064 if (ppidl)
1065 {
1066 LPITEMIDLIST pidl = NULL;
1067
1068 if (m_idList)
1069 {
1070 pidl = ILClone(m_idList);
1071 if (!pidl)
1072 {
1073 (*(IUnknown**) ppv)->Release();
1074 return E_FAIL;
1075 }
1076 }
1077
1078 *ppidl = pidl;
1079 }
1080
1081 return hr;
1082 }
1083
1084 LPITEMIDLIST CMenuSFToolbar::GetPidlFromId(UINT uItem, INT* pIndex)
1085 {
1086 TBBUTTONINFO info = { 0 };
1087 info.cbSize = sizeof(TBBUTTONINFO);
1088 info.dwMask = 0;
1089 int index = SendMessage(m_hwnd, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
1090 if (index < 0)
1091 return NULL;
1092
1093 if (pIndex)
1094 *pIndex = index;
1095
1096 TBBUTTON btn = { 0 };
1097 if (!SendMessage(m_hwnd, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn)))
1098 return NULL;
1099
1100 return reinterpret_cast<LPITEMIDLIST>(btn.dwData);
1101 }
1102
1103 HRESULT CMenuSFToolbar::OnContextMenu(NMMOUSE * rclick)
1104 {
1105 HRESULT hr;
1106 CComPtr<IContextMenu> contextMenu;
1107 LPCITEMIDLIST pidl = reinterpret_cast<LPCITEMIDLIST>(rclick->dwItemData);
1108
1109 hr = m_shellFolder->GetUIObjectOf(m_hwnd, 1, &pidl, IID_IContextMenu, NULL, reinterpret_cast<VOID **>(&contextMenu));
1110 if (hr != S_OK)
1111 return hr;
1112
1113 return DoContextMenu(contextMenu);
1114 }
1115
1116 HRESULT CMenuSFToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
1117 {
1118 return m_menuBand->CallCBWithPidl(GetPidlFromId(wParam, NULL), SMC_SFEXEC, 0, 0);
1119 }
1120
1121 HRESULT CMenuSFToolbar::PopupItem(UINT uItem)
1122 {
1123 HRESULT hr;
1124 UINT uId;
1125 UINT uIdAncestor;
1126 DWORD flags;
1127 int index;
1128 CComPtr<IShellMenuCallback> psmc;
1129 CComPtr<IShellMenu> shellMenu;
1130
1131 LPITEMIDLIST pidl = GetPidlFromId(uItem, &index);
1132
1133 if (!pidl)
1134 return E_FAIL;
1135
1136 #if USE_SYSTEM_MENUBAND
1137 hr = CoCreateInstance(CLSID_MenuBand,
1138 NULL,
1139 CLSCTX_INPROC_SERVER,
1140 IID_PPV_ARG(IShellMenu, &shellMenu));
1141 #else
1142 hr = CMenuBand_Constructor(IID_PPV_ARG(IShellMenu, &shellMenu));
1143 #endif
1144 if (FAILED(hr))
1145 return hr;
1146 #if WRAP_MENUBAND
1147 hr = CMenuBand_Wrapper(shellMenu, IID_PPV_ARG(IShellMenu, &shellMenu));
1148 if (FAILED(hr))
1149 return hr;
1150 #endif
1151
1152 m_menuBand->GetMenuInfo(&psmc, &uId, &uIdAncestor, &flags);
1153
1154 // FIXME: not sure waht to use as uId/uIdAncestor here
1155 hr = shellMenu->Initialize(psmc, 0, uId, SMINIT_VERTICAL);
1156 if (FAILED(hr))
1157 return hr;
1158
1159 CComPtr<IShellFolder> childFolder;
1160 hr = m_shellFolder->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &childFolder));
1161 if (FAILED(hr))
1162 return hr;
1163
1164 hr = shellMenu->SetShellFolder(childFolder, NULL, NULL, 0);
1165 if (FAILED(hr))
1166 return hr;
1167
1168 return PopupSubMenu(index, shellMenu);
1169 }
1170
1171 HRESULT CMenuSFToolbar::HasSubMenu(UINT uItem)
1172 {
1173 HRESULT hr;
1174 CComPtr<IShellItem> psi;
1175 SHCreateShellItem(NULL, m_shellFolder, GetPidlFromId(uItem, NULL), &psi);
1176
1177 SFGAOF attrs;
1178 hr = psi->GetAttributes(SFGAO_FOLDER, &attrs);
1179 if (FAILED(hr))
1180 return hr;
1181
1182 return (attrs != 0) ? S_OK : S_FALSE;
1183 }
1184
1185 CMenuBand::CMenuBand() :
1186 m_site(NULL),
1187 m_psmc(NULL),
1188 m_staticToolbar(NULL),
1189 m_SFToolbar(NULL),
1190 m_useBigIcons(FALSE)
1191 {
1192 m_focusManager = CMenuFocusManager::AcquireManager();
1193 }
1194
1195 CMenuBand::~CMenuBand()
1196 {
1197 CMenuFocusManager::ReleaseManager(m_focusManager);
1198
1199 if (m_site)
1200 m_site->Release();
1201
1202 if (m_psmc)
1203 m_psmc->Release();
1204
1205 if (m_staticToolbar)
1206 delete m_staticToolbar;
1207
1208 if (m_SFToolbar)
1209 delete m_SFToolbar;
1210 }
1211
1212 HRESULT STDMETHODCALLTYPE CMenuBand::Initialize(
1213 IShellMenuCallback *psmc,
1214 UINT uId,
1215 UINT uIdAncestor,
1216 DWORD dwFlags)
1217 {
1218 if (m_psmc)
1219 m_psmc->Release();
1220
1221 m_psmc = psmc;
1222 m_uId = uId;
1223 m_uIdAncestor = uIdAncestor;
1224 m_dwFlags = dwFlags;
1225
1226 if (m_psmc)
1227 {
1228 m_psmc->AddRef();
1229
1230 _CallCB(SMC_CREATE, 0, reinterpret_cast<LPARAM>(&m_UserData));
1231 }
1232
1233 return S_OK;
1234 }
1235
1236 HRESULT STDMETHODCALLTYPE CMenuBand::GetMenuInfo(
1237 IShellMenuCallback **ppsmc,
1238 UINT *puId,
1239 UINT *puIdAncestor,
1240 DWORD *pdwFlags)
1241 {
1242 if (!pdwFlags) // maybe?
1243 return E_INVALIDARG;
1244
1245 if (ppsmc)
1246 *ppsmc = m_psmc;
1247
1248 if (puId)
1249 *puId = m_uId;
1250
1251 if (puIdAncestor)
1252 *puIdAncestor = m_uIdAncestor;
1253
1254 *pdwFlags = m_dwFlags;
1255
1256 return S_OK;
1257 }
1258
1259 HRESULT STDMETHODCALLTYPE CMenuBand::SetMenu(
1260 HMENU hmenu,
1261 HWND hwnd,
1262 DWORD dwFlags)
1263 {
1264 if (m_staticToolbar == NULL)
1265 {
1266 m_staticToolbar = new CMenuStaticToolbar(this);
1267 }
1268 m_hmenu = hmenu;
1269 m_menuOwner;
1270
1271 HRESULT hr = m_staticToolbar->SetMenu(hmenu, hwnd, dwFlags);
1272 if (FAILED(hr))
1273 return hr;
1274
1275 if (m_site)
1276 {
1277 HWND hwndParent;
1278
1279 hr = m_site->GetWindow(&hwndParent);
1280 if (FAILED(hr))
1281 return hr;
1282
1283 hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
1284 if (FAILED(hr))
1285 return hr;
1286
1287 hr = m_staticToolbar->FillToolbar();
1288 }
1289
1290 return hr;
1291 }
1292
1293 HRESULT STDMETHODCALLTYPE CMenuBand::GetMenu(
1294 HMENU *phmenu,
1295 HWND *phwnd,
1296 DWORD *pdwFlags)
1297 {
1298 if (m_staticToolbar == NULL)
1299 return E_FAIL;
1300
1301 return m_staticToolbar->GetMenu(phmenu, phwnd, pdwFlags);
1302 }
1303
1304 HRESULT STDMETHODCALLTYPE CMenuBand::SetSite(IUnknown *pUnkSite)
1305 {
1306 HWND hwndParent;
1307 HRESULT hr;
1308
1309 if (m_site != NULL)
1310 m_site->Release();
1311
1312 if (pUnkSite == NULL)
1313 return S_OK;
1314
1315 hwndParent = NULL;
1316 hr = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &m_site));
1317 if (SUCCEEDED(hr))
1318 {
1319 m_site->Release();
1320
1321 hr = m_site->GetWindow(&hwndParent);
1322 if (FAILED(hr))
1323 return hr;
1324 }
1325
1326 if (!::IsWindow(hwndParent))
1327 return E_FAIL;
1328
1329 if (m_staticToolbar != NULL)
1330 {
1331 hr = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
1332 if (FAILED(hr))
1333 return hr;
1334
1335 hr = m_staticToolbar->FillToolbar();
1336 if (FAILED(hr))
1337 return hr;
1338 }
1339
1340 if (m_SFToolbar != NULL)
1341 {
1342 hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
1343 if (FAILED(hr))
1344 return hr;
1345
1346 hr = m_SFToolbar->FillToolbar();
1347 if (FAILED(hr))
1348 return hr;
1349 }
1350
1351 CComPtr<IOleWindow> pTopLevelWindow;
1352 hr = IUnknown_QueryService(m_site, SID_STopLevelBrowser, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
1353 if (FAILED(hr))
1354 return hr;
1355
1356 return pTopLevelWindow->GetWindow(&m_topLevelWindow);
1357 }
1358
1359 HRESULT STDMETHODCALLTYPE CMenuBand::GetSite(REFIID riid, PVOID *ppvSite)
1360 {
1361 if (m_site == NULL)
1362 return E_FAIL;
1363
1364 return m_site->QueryInterface(riid, ppvSite);
1365 }
1366
1367 HRESULT STDMETHODCALLTYPE CMenuBand::GetWindow(
1368 HWND *phwnd)
1369 {
1370 if (m_SFToolbar != NULL)
1371 return m_SFToolbar->GetWindow(phwnd);
1372
1373 if (m_staticToolbar != NULL)
1374 return m_staticToolbar->GetWindow(phwnd);
1375
1376 return E_FAIL;
1377 }
1378
1379 HRESULT STDMETHODCALLTYPE CMenuBand::OnPosRectChangeDB(RECT *prc)
1380 {
1381 SIZE sizeStaticY = { 0 };
1382 SIZE sizeShlFldY = { 0 };
1383 HWND hwndStatic = NULL;
1384 HWND hwndShlFld = NULL;
1385 HRESULT hr = S_OK;
1386
1387 if (m_staticToolbar != NULL)
1388 hr = m_staticToolbar->GetWindow(&hwndStatic);
1389 if (FAILED(hr))
1390 return hr;
1391
1392 if (m_SFToolbar != NULL)
1393 hr = m_SFToolbar->GetWindow(&hwndShlFld);
1394 if (FAILED(hr))
1395 return hr;
1396
1397 if (hwndStatic == NULL && hwndShlFld == NULL)
1398 return E_FAIL;
1399
1400 if (hwndStatic) SendMessageW(hwndStatic, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeStaticY));
1401 if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeShlFldY));
1402
1403 int sy = max(prc->bottom - prc->top, sizeStaticY.cy + sizeShlFldY.cy);
1404
1405 if (hwndShlFld)
1406 {
1407 SetWindowPos(hwndShlFld, NULL,
1408 prc->left,
1409 prc->top,
1410 prc->right - prc->left,
1411 sizeShlFldY.cy,
1412 0);
1413 DWORD btnSize = SendMessage(hwndShlFld, TB_GETBUTTONSIZE, 0, 0);
1414 SendMessage(hwndShlFld, TB_SETBUTTONSIZE, 0, MAKELPARAM(prc->right - prc->left, HIWORD(btnSize)));
1415 }
1416 if (hwndStatic)
1417 {
1418 SetWindowPos(hwndStatic, hwndShlFld,
1419 prc->left,
1420 prc->top + sizeShlFldY.cy,
1421 prc->right - prc->left,
1422 sy - sizeShlFldY.cy,
1423 0);
1424 DWORD btnSize = SendMessage(hwndStatic, TB_GETBUTTONSIZE, 0, 0);
1425 SendMessage(hwndStatic, TB_SETBUTTONSIZE, 0, MAKELPARAM(prc->right - prc->left, HIWORD(btnSize)));
1426 }
1427
1428 return S_OK;
1429 }
1430
1431 HRESULT STDMETHODCALLTYPE CMenuBand::GetBandInfo(
1432 DWORD dwBandID,
1433 DWORD dwViewMode,
1434 DESKBANDINFO *pdbi)
1435 {
1436 HWND hwndStatic = NULL;
1437 HWND hwndShlFld = NULL;
1438 HRESULT hr = S_OK;
1439
1440 if (m_staticToolbar != NULL)
1441 hr = m_staticToolbar->GetWindow(&hwndStatic);
1442 if (FAILED(hr))
1443 return hr;
1444
1445 if (m_SFToolbar != NULL)
1446 hr = m_SFToolbar->GetWindow(&hwndShlFld);
1447 if (FAILED(hr))
1448 return hr;
1449
1450 if (hwndStatic == NULL && hwndShlFld == NULL)
1451 return E_FAIL;
1452
1453 // HACK (?)
1454 if (pdbi->dwMask == 0)
1455 {
1456 pdbi->dwMask = DBIM_MINSIZE | DBIM_MAXSIZE | DBIM_INTEGRAL | DBIM_ACTUAL | DBIM_TITLE | DBIM_MODEFLAGS | DBIM_BKCOLOR;
1457 }
1458
1459 if (pdbi->dwMask & DBIM_MINSIZE)
1460 {
1461 SIZE sizeStatic = { 0 };
1462 SIZE sizeShlFld = { 0 };
1463
1464 if (hwndStatic) SendMessageW(hwndStatic, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeStatic));
1465 if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeShlFld));
1466
1467 pdbi->ptMinSize.x = 0;
1468 pdbi->ptMinSize.y = sizeStatic.cy + sizeShlFld.cy;
1469 }
1470 if (pdbi->dwMask & DBIM_MAXSIZE)
1471 {
1472 SIZE sizeStatic = { 0 };
1473 SIZE sizeShlFld = { 0 };
1474
1475 if (hwndStatic) SendMessageW(hwndStatic, TB_GETMAXSIZE, 0, reinterpret_cast<LPARAM>(&sizeStatic));
1476 if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETMAXSIZE, 0, reinterpret_cast<LPARAM>(&sizeShlFld));
1477
1478 pdbi->ptMaxSize.x = max(sizeStatic.cx, sizeShlFld.cx); // ignored
1479 pdbi->ptMaxSize.y = sizeStatic.cy + sizeShlFld.cy;
1480 }
1481 if (pdbi->dwMask & DBIM_INTEGRAL)
1482 {
1483 pdbi->ptIntegral.x = 0;
1484 pdbi->ptIntegral.y = 0;
1485 }
1486 if (pdbi->dwMask & DBIM_ACTUAL)
1487 {
1488 SIZE sizeStatic = { 0 };
1489 SIZE sizeShlFld = { 0 };
1490
1491 if (hwndStatic) SendMessageW(hwndStatic, TB_GETIDEALSIZE, FALSE, reinterpret_cast<LPARAM>(&sizeStatic));
1492 if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETIDEALSIZE, FALSE, reinterpret_cast<LPARAM>(&sizeShlFld));
1493 pdbi->ptActual.x = max(sizeStatic.cx, sizeShlFld.cx);
1494
1495 if (hwndStatic) SendMessageW(hwndStatic, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeStatic));
1496 if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeShlFld));
1497 pdbi->ptActual.y = sizeStatic.cy + sizeShlFld.cy;
1498 }
1499 if (pdbi->dwMask & DBIM_TITLE)
1500 wcscpy(pdbi->wszTitle, L"");
1501 if (pdbi->dwMask & DBIM_MODEFLAGS)
1502 pdbi->dwModeFlags = DBIMF_UNDELETEABLE;
1503 if (pdbi->dwMask & DBIM_BKCOLOR)
1504 pdbi->crBkgnd = 0;
1505 return S_OK;
1506 }
1507
1508 /* IDockingWindow */
1509 HRESULT STDMETHODCALLTYPE CMenuBand::ShowDW(BOOL fShow)
1510 {
1511 HRESULT hr = S_OK;
1512
1513 if (m_staticToolbar != NULL)
1514 hr = m_staticToolbar->ShowWindow(fShow);
1515 if (FAILED(hr))
1516 return hr;
1517 if (m_SFToolbar != NULL)
1518 hr = m_SFToolbar->ShowWindow(fShow);
1519 if (FAILED(hr))
1520 return hr;
1521
1522 if (fShow)
1523 {
1524 hr = _CallCB(SMC_INITMENU, 0, 0);
1525 if (FAILED(hr))
1526 return hr;
1527 }
1528
1529 if (fShow)
1530 hr = m_focusManager->PushMenu(this);
1531 else
1532 hr = m_focusManager->PopMenu(this);
1533
1534 return hr;
1535 }
1536
1537 HRESULT STDMETHODCALLTYPE CMenuBand::CloseDW(DWORD dwReserved)
1538 {
1539 ShowDW(FALSE);
1540
1541 if (m_staticToolbar != NULL)
1542 return m_staticToolbar->Close();
1543
1544 if (m_SFToolbar != NULL)
1545 return m_SFToolbar->Close();
1546
1547 return S_OK;
1548 }
1549 HRESULT STDMETHODCALLTYPE CMenuBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
1550 {
1551 UNIMPLEMENTED;
1552 return S_OK;
1553 }
1554
1555 HRESULT STDMETHODCALLTYPE CMenuBand::ContextSensitiveHelp(BOOL fEnterMode)
1556 {
1557 UNIMPLEMENTED;
1558 return S_OK;
1559 }
1560
1561 HRESULT STDMETHODCALLTYPE CMenuBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
1562 {
1563 HRESULT hr;
1564
1565 CComPtr<IMenuPopup> pmp;
1566
1567 hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &pmp));
1568 if (FAILED(hr))
1569 return hr;
1570
1571 hr = pmp->SetSubMenu(this, TRUE);
1572 if (FAILED(hr))
1573 return hr;
1574
1575 CComPtr<IOleWindow> pTopLevelWindow;
1576 hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
1577 if (FAILED(hr))
1578 return hr;
1579
1580 hr = pTopLevelWindow->GetWindow(&m_topLevelWindow);
1581 if (FAILED(hr))
1582 return hr;
1583
1584 return S_FALSE;
1585 }
1586
1587 HRESULT STDMETHODCALLTYPE CMenuBand::HasFocusIO()
1588 {
1589 UNIMPLEMENTED;
1590 return S_OK;
1591 }
1592
1593 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateAcceleratorIO(LPMSG lpMsg)
1594 {
1595 UNIMPLEMENTED;
1596 return S_OK;
1597 }
1598
1599 HRESULT STDMETHODCALLTYPE CMenuBand::IsDirty()
1600 {
1601 UNIMPLEMENTED;
1602 return S_OK;
1603 }
1604
1605 HRESULT STDMETHODCALLTYPE CMenuBand::Load(IStream *pStm)
1606 {
1607 UNIMPLEMENTED;
1608 return S_OK;
1609 }
1610
1611 HRESULT STDMETHODCALLTYPE CMenuBand::Save(IStream *pStm, BOOL fClearDirty)
1612 {
1613 UNIMPLEMENTED;
1614 return S_OK;
1615 }
1616
1617 HRESULT STDMETHODCALLTYPE CMenuBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
1618 {
1619 UNIMPLEMENTED;
1620 return S_OK;
1621 }
1622
1623 HRESULT STDMETHODCALLTYPE CMenuBand::GetClassID(CLSID *pClassID)
1624 {
1625 UNIMPLEMENTED;
1626 return S_OK;
1627 }
1628
1629 HRESULT STDMETHODCALLTYPE CMenuBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
1630 {
1631 UNIMPLEMENTED;
1632 return S_OK;
1633 }
1634
1635 HRESULT STDMETHODCALLTYPE CMenuBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1636 {
1637 if (!pguidCmdGroup)
1638 return E_FAIL;
1639
1640 if (IsEqualGUID(*pguidCmdGroup, CLSID_MenuBand))
1641 {
1642 if (nCmdID == 16) // set (big) icon size
1643 {
1644 this->m_useBigIcons = TRUE;
1645 return S_OK;
1646 }
1647 else if (nCmdID == 19) // popup-related
1648 {
1649 return S_FALSE;
1650 }
1651 }
1652
1653 UNIMPLEMENTED;
1654 return S_OK;
1655 }
1656
1657 HRESULT STDMETHODCALLTYPE CMenuBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
1658 {
1659 if (IsEqualIID(guidService, SID_SMenuBandChild) ||
1660 IsEqualIID(guidService, SID_SMenuBandBottom) ||
1661 IsEqualIID(guidService, SID_SMenuBandBottomSelected))
1662 return this->QueryInterface(riid, ppvObject);
1663 WARN("Unknown service requested %s\n", wine_dbgstr_guid(&guidService));
1664 return E_NOINTERFACE;
1665 }
1666
1667 HRESULT STDMETHODCALLTYPE CMenuBand::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
1668 {
1669 UNIMPLEMENTED;
1670 return S_OK;
1671 }
1672
1673 HRESULT STDMETHODCALLTYPE CMenuBand::OnSelect(DWORD dwSelectType)
1674 {
1675 CComPtr<IMenuPopup> pmp;
1676 HRESULT hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &pmp));
1677 if (FAILED(hr))
1678 return hr;
1679 pmp->OnSelect(dwSelectType);
1680 return S_OK;
1681 }
1682
1683 HRESULT STDMETHODCALLTYPE CMenuBand::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
1684 {
1685 UNIMPLEMENTED;
1686 return S_OK;
1687 }
1688
1689 HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient)
1690 {
1691 UNIMPLEMENTED;
1692 return S_OK;
1693 }
1694
1695 HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
1696 {
1697 UNIMPLEMENTED;
1698 return S_OK;
1699 }
1700
1701 HRESULT STDMETHODCALLTYPE CMenuBand::IsMenuMessage(MSG *pmsg)
1702 {
1703 //UNIMPLEMENTED;
1704 //return S_OK;
1705 return S_FALSE;
1706 //return E_NOTIMPL;
1707 }
1708
1709 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateMenuMessage(MSG *pmsg, LRESULT *plRet)
1710 {
1711 //UNIMPLEMENTED;
1712 return S_FALSE;
1713 }
1714
1715 HRESULT STDMETHODCALLTYPE CMenuBand::SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags)
1716 {
1717 if (m_SFToolbar == NULL)
1718 {
1719 m_SFToolbar = new CMenuSFToolbar(this);
1720 }
1721
1722 HRESULT hr = m_SFToolbar->SetShellFolder(psf, pidlFolder, hKey, dwFlags);
1723 if (FAILED(hr))
1724 return hr;
1725
1726 if (m_site)
1727 {
1728 HWND hwndParent;
1729
1730 hr = m_site->GetWindow(&hwndParent);
1731 if (FAILED(hr))
1732 return hr;
1733
1734 hr = m_SFToolbar->CreateToolbar(hwndParent, m_dwFlags);
1735 if (FAILED(hr))
1736 return hr;
1737
1738 hr = m_SFToolbar->FillToolbar();
1739 }
1740
1741 return hr;
1742 }
1743
1744 HRESULT STDMETHODCALLTYPE CMenuBand::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv)
1745 {
1746 if (m_SFToolbar)
1747 return m_SFToolbar->GetShellFolder(pdwFlags, ppidl, riid, ppv);
1748 return E_FAIL;
1749 }
1750
1751 HRESULT STDMETHODCALLTYPE CMenuBand::InvalidateItem(LPSMDATA psmd, DWORD dwFlags)
1752 {
1753 UNIMPLEMENTED;
1754 return S_OK;
1755 }
1756
1757 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(LPSMDATA psmd)
1758 {
1759 UNIMPLEMENTED;
1760 return S_OK;
1761 }
1762
1763 HRESULT STDMETHODCALLTYPE CMenuBand::SetMenuToolbar(IUnknown *punk, DWORD dwFlags)
1764 {
1765 UNIMPLEMENTED;
1766 return S_OK;
1767 }
1768
1769 HRESULT STDMETHODCALLTYPE CMenuBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
1770 {
1771 *theResult = 0;
1772 switch (uMsg)
1773 {
1774 case WM_COMMAND:
1775
1776 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd))
1777 {
1778 return m_staticToolbar->OnCommand(wParam, lParam, theResult);
1779 }
1780
1781 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd))
1782 {
1783 return m_SFToolbar->OnCommand(wParam, lParam, theResult);
1784 }
1785
1786 return S_OK;
1787
1788 case WM_NOTIFY:
1789 NMHDR * hdr = reinterpret_cast<LPNMHDR>(lParam);
1790 NMTBCUSTOMDRAW * cdraw;
1791 NMTBHOTITEM * hot;
1792 NMMOUSE * rclick;
1793 switch (hdr->code)
1794 {
1795 case TBN_HOTITEMCHANGE:
1796 hot = reinterpret_cast<LPNMTBHOTITEM>(hdr);
1797
1798 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd))
1799 {
1800 return m_staticToolbar->OnHotItemChange(hot);
1801 }
1802
1803 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd))
1804 {
1805 return m_SFToolbar->OnHotItemChange(hot);
1806 }
1807
1808 return S_OK;
1809
1810 case NM_RCLICK:
1811 rclick = reinterpret_cast<LPNMMOUSE>(hdr);
1812
1813 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd))
1814 {
1815 return m_staticToolbar->OnContextMenu(rclick);
1816 }
1817
1818 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd))
1819 {
1820 return m_SFToolbar->OnContextMenu(rclick);
1821 }
1822
1823 return S_OK;
1824 case NM_CUSTOMDRAW:
1825 cdraw = reinterpret_cast<LPNMTBCUSTOMDRAW>(hdr);
1826 switch (cdraw->nmcd.dwDrawStage)
1827 {
1828 case CDDS_PREPAINT:
1829 *theResult = CDRF_NOTIFYITEMDRAW;
1830 return S_OK;
1831
1832 case CDDS_ITEMPREPAINT:
1833
1834 cdraw->clrBtnFace = GetSysColor(COLOR_MENU);
1835 cdraw->clrBtnHighlight = GetSysColor(COLOR_MENUHILIGHT);
1836
1837 cdraw->clrText = GetSysColor(COLOR_MENUTEXT);
1838 cdraw->clrTextHighlight = GetSysColor(COLOR_HIGHLIGHTTEXT);
1839 cdraw->clrHighlightHotTrack = GetSysColor(COLOR_HIGHLIGHTTEXT);
1840
1841 RECT rc = cdraw->nmcd.rc;
1842 HDC hdc = cdraw->nmcd.hdc;
1843
1844 HBRUSH bgBrush = GetSysColorBrush(COLOR_MENU);
1845 HBRUSH hotBrush = GetSysColorBrush(COLOR_MENUHILIGHT);
1846
1847 switch (cdraw->nmcd.uItemState)
1848 {
1849 case CDIS_HOT:
1850 case CDIS_FOCUS:
1851 FillRect(hdc, &rc, hotBrush);
1852 break;
1853 default:
1854 FillRect(hdc, &rc, bgBrush);
1855 break;
1856 }
1857
1858 *theResult = TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOETCHEDEFFECT | TBCDRF_HILITEHOTTRACK | TBCDRF_NOOFFSET;
1859 return S_OK;
1860 }
1861 return S_OK;
1862 }
1863 return S_OK;
1864 }
1865
1866 return S_FALSE;
1867 }
1868
1869 HRESULT STDMETHODCALLTYPE CMenuBand::IsWindowOwner(HWND hWnd)
1870 {
1871 if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd))
1872 return S_OK;
1873
1874 if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd))
1875 return S_OK;
1876
1877 return S_FALSE;
1878 }
1879
1880 HRESULT STDMETHODCALLTYPE CMenuBand::GetSubMenu(THIS)
1881 {
1882 UNIMPLEMENTED;
1883 return S_OK;
1884 }
1885
1886 HRESULT STDMETHODCALLTYPE CMenuBand::SetToolbar(THIS)
1887 {
1888 UNIMPLEMENTED;
1889 return S_OK;
1890 }
1891
1892 HRESULT STDMETHODCALLTYPE CMenuBand::SetMinWidth(THIS)
1893 {
1894 UNIMPLEMENTED;
1895 return S_OK;
1896 }
1897
1898 HRESULT STDMETHODCALLTYPE CMenuBand::SetNoBorder(THIS)
1899 {
1900 UNIMPLEMENTED;
1901 return S_OK;
1902 }
1903
1904 HRESULT STDMETHODCALLTYPE CMenuBand::SetTheme(THIS)
1905 {
1906 UNIMPLEMENTED;
1907 return S_OK;
1908 }
1909
1910 HRESULT STDMETHODCALLTYPE CMenuBand::GetTop(THIS)
1911 {
1912 UNIMPLEMENTED;
1913 return S_OK;
1914 }
1915
1916 HRESULT STDMETHODCALLTYPE CMenuBand::GetBottom(THIS)
1917 {
1918 UNIMPLEMENTED;
1919 return S_OK;
1920 }
1921
1922 HRESULT STDMETHODCALLTYPE CMenuBand::GetTracked(THIS)
1923 {
1924 UNIMPLEMENTED;
1925 return S_OK;
1926 }
1927
1928 HRESULT STDMETHODCALLTYPE CMenuBand::GetParentSite(THIS)
1929 {
1930 UNIMPLEMENTED;
1931 return S_OK;
1932 }
1933
1934 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(THIS)
1935 {
1936 UNIMPLEMENTED;
1937 return S_OK;
1938 }
1939
1940 HRESULT STDMETHODCALLTYPE CMenuBand::DoDefaultAction(THIS)
1941 {
1942 UNIMPLEMENTED;
1943 return S_OK;
1944 }
1945
1946 HRESULT STDMETHODCALLTYPE CMenuBand::IsEmpty(THIS)
1947 {
1948 UNIMPLEMENTED;
1949 return S_OK;
1950 }
1951
1952 HRESULT CMenuBand::CallCBWithId(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam)
1953 {
1954 return _CallCB(uMsg, wParam, lParam, id);
1955 }
1956
1957 HRESULT CMenuBand::CallCBWithPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam)
1958 {
1959 return _CallCB(uMsg, wParam, lParam, 0, pidl);
1960 }
1961
1962 HRESULT CMenuBand::_CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id, LPITEMIDLIST pidl)
1963 {
1964 if (!m_psmc)
1965 return S_FALSE;
1966
1967 HWND hwnd;
1968 GetWindow(&hwnd);
1969
1970 SMDATA smData = { 0 };
1971 smData.punk = static_cast<IShellMenu2*>(this);
1972 smData.uId = id;
1973 smData.uIdParent = m_uId;
1974 smData.uIdAncestor = m_uIdAncestor;
1975 smData.hwnd = hwnd;
1976 smData.pidlItem = pidl;
1977 if (m_staticToolbar)
1978 {
1979 smData.hmenu = m_hmenu;
1980 }
1981 smData.pvUserData = NULL;
1982 if (m_SFToolbar)
1983 m_SFToolbar->GetShellFolder(NULL, &smData.pidlFolder, IID_PPV_ARG(IShellFolder, &smData.psf));
1984 HRESULT hr = m_psmc->CallbackSM(&smData, uMsg, wParam, lParam);
1985 ILFree(smData.pidlFolder);
1986 if (smData.psf)
1987 smData.psf->Release();
1988 return hr;
1989 }
1990
1991 HRESULT CMenuBand::TrackPopup(HMENU popup, INT x, INT y)
1992 {
1993 ::TrackPopupMenu(popup, 0, x, y, 0, m_menuOwner, NULL);
1994 return S_OK;
1995 }
1996
1997 HRESULT CMenuBand::GetTopLevelWindow(HWND*topLevel)
1998 {
1999 *topLevel = m_topLevelWindow;
2000 return S_OK;
2001 }