[SHELL32]
[reactos.git] / dll / win32 / browseui / internettoolbar.cpp
1 /*
2 * ReactOS Explorer
3 *
4 * Copyright 2009 Andrew Hill <ash77 at domain reactos.org>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 Implements a class that knows how to hold and manage the menu band, brand band,
23 toolbar, and address band for an explorer window
24 */
25
26 #include "precomp.h"
27
28 /* FIXME, I can't include windowsx because it conflicts with some #defines */
29 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
30 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
31
32 #define USE_CUSTOM_MENUBAND 1
33
34 // navigation controls and menubar just send a message to parent window
35 /*
36 TODO:
37 ****Implement BandProxy methods
38 ****Add QueryStatus handler for built-in bands
39 ****Enable/Disable up, search, and folders commands appropriately
40 **Why are explorer toolbar separators a nonstandard width?
41 **Remove "(Empty)" item from Favorites menu. Probably something missing in CMenuCallback::CallbackSM
42 **Chevron menu on menuband doesn't work
43 **Fix CInternetToolbar::QueryBand to be generic
44
45 ****Fix context menu to strip divider when menu shown for menu band
46 ****Fix context menu to have items checked appropriately
47 ****Implement -1 command id update
48 ****When bands are rearranged, resize the internet toolbar and fix height of brand band
49 ****Right clicking on the browse back and forward toolbar buttons displays the same as pulldown menus
50 Implement show/hide of bands
51 Why is the background color of my toolbars different from explorer?
52 Internet Toolbar command handler should get the target for the command and call Exec on the target.
53 For commands built in to the Internet Toolbar, its Exec handles the command
54 When window width is changed, brand band flashes badly
55 Add all bands with correct ids (system bands now add with correct ids)
56 Implement IBandSite
57 Implement remaining IExplorerToolbar methods
58 Fix toolbar buttons to enable/disable correctly
59 After toolbar is customized, it may be necessary to patch the widths of separators
60 Add theme support
61 Check sizes and spacing of toolbars against Explorer
62 Implement resizing of the dock bar
63 Add missing icons for toolbar items
64 Draw History item in forward/back dropdown menus with icon
65 Fix toolbar customize dialog to not include separators as possible selections
66 Implement save/restore of toolbar state
67 Refactor drop down menu code to use a common function since code is so similar
68 */
69
70 extern HRESULT WINAPI SHBindToFolder(LPCITEMIDLIST path, IShellFolder **newFolder);
71 extern HRESULT CreateToolsBar(REFIID riid, void **ppv);
72 extern HRESULT CreateBrandBand(REFIID riid, void **ppv);
73 extern HRESULT CreateBandProxy(REFIID riid, void **ppv);
74 extern HRESULT CreateAddressBand(REFIID riid, void **ppv);
75
76 HRESULT IUnknown_HasFocusIO(IUnknown * punk)
77 {
78 CComPtr<IInputObject> pio;
79 HRESULT hr;
80 hr = punk->QueryInterface(IID_PPV_ARG(IInputObject, &pio));
81 if (FAILED(hr))
82 return hr;
83 return pio->HasFocusIO();
84 }
85
86 HRESULT IUnknown_TranslateAcceleratorIO(IUnknown * punk, MSG * pmsg)
87 {
88 CComPtr<IInputObject> pio;
89 HRESULT hr;
90 if (!punk)
91 return E_FAIL;
92 hr = punk->QueryInterface(IID_PPV_ARG(IInputObject, &pio));
93 if (FAILED(hr))
94 return hr;
95 return pio->TranslateAcceleratorIO(pmsg);
96 }
97
98 HRESULT IUnknown_RelayWinEvent(IUnknown * punk, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
99 {
100 CComPtr<IWinEventHandler> menuWinEventHandler;
101 HRESULT hResult = punk->QueryInterface(IID_PPV_ARG(IWinEventHandler, &menuWinEventHandler));
102 if (FAILED_UNEXPECTEDLY(hResult))
103 return hResult;
104 hResult = menuWinEventHandler->IsWindowOwner(hWnd);
105 if (FAILED_UNEXPECTEDLY(hResult))
106 return hResult;
107 if (hResult == S_OK)
108 return menuWinEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
109 return S_FALSE;
110 }
111
112 HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow)
113 {
114 CComPtr<IDockingWindow> dockingWindow;
115 HRESULT hResult = punk->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
116 if (FAILED_UNEXPECTEDLY(hResult))
117 return hResult;
118 hResult = dockingWindow->ShowDW(fShow);
119 if (FAILED_UNEXPECTEDLY(hResult))
120 return hResult;
121 return S_OK;
122 }
123
124 HRESULT IUnknown_CloseDW(IUnknown * punk, DWORD dwReserved)
125 {
126 CComPtr<IDockingWindow> dockingWindow;
127 HRESULT hResult = punk->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
128 if (FAILED_UNEXPECTEDLY(hResult))
129 return hResult;
130 hResult = dockingWindow->CloseDW(dwReserved);
131 if (FAILED_UNEXPECTEDLY(hResult))
132 return hResult;
133 return S_OK;
134 }
135
136 typedef HRESULT(*PMENUBAND_CONSTRUCTOR)(REFIID riid, void **ppv);
137
138 class CInternetToolbar;
139
140 class CDockSite :
141 public CComObjectRootEx<CComMultiThreadModelNoCS>,
142 public IDockingWindowSite,
143 public IInputObjectSite,
144 public IOleCommandTarget,
145 public IServiceProvider
146 {
147 public:
148 enum {
149 ITF_NOGRIPPER = 1,
150 ITF_NOTITLE = 2,
151 ITF_NEWBANDALWAYS = 4,
152 ITF_GRIPPERALWAYS = 8,
153 ITF_FIXEDSIZE = 16
154 };
155 private:
156 CComPtr<IUnknown> fContainedBand; // the band inside us
157 CInternetToolbar *fToolbar; // our browser
158 HWND fRebarWindow;
159 HWND fChildWindow;
160 int fBandID;
161 public:
162 int fFlags;
163 private:
164 bool fInitialized;
165 // fields of DESKBANDINFO must be preserved between calls to GetBandInfo
166 DESKBANDINFO fDeskBandInfo;
167 public:
168 CDockSite();
169 ~CDockSite();
170 HRESULT Initialize(IUnknown *containedBand, CInternetToolbar *browser, HWND hwnd, int bandID, int flags);
171 HRESULT GetRBBandInfo(REBARBANDINFOW &bandInfo);
172 private:
173
174 // *** IOleWindow methods ***
175 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
176 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
177
178 // *** IDockingWindow methods ***
179 virtual HRESULT STDMETHODCALLTYPE GetBorderDW(IUnknown* punkObj, LPRECT prcBorder);
180 virtual HRESULT STDMETHODCALLTYPE RequestBorderSpaceDW(IUnknown* punkObj, LPCBORDERWIDTHS pbw);
181 virtual HRESULT STDMETHODCALLTYPE SetBorderSpaceDW(IUnknown* punkObj, LPCBORDERWIDTHS pbw);
182
183 // *** IInputObjectSite specific methods ***
184 virtual HRESULT STDMETHODCALLTYPE OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus);
185
186 // *** IOleCommandTarget specific methods ***
187 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
188 OLECMD prgCmds[ ], OLECMDTEXT *pCmdText);
189 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
190 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
191
192 // *** IServiceProvider methods ***
193 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
194
195 BEGIN_COM_MAP(CDockSite)
196 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
197 COM_INTERFACE_ENTRY_IID(IID_IDockingWindowSite, IDockingWindowSite)
198 COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite)
199 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
200 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
201 END_COM_MAP()
202 };
203
204 CDockSite::CDockSite()
205 {
206 fToolbar = NULL;
207 fRebarWindow = NULL;
208 fChildWindow = NULL;
209 fBandID = 0;
210 fFlags = 0;
211 fInitialized = false;
212 memset(&fDeskBandInfo, 0, sizeof(fDeskBandInfo));
213 }
214
215 CDockSite::~CDockSite()
216 {
217 }
218
219 HRESULT CDockSite::Initialize(IUnknown *containedBand, CInternetToolbar *browser, HWND hwnd, int bandID, int flags)
220 {
221 TCHAR textBuffer[40];
222 REBARBANDINFOW bandInfo;
223 HRESULT hResult;
224
225 fContainedBand = containedBand;
226 fToolbar = browser;
227 fRebarWindow = hwnd;
228 fBandID = bandID;
229 fFlags = flags;
230 hResult = IUnknown_SetSite(containedBand, static_cast<IOleWindow *>(this));
231 if (FAILED(hResult))
232 return hResult;
233 hResult = IUnknown_GetWindow(containedBand, &fChildWindow);
234 if (FAILED(hResult))
235 return hResult;
236
237 memset(&bandInfo, 0, sizeof(bandInfo));
238 bandInfo.cbSize = sizeof(bandInfo);
239 bandInfo.lpText = textBuffer;
240 bandInfo.cch = sizeof(textBuffer) / sizeof(TCHAR);
241 hResult = GetRBBandInfo(bandInfo);
242
243 SendMessage(fRebarWindow, RB_GETBANDCOUNT, 0, 0);
244 SendMessage(fRebarWindow, RB_INSERTBANDW, -1, (LPARAM)&bandInfo);
245 fInitialized = true;
246 return S_OK;
247 }
248
249 HRESULT CDockSite::GetRBBandInfo(REBARBANDINFOW &bandInfo)
250 {
251 CComPtr<IDeskBand> deskBand;
252 HRESULT hResult;
253
254 hResult = fContainedBand->QueryInterface(IID_PPV_ARG(IDeskBand, &deskBand));
255 if (FAILED(hResult))
256 return hResult;
257
258 fDeskBandInfo.dwMask = DBIM_BKCOLOR | DBIM_MODEFLAGS | DBIM_TITLE | DBIM_ACTUAL |
259 DBIM_INTEGRAL | DBIM_MAXSIZE | DBIM_MINSIZE;
260 hResult = deskBand->GetBandInfo(fBandID, 0, &fDeskBandInfo);
261 // result of call is ignored
262
263 bandInfo.fMask = RBBIM_LPARAM | RBBIM_IDEALSIZE | RBBIM_ID | RBBIM_CHILDSIZE | RBBIM_CHILD |
264 RBBIM_TEXT | RBBIM_STYLE;
265
266 bandInfo.fStyle = RBBS_FIXEDBMP;
267 if (fDeskBandInfo.dwModeFlags & DBIMF_VARIABLEHEIGHT)
268 bandInfo.fStyle |= RBBS_VARIABLEHEIGHT;
269 if (fDeskBandInfo.dwModeFlags & DBIMF_USECHEVRON)
270 bandInfo.fStyle |= RBBS_USECHEVRON;
271 if (fDeskBandInfo.dwModeFlags & DBIMF_BREAK)
272 bandInfo.fStyle |= RBBS_BREAK;
273 if (fDeskBandInfo.dwModeFlags & DBIMF_TOPALIGN)
274 bandInfo.fStyle |= RBBS_TOPALIGN;
275 if (fFlags & ITF_NOGRIPPER || fToolbar->fLocked)
276 bandInfo.fStyle |= RBBS_NOGRIPPER;
277 if (fFlags & ITF_NOTITLE)
278 bandInfo.fStyle |= RBBS_HIDETITLE;
279 if (fFlags & ITF_GRIPPERALWAYS && !fToolbar->fLocked)
280 bandInfo.fStyle |= RBBS_GRIPPERALWAYS;
281 if (fFlags & ITF_FIXEDSIZE)
282 bandInfo.fStyle |= RBBS_FIXEDSIZE;
283
284 if (fDeskBandInfo.dwModeFlags & DBIMF_BKCOLOR)
285 {
286 bandInfo.fMask |= RBBIM_COLORS;
287 bandInfo.clrFore = CLR_DEFAULT;
288 bandInfo.clrBack = fDeskBandInfo.crBkgnd;
289 }
290 wcsncpy(bandInfo.lpText, fDeskBandInfo.wszTitle, bandInfo.cch);
291 bandInfo.hwndChild = fChildWindow;
292 bandInfo.cxMinChild = fDeskBandInfo.ptMinSize.x;
293 bandInfo.cyMinChild = fDeskBandInfo.ptMinSize.y;
294 bandInfo.wID = fBandID;
295 bandInfo.cyChild = fDeskBandInfo.ptActual.y;
296 bandInfo.cyMaxChild = fDeskBandInfo.ptMaxSize.y;
297 bandInfo.cyIntegral = fDeskBandInfo.ptIntegral.y;
298 bandInfo.cxIdeal = fDeskBandInfo.ptActual.x;
299 bandInfo.lParam = reinterpret_cast<LPARAM>(this);
300 return S_OK;
301 }
302
303 HRESULT STDMETHODCALLTYPE CDockSite::GetWindow(HWND *lphwnd)
304 {
305 if (lphwnd == NULL)
306 return E_POINTER;
307 *lphwnd = fRebarWindow;
308 return S_OK;
309 }
310
311 HRESULT STDMETHODCALLTYPE CDockSite::ContextSensitiveHelp(BOOL fEnterMode)
312 {
313 return E_NOTIMPL;
314 }
315
316 HRESULT STDMETHODCALLTYPE CDockSite::GetBorderDW(IUnknown* punkObj, LPRECT prcBorder)
317 {
318 return E_NOTIMPL;
319 }
320
321 HRESULT STDMETHODCALLTYPE CDockSite::RequestBorderSpaceDW(IUnknown* punkObj, LPCBORDERWIDTHS pbw)
322 {
323 return E_NOTIMPL;
324 }
325
326 HRESULT STDMETHODCALLTYPE CDockSite::SetBorderSpaceDW(IUnknown* punkObj, LPCBORDERWIDTHS pbw)
327 {
328 return E_NOTIMPL;
329 }
330
331 HRESULT STDMETHODCALLTYPE CDockSite::OnFocusChangeIS (IUnknown *punkObj, BOOL fSetFocus)
332 {
333 return E_NOTIMPL;
334 }
335
336 HRESULT STDMETHODCALLTYPE CDockSite::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
337 OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
338 {
339 return E_NOTIMPL;
340 }
341
342 HRESULT STDMETHODCALLTYPE CDockSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
343 VARIANT *pvaIn, VARIANT *pvaOut)
344 {
345 TCHAR textBuffer[40];
346 REBARBANDINFOW bandInfo;
347 int index;
348 HRESULT hResult;
349
350 if (IsEqualIID(*pguidCmdGroup, CGID_DeskBand))
351 {
352 switch (nCmdID)
353 {
354 case DBID_BANDINFOCHANGED:
355 if (fInitialized == false)
356 return S_OK;
357 if (V_VT(pvaIn) != VT_I4)
358 return E_INVALIDARG;
359 if (V_I4(pvaIn) != fBandID)
360 return E_FAIL;
361 // deskband information changed
362 // call GetBandInfo and refresh information in rebar
363 memset(&bandInfo, 0, sizeof(bandInfo));
364 bandInfo.cbSize = sizeof(bandInfo);
365 bandInfo.lpText = textBuffer;
366 bandInfo.cch = sizeof(textBuffer) / sizeof(TCHAR);
367 hResult = GetRBBandInfo(bandInfo);
368 if (FAILED(hResult))
369 return hResult;
370 index = (int)SendMessage(fRebarWindow, RB_IDTOINDEX, fBandID, 0);
371 SendMessage(fRebarWindow, RB_SETBANDINFOW, index, (LPARAM)&bandInfo);
372 return S_OK;
373 }
374 }
375 return E_FAIL;
376 }
377
378 HRESULT STDMETHODCALLTYPE CDockSite::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
379 {
380 if (IsEqualIID(guidService, SID_SMenuBandParent))
381 return this->QueryInterface(riid, ppvObject);
382
383 return fToolbar->QueryService(guidService, riid, ppvObject);
384 }
385
386 CMenuCallback::CMenuCallback()
387 {
388 }
389
390 CMenuCallback::~CMenuCallback()
391 {
392 }
393
394 HRESULT STDMETHODCALLTYPE CMenuCallback::GetObject(LPSMDATA psmd, REFIID riid, void **ppvObject)
395 {
396 CComPtr<IShellMenu> parentMenu;
397 CComPtr<IShellMenu> newMenu;
398 CComPtr<IShellFolder> favoritesFolder;
399 LPITEMIDLIST favoritesPIDL;
400 HWND ownerWindow;
401 HMENU parentHMenu;
402 HMENU favoritesHMenu;
403 HKEY orderRegKey;
404 DWORD disposition;
405 HRESULT hResult;
406 static const TCHAR szFavoritesKey[] =
407 _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MenuOrder\\Favorites");
408
409 if (!IsEqualIID(riid, IID_IShellMenu))
410 return E_FAIL;
411 if (psmd->uId != FCIDM_MENU_FAVORITES)
412 return E_FAIL;
413
414 if (fFavoritesMenu.p == NULL)
415 {
416 // create favorites menu
417 hResult = psmd->punk->QueryInterface(IID_PPV_ARG(IShellMenu, &parentMenu));
418 if (FAILED(hResult))
419 return hResult;
420 hResult = parentMenu->GetMenu(&parentHMenu, &ownerWindow, NULL);
421 if (FAILED(hResult))
422 return hResult;
423 favoritesHMenu = GetSubMenu(parentHMenu, 3);
424 if (favoritesHMenu == NULL)
425 return E_FAIL;
426 #if USE_CUSTOM_MENUBAND
427 HMODULE hrs = LoadLibrary(L"rshell.dll");
428
429 PMENUBAND_CONSTRUCTOR func = (PMENUBAND_CONSTRUCTOR) GetProcAddress(hrs, "CMenuBand_Constructor");
430 if (func)
431 {
432 hResult = func(IID_PPV_ARG(IShellMenu, &newMenu));
433 }
434 else
435 {
436 hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER,
437 IID_PPV_ARG(IShellMenu, &newMenu));
438 }
439 #else
440 hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER,
441 IID_PPV_ARG(IShellMenu, &newMenu));
442 #endif
443 if (FAILED(hResult))
444 return hResult;
445 hResult = newMenu->Initialize(this, FCIDM_MENU_FAVORITES, -1, SMINIT_VERTICAL | SMINIT_CACHED);
446 if (FAILED(hResult))
447 return hResult;
448 hResult = newMenu->SetMenu(favoritesHMenu, ownerWindow, SMSET_TOP | SMSET_DONTOWN);
449 if (FAILED(hResult))
450 return hResult;
451 hResult = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &favoritesPIDL);
452 if (FAILED(hResult))
453 return hResult;
454 hResult = SHBindToFolder(favoritesPIDL, &favoritesFolder);
455 if (FAILED(hResult))
456 return hResult;
457 RegCreateKeyEx(HKEY_CURRENT_USER, szFavoritesKey,
458 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &orderRegKey, &disposition);
459 hResult = newMenu->SetShellFolder(favoritesFolder, favoritesPIDL, orderRegKey, SMSET_BOTTOM | 0x18);
460 ILFree(favoritesPIDL);
461 if (SUCCEEDED(hResult))
462 fFavoritesMenu.Attach(newMenu.Detach());
463 }
464 if (fFavoritesMenu.p == NULL)
465 return E_FAIL;
466 return fFavoritesMenu->QueryInterface(riid, ppvObject);
467 }
468
469 HRESULT STDMETHODCALLTYPE CMenuCallback::CallbackSM(LPSMDATA psmd, UINT uMsg, WPARAM wParam, LPARAM lParam)
470 {
471 switch (uMsg)
472 {
473 case SMC_INITMENU:
474 break;
475 case SMC_CREATE:
476 break;
477 case SMC_EXITMENU:
478 break;
479 case SMC_GETINFO:
480 {
481 SMINFO *infoPtr = reinterpret_cast<SMINFO *>(lParam);
482 if ((infoPtr->dwMask & SMIM_FLAGS) != 0)
483 {
484 if (psmd->uId == FCIDM_MENU_FAVORITES)
485 {
486 infoPtr->dwFlags |= SMIF_DROPCASCADE;
487 }
488 else
489 {
490 infoPtr->dwFlags |= SMIF_TRACKPOPUP;
491 }
492 }
493 if ((infoPtr->dwMask & SMIM_ICON) != 0)
494 infoPtr->iIcon = -1;
495 return S_OK;
496 }
497 case SMC_GETSFINFO:
498 break;
499 case SMC_GETOBJECT:
500 return GetObject(psmd, *reinterpret_cast<IID *>(wParam), reinterpret_cast<void **>(lParam));
501 case SMC_GETSFOBJECT:
502 break;
503 case SMC_SFEXEC:
504 break;
505 case SMC_SFSELECTITEM:
506 break;
507 case 13:
508 // return tooltip
509 break;
510 case SMC_REFRESH:
511 break;
512 case SMC_DEMOTE:
513 break;
514 case SMC_PROMOTE:
515 break;
516 case 0x13:
517 break;
518 case SMC_DEFAULTICON:
519 break;
520 case SMC_NEWITEM:
521 break;
522 case SMC_CHEVRONEXPAND:
523 break;
524 case SMC_DISPLAYCHEVRONTIP:
525 break;
526 case SMC_SETSFOBJECT:
527 break;
528 case SMC_SHCHANGENOTIFY:
529 break;
530 case SMC_CHEVRONGETTIP:
531 break;
532 case SMC_SFDDRESTRICTED:
533 break;
534 case 0x35:
535 break;
536 case 49:
537 break;
538 case 0x10000000:
539 break;
540 }
541 return S_FALSE;
542 }
543
544 CInternetToolbar::CInternetToolbar()
545 {
546 fMainReBar = NULL;
547 fLocked = false;
548 fMenuBandWindow = NULL;
549 fNavigationWindow = NULL;
550 fMenuCallback.AddRef();
551 fToolbarWindow = NULL;
552 fAdviseCookie = 0;
553 }
554
555 CInternetToolbar::~CInternetToolbar()
556 {
557 fMenuCallback.Release();
558 }
559
560 void CInternetToolbar::AddDockItem(IUnknown *newItem, int bandID, int flags)
561 {
562 CComPtr<CDockSite> newSite;
563
564 newSite = new CComObject<CDockSite>;
565 newSite->Initialize(newItem, this, fMainReBar, bandID, flags);
566 }
567
568 HRESULT CInternetToolbar::ReserveBorderSpace(LONG maxHeight)
569 {
570 CComPtr<IDockingWindowSite> dockingWindowSite;
571 RECT availableBorderSpace;
572
573 HRESULT hResult = fSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &dockingWindowSite));
574 if (FAILED(hResult))
575 return hResult;
576 hResult = dockingWindowSite->GetBorderDW(static_cast<IDockingWindow *>(this), &availableBorderSpace);
577 if (FAILED(hResult))
578 return hResult;
579
580 if (availableBorderSpace.top > maxHeight)
581 {
582 availableBorderSpace.top = maxHeight;
583 }
584
585 return ResizeBorderDW(&availableBorderSpace, fSite, FALSE);
586 }
587
588 HRESULT CInternetToolbar::CreateMenuBar(IShellMenu **menuBar)
589 {
590 CComPtr<IOleCommandTarget> siteCommandTarget;
591 CComPtr<IOleWindow> oleWindow;
592 CComPtr<IOleCommandTarget> commandTarget;
593 CComPtr<IShellMenuCallback> callback;
594 VARIANT menuOut;
595 HWND ownerWindow;
596 HRESULT hResult;
597
598 #if USE_CUSTOM_MENUBAND
599 HMODULE hrs = LoadLibraryW(L"rshell.dll");
600
601 if (!hrs)
602 {
603 DbgPrint("Failed: %d\n", GetLastError());
604 return E_FAIL;
605 }
606
607 PMENUBAND_CONSTRUCTOR func = (PMENUBAND_CONSTRUCTOR) GetProcAddress(hrs, "CMenuBand_Constructor");
608 if (func)
609 {
610 hResult = func(IID_PPV_ARG(IShellMenu, menuBar));
611 }
612 else
613 {
614 DbgPrint("Failed: %d\n", GetLastError());
615 hResult = E_FAIL;
616 }
617
618 if (FAILED(hResult))
619 {
620 hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER,
621 IID_PPV_ARG(IShellMenu, menuBar));
622 }
623 #else
624 hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER,
625 IID_PPV_ARG(IShellMenu, menuBar));
626 #endif
627 if (FAILED(hResult))
628 return hResult;
629 hResult = fMenuCallback.QueryInterface(IID_PPV_ARG(IShellMenuCallback, &callback));
630 if (FAILED(hResult))
631 return hResult;
632 hResult = (*menuBar)->Initialize(callback, -1, ANCESTORDEFAULT, SMINIT_HORIZONTAL | SMINIT_TOPLEVEL);
633 if (FAILED(hResult))
634 return hResult;
635 hResult = fSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
636 if (FAILED(hResult))
637 return hResult;
638 hResult = oleWindow->GetWindow(&ownerWindow);
639 if (FAILED(hResult))
640 return hResult;
641 hResult = fSite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &siteCommandTarget));
642 if (FAILED(hResult))
643 return hResult;
644 hResult = siteCommandTarget->Exec(&CGID_Explorer, 0x35, 0, NULL, &menuOut);
645 if (FAILED(hResult))
646 return hResult;
647 if (V_VT(&menuOut) != VT_INT_PTR || V_INTREF(&menuOut) == NULL)
648 return E_FAIL;
649 hResult = (*menuBar)->SetMenu((HMENU)V_INTREF(&menuOut), ownerWindow, SMSET_DONTOWN);
650 if (FAILED(hResult))
651 return hResult;
652 hResult = IUnknown_Exec(*menuBar, CGID_MenuBand, 3, 1, NULL, NULL);
653 if (FAILED(hResult))
654 return hResult;
655 return S_OK;
656 }
657
658 HRESULT CInternetToolbar::CreateBrandBand(IUnknown **logoBar)
659 {
660 #if 1
661 return ::CreateBrandBand(IID_PPV_ARG(IUnknown, logoBar));
662 #else
663 return CoCreateInstance(CLSID_BrandBand, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, logoBar));
664 #endif
665 }
666
667 HRESULT CInternetToolbar::CreateToolsBar(IUnknown **toolsBar)
668 {
669 return ::CreateToolsBar(IID_PPV_ARG(IUnknown, toolsBar));
670 }
671
672 HRESULT CInternetToolbar::CreateAddressBand(IUnknown **toolsBar)
673 {
674 #if 1
675 return ::CreateAddressBand(IID_PPV_ARG(IUnknown, toolsBar));
676 #else
677 return CoCreateInstance(CLSID_SH_AddressBand, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, toolsBar));
678 #endif
679 }
680
681 HRESULT CInternetToolbar::LockUnlockToolbars(bool locked)
682 {
683 REBARBANDINFOW rebarBandInfo;
684 int bandCount;
685 CDockSite *dockSite;
686 HRESULT hResult;
687
688 if (locked != fLocked)
689 {
690 fLocked = locked;
691 rebarBandInfo.cbSize = sizeof(rebarBandInfo);
692 rebarBandInfo.fMask = RBBIM_STYLE | RBBIM_LPARAM;
693 bandCount = (int)SendMessage(fMainReBar, RB_GETBANDCOUNT, 0, 0);
694 for (INT x = 0; x < bandCount; x++)
695 {
696 SendMessage(fMainReBar, RB_GETBANDINFOW, x, (LPARAM)&rebarBandInfo);
697 dockSite = reinterpret_cast<CDockSite *>(rebarBandInfo.lParam);
698 if (dockSite != NULL)
699 {
700 rebarBandInfo.fStyle &= ~(RBBS_NOGRIPPER | RBBS_GRIPPERALWAYS);
701 if (dockSite->fFlags & CDockSite::ITF_NOGRIPPER || fLocked)
702 rebarBandInfo.fStyle |= RBBS_NOGRIPPER;
703 if (dockSite->fFlags & CDockSite::ITF_GRIPPERALWAYS && !fLocked)
704 rebarBandInfo.fStyle |= RBBS_GRIPPERALWAYS;
705 SendMessage(fMainReBar, RB_SETBANDINFOW, x, (LPARAM)&rebarBandInfo);
706 }
707 }
708 hResult = ReserveBorderSpace();
709
710 // TODO: refresh view menu?
711 }
712 return S_OK;
713 }
714
715 HRESULT CInternetToolbar::CommandStateChanged(bool newValue, int commandID)
716 {
717 HRESULT hResult;
718
719 hResult = S_OK;
720 switch (commandID)
721 {
722 case -1:
723 // loop through buttons
724 //for buttons in CLSID_CommonButtons
725 // if up, QueryStatus for up state and update it
726 //
727 //for buttons in fCommandCategory, update with QueryStatus of fCommandTarget
728 break;
729 case 1:
730 // forward
731 hResult = SetState(&CLSID_CommonButtons, IDM_GOTO_FORWARD, newValue ? TBSTATE_ENABLED : 0);
732 break;
733 case 2:
734 // back
735 hResult = SetState(&CLSID_CommonButtons, IDM_GOTO_BACK, newValue ? TBSTATE_ENABLED : 0);
736 break;
737 }
738 return hResult;
739 }
740
741 HRESULT CInternetToolbar::CreateAndInitBandProxy()
742 {
743 CComPtr<IServiceProvider> serviceProvider;
744 HRESULT hResult;
745
746 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
747 if (FAILED(hResult))
748 return hResult;
749 hResult = serviceProvider->QueryService(SID_IBandProxy, IID_PPV_ARG(IBandProxy, &fBandProxy));
750 if (FAILED(hResult))
751 {
752 hResult = CreateBandProxy(IID_PPV_ARG(IBandProxy, &fBandProxy));
753 if (FAILED(hResult))
754 return hResult;
755 hResult = fBandProxy->SetSite(fSite);
756 if (FAILED(hResult))
757 return hResult;
758 }
759 return S_OK;
760 }
761
762 HRESULT STDMETHODCALLTYPE CInternetToolbar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
763 {
764 return E_NOTIMPL;
765 }
766
767 HRESULT STDMETHODCALLTYPE CInternetToolbar::HasFocusIO()
768 {
769 HRESULT hr = S_FALSE;
770
771 if (fMenuBar)
772 hr = IUnknown_HasFocusIO(fMenuBar);
773 if (hr != S_FALSE)
774 return hr;
775
776 if (fControlsBar)
777 hr = IUnknown_HasFocusIO(fControlsBar);
778 if (hr != S_FALSE)
779 return hr;
780
781 if (fNavigationBar)
782 hr = IUnknown_HasFocusIO(fNavigationBar);
783 if (hr != S_FALSE)
784 return hr;
785
786 return S_FALSE;
787 }
788
789 HRESULT STDMETHODCALLTYPE CInternetToolbar::TranslateAcceleratorIO(LPMSG lpMsg)
790 {
791 HRESULT hr = S_FALSE;
792
793 if (fMenuBar)
794 hr = IUnknown_TranslateAcceleratorIO(fMenuBar, lpMsg);
795 if (hr == S_OK)
796 return hr;
797
798 if (fControlsBar)
799 hr = IUnknown_TranslateAcceleratorIO(fControlsBar, lpMsg);
800 if (hr == S_OK)
801 return hr;
802
803 if (fNavigationBar)
804 hr = IUnknown_TranslateAcceleratorIO(fNavigationBar, lpMsg);
805 if (hr == S_OK)
806 return hr;
807
808 return S_FALSE;
809 }
810
811 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetWindow(HWND *lphwnd)
812 {
813 if (lphwnd == NULL)
814 return E_POINTER;
815 *lphwnd = m_hWnd;
816 return S_OK;
817 }
818
819 HRESULT STDMETHODCALLTYPE CInternetToolbar::ContextSensitiveHelp(BOOL fEnterMode)
820 {
821 return E_NOTIMPL;
822 }
823
824 HRESULT STDMETHODCALLTYPE CInternetToolbar::ShowDW(BOOL fShow)
825 {
826 HRESULT hResult;
827
828 // show the bar here
829 if (fShow)
830 {
831 hResult = ReserveBorderSpace();
832 if (FAILED_UNEXPECTEDLY(hResult))
833 return hResult;
834 }
835
836 if (fMenuBar)
837 {
838 hResult = IUnknown_ShowDW(fMenuBar, fShow);
839 if (FAILED_UNEXPECTEDLY(hResult))
840 return hResult;
841 }
842
843 if (fControlsBar)
844 {
845 hResult = IUnknown_ShowDW(fControlsBar, fShow);
846 if (FAILED_UNEXPECTEDLY(hResult))
847 return hResult;
848 }
849 if (fNavigationBar)
850 {
851 hResult = IUnknown_ShowDW(fNavigationBar, fShow);
852 if (FAILED_UNEXPECTEDLY(hResult))
853 return hResult;
854 }
855 if (fLogoBar)
856 {
857 hResult = IUnknown_ShowDW(fLogoBar, fShow);
858 if (FAILED_UNEXPECTEDLY(hResult))
859 return hResult;
860 }
861 return S_OK;
862 }
863
864 template<class T>
865 void ReleaseCComPtrExpectZero(CComPtr<T>& cptr, BOOL forceRelease = FALSE)
866 {
867 if (cptr.p != NULL)
868 {
869 int nrc = cptr->Release();
870 if (nrc > 0)
871 {
872 DbgPrint("WARNING: Unexpected RefCount > 0 (%d)!\n", nrc);
873 if (forceRelease)
874 {
875 while (nrc > 0)
876 {
877 nrc = cptr->Release();
878 }
879 }
880 }
881 cptr.Detach();
882 }
883 }
884
885 HRESULT STDMETHODCALLTYPE CInternetToolbar::CloseDW(DWORD dwReserved)
886 {
887 HRESULT hResult;
888
889 if (fMenuBar)
890 {
891 hResult = IUnknown_CloseDW(fMenuBar, dwReserved);
892 if (FAILED_UNEXPECTEDLY(hResult))
893 return hResult;
894 ReleaseCComPtrExpectZero(fMenuBar);
895 }
896 if (fControlsBar)
897 {
898 hResult = IUnknown_CloseDW(fControlsBar, dwReserved);
899 if (FAILED_UNEXPECTEDLY(hResult))
900 return hResult;
901 ReleaseCComPtrExpectZero(fControlsBar);
902 }
903 if (fNavigationBar)
904 {
905 hResult = IUnknown_CloseDW(fNavigationBar, dwReserved);
906 if (FAILED_UNEXPECTEDLY(hResult))
907 return hResult;
908 ReleaseCComPtrExpectZero(fNavigationBar);
909 }
910 if (fLogoBar)
911 {
912 hResult = IUnknown_CloseDW(fLogoBar, dwReserved);
913 if (FAILED_UNEXPECTEDLY(hResult))
914 return hResult;
915 ReleaseCComPtrExpectZero(fLogoBar);
916 }
917 return S_OK;
918 }
919
920 HRESULT STDMETHODCALLTYPE CInternetToolbar::ResizeBorderDW(LPCRECT prcBorder,
921 IUnknown *punkToolbarSite, BOOL fReserved)
922 {
923 RECT neededBorderSpace;
924 RECT availableBorderSpace = *prcBorder;
925
926 SendMessage(fMainReBar, RB_SIZETORECT, RBSTR_CHANGERECT, reinterpret_cast<LPARAM>(&availableBorderSpace));
927
928 // RBSTR_CHANGERECT does not seem to set the proper size in the rect.
929 // Let's make sure we fetch the actual size properly.
930 GetWindowRect(fMainReBar, &availableBorderSpace);
931 neededBorderSpace.left = 0;
932 neededBorderSpace.top = availableBorderSpace.bottom - availableBorderSpace.top;
933 if (!fLocked)
934 neededBorderSpace.top += 3;
935 neededBorderSpace.right = 0;
936 neededBorderSpace.bottom = 0;
937
938 CComPtr<IDockingWindowSite> dockingWindowSite;
939
940 HRESULT hResult = fSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &dockingWindowSite));
941 if (FAILED(hResult))
942 return hResult;
943
944 hResult = dockingWindowSite->RequestBorderSpaceDW(static_cast<IDockingWindow *>(this), &neededBorderSpace);
945 if (FAILED(hResult))
946 return hResult;
947
948 hResult = dockingWindowSite->SetBorderSpaceDW(static_cast<IDockingWindow *>(this), &neededBorderSpace);
949 if (FAILED(hResult))
950 return hResult;
951
952 return S_OK;
953 }
954
955 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetClassID(CLSID *pClassID)
956 {
957 if (pClassID == NULL)
958 return E_POINTER;
959 *pClassID = CLSID_InternetToolbar;
960 return S_OK;
961 }
962
963 HRESULT STDMETHODCALLTYPE CInternetToolbar::IsDirty()
964 {
965 return E_NOTIMPL;
966 }
967
968 HRESULT STDMETHODCALLTYPE CInternetToolbar::Load(IStream *pStm)
969 {
970 return E_NOTIMPL;
971 }
972
973 HRESULT STDMETHODCALLTYPE CInternetToolbar::Save(IStream *pStm, BOOL fClearDirty)
974 {
975 return E_NOTIMPL;
976 }
977
978 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetSizeMax(ULARGE_INTEGER *pcbSize)
979 {
980 return E_NOTIMPL;
981 }
982
983 HRESULT STDMETHODCALLTYPE CInternetToolbar::InitNew()
984 {
985 CComPtr<IShellMenu> menuBar;
986 CComPtr<IUnknown> logoBar;
987 CComPtr<IUnknown> toolsBar;
988 CComPtr<IUnknown> navigationBar;
989 HRESULT hResult;
990
991 /* Create and attach the menubar to the rebar */
992 hResult = CreateMenuBar(&menuBar);
993 if (FAILED(hResult))
994 return hResult;
995 AddDockItem(menuBar, ITBBID_MENUBAND, CDockSite::ITF_NOTITLE | CDockSite::ITF_NEWBANDALWAYS | CDockSite::ITF_GRIPPERALWAYS);
996
997 hResult = IUnknown_GetWindow(menuBar, &fMenuBandWindow);
998 fMenuBar.Attach(menuBar.Detach()); // transfer the ref count
999
1000 // FIXME: The ros Rebar does not properly support fixed-size items such as the brandband,
1001 // and it will put them in their own row, sized to take up the whole row.
1002 #if 0
1003 /* Create and attach the brand/logo to the rebar */
1004 hResult = CreateBrandBand(&logoBar);
1005 if (FAILED(hResult))
1006 return hResult;
1007 AddDockItem(logoBar, ITBBID_BRANDBAND, CDockSite::ITF_NOGRIPPER | CDockSite::ITF_NOTITLE | CDockSite::ITF_FIXEDSIZE);
1008 fLogoBar.Attach(logoBar.Detach()); // transfer the ref count
1009 #endif
1010
1011 /* Create and attach the standard toolbar to the rebar */
1012 hResult = CreateToolsBar(&toolsBar);
1013 if (FAILED(hResult))
1014 return hResult;
1015 AddDockItem(toolsBar, ITBBID_TOOLSBAND, CDockSite::ITF_NOTITLE | CDockSite::ITF_NEWBANDALWAYS | CDockSite::ITF_GRIPPERALWAYS);
1016 fControlsBar.Attach(toolsBar.Detach()); // transfer the ref count
1017 hResult = IUnknown_GetWindow(fControlsBar, &fToolbarWindow);
1018 if (FAILED(hResult))
1019 return hResult;
1020
1021 /* Create and attach the address/navigation toolbar to the rebar */
1022 hResult = CreateAddressBand(&navigationBar);
1023 if (FAILED(hResult))
1024 return hResult;
1025 AddDockItem(navigationBar, ITBBID_ADDRESSBAND, CDockSite::ITF_NEWBANDALWAYS | CDockSite::ITF_GRIPPERALWAYS);
1026 fNavigationBar.Attach(navigationBar.Detach());
1027 hResult = IUnknown_GetWindow(fNavigationBar, &fNavigationWindow);
1028
1029 return S_OK;
1030 }
1031
1032 HRESULT STDMETHODCALLTYPE CInternetToolbar::QueryStatus(const GUID *pguidCmdGroup,
1033 ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
1034 {
1035 if (IsEqualIID(*pguidCmdGroup, CGID_PrivCITCommands))
1036 {
1037 while (cCmds != 0)
1038 {
1039 switch (prgCmds->cmdID)
1040 {
1041 case ITID_TEXTLABELS: // Text Labels state
1042 prgCmds->cmdf = OLECMDF_SUPPORTED;
1043 break;
1044 case ITID_TOOLBARBANDSHOWN: // toolbar visibility
1045 prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1046 break;
1047 case ITID_ADDRESSBANDSHOWN: // address bar visibility
1048 prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1049 break;
1050 case ITID_LINKSBANDSHOWN: // links bar visibility
1051 prgCmds->cmdf = 0;
1052 break;
1053 case ITID_MENUBANDSHOWN: // Menubar band visibility
1054 prgCmds->cmdf = 0;
1055 break;
1056 case ITID_AUTOHIDEENABLED: // Auto hide enabled/disabled
1057 prgCmds->cmdf = 0;
1058 break;
1059 case ITID_CUSTOMIZEENABLED: // customize enabled
1060 prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1061 break;
1062 case ITID_TOOLBARLOCKED: // lock toolbars
1063 prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1064 if (fLocked)
1065 prgCmds->cmdf |= OLECMDF_LATCHED;
1066 break;
1067 default:
1068 prgCmds->cmdf = 0;
1069 break;
1070 }
1071 prgCmds++;
1072 cCmds--;
1073 }
1074 return S_OK;
1075 }
1076 return E_FAIL;
1077 }
1078
1079 HRESULT STDMETHODCALLTYPE CInternetToolbar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
1080 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1081 {
1082 if (IsEqualIID(*pguidCmdGroup, CGID_PrivCITCommands))
1083 {
1084 switch (nCmdID)
1085 {
1086 case 1:
1087 // what do I do here?
1088 return S_OK;
1089 case ITID_TEXTLABELS:
1090 // toggle text labels
1091 return S_OK;
1092 case ITID_TOOLBARBANDSHOWN:
1093 // toggle toolbar band visibility
1094 return S_OK;
1095 case ITID_ADDRESSBANDSHOWN:
1096 // toggle address band visibility
1097 return S_OK;
1098 case ITID_LINKSBANDSHOWN:
1099 // toggle links band visibility
1100 return S_OK;
1101 case ITID_CUSTOMIZEENABLED:
1102 // run customize
1103 return S_OK;
1104 case ITID_TOOLBARLOCKED:
1105 return LockUnlockToolbars(!fLocked);
1106 }
1107 }
1108 return E_FAIL;
1109 }
1110
1111 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetTypeInfoCount(UINT *pctinfo)
1112 {
1113 return E_NOTIMPL;
1114 }
1115
1116 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1117 {
1118 return E_NOTIMPL;
1119 }
1120
1121 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
1122 LCID lcid, DISPID *rgDispId)
1123 {
1124 return E_NOTIMPL;
1125 }
1126
1127 HRESULT STDMETHODCALLTYPE CInternetToolbar::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
1128 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1129 {
1130 HRESULT hResult;
1131
1132 switch(dispIdMember)
1133 {
1134 case DISPID_BEFORENAVIGATE:
1135 hResult = S_OK;
1136 break;
1137 case DISPID_DOWNLOADCOMPLETE:
1138 hResult = S_OK;
1139 break;
1140 case DISPID_COMMANDSTATECHANGE:
1141 if (pDispParams->cArgs != 2)
1142 return E_INVALIDARG;
1143 if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL || V_VT(&pDispParams->rgvarg[1]) != VT_I4)
1144 return E_INVALIDARG;
1145 return CommandStateChanged(V_BOOL(&pDispParams->rgvarg[0]) != VARIANT_FALSE,
1146 V_I4(&pDispParams->rgvarg[1]));
1147 case DISPID_DOWNLOADBEGIN:
1148 hResult = S_OK;
1149 break;
1150 case DISPID_NAVIGATECOMPLETE2:
1151 hResult = S_OK;
1152 break;
1153 case DISPID_DOCUMENTCOMPLETE:
1154 hResult = S_OK;
1155 break;
1156 }
1157 return S_OK;
1158 }
1159
1160 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetCommandTarget(IUnknown *theTarget, GUID *category, long param14)
1161 {
1162 HRESULT hResult;
1163
1164 fCommandTarget.Release();
1165 hResult = theTarget->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &fCommandTarget));
1166 if (FAILED(hResult))
1167 return hResult;
1168 fCommandCategory = *category;
1169 return S_OK;
1170 }
1171
1172 HRESULT STDMETHODCALLTYPE CInternetToolbar::Unknown1()
1173 {
1174 return E_NOTIMPL;
1175 }
1176
1177 HRESULT STDMETHODCALLTYPE CInternetToolbar::AddButtons(const GUID *pguidCmdGroup, long buttonCount, TBBUTTON *buttons)
1178 {
1179 return E_NOTIMPL;
1180 }
1181
1182 HRESULT STDMETHODCALLTYPE CInternetToolbar::AddString(const GUID *pguidCmdGroup,
1183 HINSTANCE param10, LPCTSTR param14, long *param18)
1184 {
1185 long result;
1186
1187 result = (long)::SendMessage(fToolbarWindow, TB_ADDSTRINGW,
1188 reinterpret_cast<WPARAM>(param10), reinterpret_cast<LPARAM>(param14));
1189 *param18 = result;
1190 if (result == -1)
1191 return E_FAIL;
1192 return S_OK;
1193 }
1194
1195 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetButton(const GUID *pguidCmdGroup, long param10, long param14)
1196 {
1197 return E_NOTIMPL;
1198 }
1199
1200 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetState(const GUID *pguidCmdGroup, long commandID, long *theState)
1201 {
1202 if (theState == NULL)
1203 return E_POINTER;
1204 // map the command id
1205 *theState = (long)::SendMessage(fToolbarWindow, TB_GETSTATE, commandID, 0);
1206 return S_OK;
1207 }
1208
1209 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetState(const GUID *pguidCmdGroup, long commandID, long theState)
1210 {
1211 // map the command id
1212 ::SendMessage(fToolbarWindow, TB_SETSTATE, commandID, MAKELONG(theState, 0));
1213 return S_OK;
1214 }
1215
1216 HRESULT STDMETHODCALLTYPE CInternetToolbar::AddBitmap(const GUID *pguidCmdGroup, long param10, long buttonCount,
1217 TBADDBITMAP *lParam, long *newIndex, COLORREF param20)
1218 {
1219 return E_NOTIMPL;
1220 }
1221
1222 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetBitmapSize(long *paramC)
1223 {
1224 if (paramC == NULL)
1225 return E_POINTER;
1226 *paramC = MAKELONG(24, 24);
1227 return S_OK;
1228 }
1229
1230 HRESULT STDMETHODCALLTYPE CInternetToolbar::SendToolbarMsg(const GUID *pguidCmdGroup, UINT uMsg,
1231 WPARAM wParam, LPARAM lParam, LRESULT *result)
1232 {
1233 return E_NOTIMPL;
1234 }
1235
1236 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetImageList(const GUID *pguidCmdGroup, HIMAGELIST param10,
1237 HIMAGELIST param14, HIMAGELIST param18)
1238 {
1239 return E_NOTIMPL;
1240 }
1241
1242 HRESULT STDMETHODCALLTYPE CInternetToolbar::ModifyButton(const GUID *pguidCmdGroup, long param10, long param14)
1243 {
1244 return E_NOTIMPL;
1245 }
1246
1247 HRESULT STDMETHODCALLTYPE CInternetToolbar::OnChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
1248 {
1249 return E_NOTIMPL;
1250 }
1251
1252 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetSite(IUnknown *pUnkSite)
1253 {
1254 CComPtr<IBrowserService> browserService;
1255 CComPtr<IServiceProvider> serviceProvider;
1256 CComPtr<IOleWindow> oleWindow;
1257 HWND ownerWindow;
1258 HWND dockContainer;
1259 HRESULT hResult;
1260
1261 if (pUnkSite == NULL)
1262 {
1263 hResult = AtlUnadvise(fSite, DIID_DWebBrowserEvents, fAdviseCookie);
1264 ::DestroyWindow(fMainReBar);
1265 DestroyWindow();
1266 fSite.Release();
1267 }
1268 else
1269 {
1270 // get window handle of owner
1271 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
1272 if (FAILED(hResult))
1273 return hResult;
1274 hResult = oleWindow->GetWindow(&ownerWindow);
1275 if (FAILED(hResult))
1276 return hResult;
1277 if (ownerWindow == NULL)
1278 return E_FAIL;
1279
1280 // create dock container
1281 fSite = pUnkSite;
1282 dockContainer = SHCreateWorkerWindowW(0, ownerWindow, 0,
1283 WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, NULL, 0);
1284 if (dockContainer == NULL)
1285 return E_FAIL;
1286 SubclassWindow(dockContainer);
1287
1288 // create rebar in dock container
1289 DWORD style = WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
1290 RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_REGISTERDROP | RBS_AUTOSIZE | RBS_DBLCLKTOGGLE |
1291 CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_TOP;
1292 DWORD exStyle = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_TOOLWINDOW;
1293 fMainReBar = CreateWindowEx(exStyle, REBARCLASSNAMEW, NULL, style,
1294 0, 0, 700, 60, dockContainer, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
1295 if (fMainReBar == NULL)
1296 return E_FAIL;
1297
1298 // take advice to watch events
1299 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
1300 hResult = serviceProvider->QueryService(
1301 SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
1302 hResult = AtlAdvise(browserService, static_cast<IDispatch *>(this), DIID_DWebBrowserEvents, &fAdviseCookie);
1303 }
1304 return S_OK;
1305 }
1306
1307 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetSite(REFIID riid, void **ppvSite)
1308 {
1309 if (ppvSite == NULL)
1310 return E_POINTER;
1311 if (fSite.p != NULL)
1312 return fSite->QueryInterface(riid, ppvSite);
1313 *ppvSite = NULL;
1314 return S_OK;
1315 }
1316
1317 HRESULT STDMETHODCALLTYPE CInternetToolbar::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
1318 {
1319 CComPtr<IServiceProvider> serviceProvider;
1320 HRESULT hResult;
1321
1322 if (IsEqualIID(guidService, IID_IBandSite))
1323 return this->QueryInterface(riid, ppvObject);
1324 if (IsEqualIID(guidService, SID_IBandProxy))
1325 {
1326 if (fBandProxy.p == NULL)
1327 {
1328 hResult = CreateAndInitBandProxy();
1329 if (FAILED(hResult))
1330 return hResult;
1331 }
1332 return fBandProxy->QueryInterface(riid, ppvObject);
1333 }
1334 return IUnknown_QueryService(fSite, guidService, riid, ppvObject);
1335 }
1336
1337 HRESULT STDMETHODCALLTYPE CInternetToolbar::OnWinEvent(
1338 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
1339 {
1340 HRESULT hResult;
1341
1342 if (fMenuBar)
1343 {
1344 hResult = IUnknown_RelayWinEvent(fMenuBar, hWnd, uMsg, wParam, lParam, theResult);
1345 if (hResult != S_FALSE)
1346 return hResult;
1347 }
1348
1349 if (fNavigationBar)
1350 {
1351 hResult = IUnknown_RelayWinEvent(fNavigationBar, hWnd, uMsg, wParam, lParam, theResult);
1352 if (hResult != S_FALSE)
1353 return hResult;
1354 }
1355
1356 if (fLogoBar)
1357 {
1358 hResult = IUnknown_RelayWinEvent(fLogoBar, hWnd, uMsg, wParam, lParam, theResult);
1359 if (hResult != S_FALSE)
1360 return hResult;
1361 }
1362
1363 return S_FALSE;
1364 }
1365
1366 HRESULT STDMETHODCALLTYPE CInternetToolbar::IsWindowOwner(HWND hWnd)
1367 {
1368 UNIMPLEMENTED;
1369 return E_NOTIMPL;
1370 }
1371
1372 HRESULT STDMETHODCALLTYPE CInternetToolbar::AddBand(IUnknown *punk)
1373 {
1374 UNIMPLEMENTED;
1375 return E_NOTIMPL;
1376 }
1377
1378 HRESULT STDMETHODCALLTYPE CInternetToolbar::EnumBands(UINT uBand, DWORD *pdwBandID)
1379 {
1380 UNIMPLEMENTED;
1381 return E_NOTIMPL;
1382 }
1383
1384 HRESULT STDMETHODCALLTYPE CInternetToolbar::QueryBand(DWORD dwBandID,
1385 IDeskBand **ppstb, DWORD *pdwState, LPWSTR pszName, int cchName)
1386 {
1387 if (ppstb == NULL)
1388 return E_POINTER;
1389 if (dwBandID == ITBBID_MENUBAND && fMenuBar.p != NULL)
1390 return fMenuBar->QueryInterface(IID_PPV_ARG(IDeskBand, ppstb));
1391 //if (dwBandID == ITBBID_BRANDBAND && fLogoBar.p != NULL)
1392 // return fLogoBar->QueryInterface(IID_PPV_ARG(IDeskBand, ppstb));
1393 *ppstb = NULL;
1394 return E_FAIL;
1395 }
1396
1397 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState)
1398 {
1399 return E_NOTIMPL;
1400 }
1401
1402 HRESULT STDMETHODCALLTYPE CInternetToolbar::RemoveBand(DWORD dwBandID)
1403 {
1404 return E_NOTIMPL;
1405 }
1406
1407 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetBandObject(DWORD dwBandID, REFIID riid, void **ppv)
1408 {
1409 return E_NOTIMPL;
1410 }
1411
1412 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetBandSiteInfo(const BANDSITEINFO *pbsinfo)
1413 {
1414 return E_NOTIMPL;
1415 }
1416
1417 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetBandSiteInfo(BANDSITEINFO *pbsinfo)
1418 {
1419 return E_NOTIMPL;
1420 }
1421
1422 LRESULT CInternetToolbar::OnTravelBack(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1423 {
1424 CComPtr<IServiceProvider> serviceProvider;
1425 CComPtr<IWebBrowser> webBrowser;
1426 HRESULT hResult;
1427
1428 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
1429 if (FAILED(hResult))
1430 return 0;
1431 hResult = serviceProvider->QueryService(SID_SShellBrowser,
1432 IID_PPV_ARG(IWebBrowser, &webBrowser));
1433 if (FAILED(hResult))
1434 return 0;
1435 hResult = webBrowser->GoBack();
1436 return 1;
1437 }
1438
1439 LRESULT CInternetToolbar::OnTravelForward(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1440 {
1441 CComPtr<IServiceProvider> serviceProvider;
1442 CComPtr<IWebBrowser> webBrowser;
1443 HRESULT hResult;
1444
1445 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
1446 if (FAILED(hResult))
1447 return 0;
1448 hResult = serviceProvider->QueryService(
1449 SID_SShellBrowser, IID_PPV_ARG(IWebBrowser, &webBrowser));
1450 if (FAILED(hResult))
1451 return 0;
1452 hResult = webBrowser->GoForward();
1453 return 1;
1454 }
1455
1456 LRESULT CInternetToolbar::OnUpLevel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1457 {
1458 CComPtr<IOleCommandTarget> oleCommandTarget;
1459 HRESULT hResult;
1460
1461 hResult = fSite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
1462 if (FAILED(hResult))
1463 return hResult;
1464 hResult = oleCommandTarget->Exec(&CGID_ShellBrowser, IDM_GOTO_UPONELEVEL, 0, NULL, NULL);
1465 return 1;
1466 }
1467
1468 LRESULT CInternetToolbar::OnSearch(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1469 {
1470 CComPtr<IObjectWithSite> objectWithSite;
1471 CComPtr<IContextMenu> contextMenu;
1472 CMINVOKECOMMANDINFO commandInfo;
1473 const char *searchGUID = "{169A0691-8DF9-11d1-A1C4-00C04FD75D13}";
1474 HRESULT hResult;
1475
1476 // TODO: Query shell if this command is enabled first
1477
1478 memset(&commandInfo, 0, sizeof(commandInfo));
1479 commandInfo.cbSize = sizeof(commandInfo);
1480 commandInfo.hwnd = m_hWnd;
1481 commandInfo.lpParameters = searchGUID;
1482 commandInfo.nShow = SW_SHOWNORMAL;
1483
1484 hResult = CoCreateInstance(CLSID_ShellSearchExt, NULL, CLSCTX_INPROC_SERVER,
1485 IID_PPV_ARG(IContextMenu, &contextMenu));
1486 if (FAILED(hResult))
1487 return 0;
1488 hResult = contextMenu->QueryInterface(IID_PPV_ARG(IObjectWithSite, &objectWithSite));
1489 if (FAILED(hResult))
1490 return 0;
1491 hResult = objectWithSite->SetSite(fSite);
1492 if (FAILED(hResult))
1493 return 0;
1494 hResult = contextMenu->InvokeCommand(&commandInfo);
1495 hResult = objectWithSite->SetSite(NULL);
1496 return 0;
1497 }
1498
1499 LRESULT CInternetToolbar::OnFolders(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1500 {
1501 CComPtr<IOleCommandTarget> oleCommandTarget;
1502 HRESULT hResult;
1503
1504 hResult = fSite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
1505 if (FAILED(hResult))
1506 return hResult;
1507 hResult = oleCommandTarget->Exec(&CGID_Explorer, 0x23, 0, NULL, NULL);
1508 return 1;
1509 }
1510
1511 LRESULT CInternetToolbar::OnForwardToCommandTarget(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1512 {
1513 HRESULT hResult;
1514
1515 if (fCommandTarget.p != NULL)
1516 {
1517 hResult = fCommandTarget->Exec(&fCommandCategory, wID, 0, NULL, NULL);
1518 }
1519 return 1;
1520 }
1521
1522 LRESULT CInternetToolbar::OnMenuDropDown(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
1523 {
1524 CComPtr<IServiceProvider> serviceProvider;
1525 CComPtr<IBrowserService> browserService;
1526 CComPtr<IOleCommandTarget> commandTarget;
1527 CComPtr<ITravelLog> travelLog;
1528 NMTOOLBARW *notifyInfo;
1529 RECT bounds;
1530 HMENU newMenu;
1531 TPMPARAMS params;
1532 int selectedItem;
1533 VARIANT parmIn;
1534 OLECMD commandInfo;
1535 HRESULT hResult;
1536
1537 notifyInfo = (NMTOOLBARW *)pNMHDR;
1538 if (notifyInfo->hdr.hwndFrom != fToolbarWindow)
1539 {
1540 // not from the toolbar, keep looking for a message handler
1541 bHandled = FALSE;
1542 return 0;
1543 }
1544 SendMessage(fToolbarWindow, TB_GETRECT, notifyInfo->iItem, reinterpret_cast<LPARAM>(&bounds));
1545 ::MapWindowPoints(fToolbarWindow, NULL, reinterpret_cast<POINT *>(&bounds), 2);
1546 switch (notifyInfo->iItem)
1547 {
1548 case IDM_GOTO_BACK:
1549 newMenu = CreatePopupMenu();
1550 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
1551 hResult = serviceProvider->QueryService(
1552 SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
1553 hResult = browserService->GetTravelLog(&travelLog);
1554 hResult = travelLog->InsertMenuEntries(browserService, newMenu, 0, 1, 9, TLMENUF_BACK);
1555 hResult = browserService->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &commandTarget));
1556 commandInfo.cmdID = 0x1d;
1557 hResult = commandTarget->QueryStatus(&CGID_Explorer, 1, &commandInfo, NULL);
1558 if ((commandInfo.cmdf & (OLECMDF_ENABLED | OLECMDF_LATCHED)) == OLECMDF_ENABLED &&
1559 travelLog->CountEntries(browserService) > 1)
1560 {
1561 AppendMenu(newMenu, MF_SEPARATOR, -1, L"");
1562 AppendMenu(newMenu, MF_STRING /* | MF_OWNERDRAW */, IDM_EXPLORERBAR_HISTORY, L"&History\tCtrl+H");
1563 }
1564 params.cbSize = sizeof (params);
1565 params.rcExclude = bounds;
1566 selectedItem = TrackPopupMenuEx(newMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
1567 bounds.left, bounds.bottom, m_hWnd, &params);
1568 if (selectedItem == IDM_EXPLORERBAR_HISTORY)
1569 {
1570 V_VT(&parmIn) = VT_I4;
1571 V_I4(&parmIn) = 1;
1572 Exec(&CGID_Explorer, 0x1d, 2, &parmIn, NULL);
1573 }
1574 else if (selectedItem != 0)
1575 hResult = travelLog->Travel(browserService, -selectedItem);
1576 DestroyMenu(newMenu);
1577 break;
1578 case IDM_GOTO_FORWARD:
1579 newMenu = CreatePopupMenu();
1580 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
1581 hResult = serviceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
1582 hResult = browserService->GetTravelLog(&travelLog);
1583 hResult = travelLog->InsertMenuEntries(browserService, newMenu, 0, 1, 9, TLMENUF_FORE);
1584 hResult = browserService->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &commandTarget));
1585 commandInfo.cmdID = 0x1d;
1586 hResult = commandTarget->QueryStatus(&CGID_Explorer, 1, &commandInfo, NULL);
1587 if ((commandInfo.cmdf & (OLECMDF_ENABLED | OLECMDF_LATCHED)) == OLECMDF_ENABLED &&
1588 travelLog->CountEntries(browserService) > 1)
1589 {
1590 AppendMenu(newMenu, MF_SEPARATOR, -1, L"");
1591 AppendMenu(newMenu, MF_STRING /* | MF_OWNERDRAW */, IDM_EXPLORERBAR_HISTORY, L"&History\tCtrl+H");
1592 }
1593 params.cbSize = sizeof (params);
1594 params.rcExclude = bounds;
1595 selectedItem = TrackPopupMenuEx(newMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
1596 bounds.left, bounds.bottom, m_hWnd, &params);
1597 if (selectedItem == IDM_EXPLORERBAR_HISTORY)
1598 {
1599 V_VT(&parmIn) = VT_I4;
1600 V_I4(&parmIn) = 1;
1601 Exec(&CGID_Explorer, 0x1d, 2, &parmIn, NULL);
1602 }
1603 else if (selectedItem != 0)
1604 hResult = travelLog->Travel(browserService, -selectedItem);
1605 DestroyMenu(newMenu);
1606 break;
1607 case gViewsCommandID:
1608 VARIANT inValue;
1609 CComVariant outValue;
1610 HRESULT hResult;
1611
1612 V_VT(&inValue) = VT_INT_PTR;
1613 V_INTREF(&inValue) = reinterpret_cast<INT *>(&bounds);
1614
1615 if (fCommandTarget.p != NULL)
1616 hResult = fCommandTarget->Exec(&fCommandCategory, 0x7031, 1, &inValue, &outValue);
1617 // pvaOut is VT_I4 with value 0x403
1618 break;
1619 }
1620 return TBDDRET_DEFAULT;
1621 }
1622
1623 LRESULT CInternetToolbar::OnQueryInsert(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
1624 {
1625 return 1;
1626 }
1627
1628 LRESULT CInternetToolbar::OnQueryDelete(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
1629 {
1630 return 1;
1631 }
1632
1633 LRESULT CInternetToolbar::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1634 {
1635 HMENU contextMenuBar;
1636 HMENU contextMenu;
1637 POINT clickLocation;
1638 int command;
1639 RBHITTESTINFO hitTestInfo;
1640 REBARBANDINFOW rebarBandInfo;
1641 int bandID;
1642
1643 clickLocation.x = LOWORD(lParam);
1644 clickLocation.y = HIWORD(lParam);
1645 hitTestInfo.pt = clickLocation;
1646 ScreenToClient(&hitTestInfo.pt);
1647 SendMessage(fMainReBar, RB_HITTEST, 0, (LPARAM)&hitTestInfo);
1648 if (hitTestInfo.iBand == -1)
1649 return 0;
1650 rebarBandInfo.cbSize = sizeof(rebarBandInfo);
1651 rebarBandInfo.fMask = RBBIM_ID;
1652 SendMessage(fMainReBar, RB_GETBANDINFOW, hitTestInfo.iBand, (LPARAM)&rebarBandInfo);
1653 bandID = rebarBandInfo.wID;
1654 contextMenuBar = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_CABINET_CONTEXTMENU));
1655 contextMenu = GetSubMenu(contextMenuBar, 0);
1656 switch (bandID)
1657 {
1658 case ITBBID_MENUBAND: // menu band
1659 DeleteMenu(contextMenu, IDM_TOOLBARS_CUSTOMIZE, MF_BYCOMMAND);
1660 DeleteMenu(contextMenu, IDM_TOOLBARS_TEXTLABELS, MF_BYCOMMAND);
1661 DeleteMenu(contextMenu, IDM_TOOLBARS_GOBUTTON, MF_BYCOMMAND);
1662 break;
1663 case ITBBID_BRANDBAND: // brand band
1664 DeleteMenu(contextMenu, IDM_TOOLBARS_CUSTOMIZE, MF_BYCOMMAND);
1665 DeleteMenu(contextMenu, IDM_TOOLBARS_TEXTLABELS, MF_BYCOMMAND);
1666 DeleteMenu(contextMenu, IDM_TOOLBARS_GOBUTTON, MF_BYCOMMAND);
1667 break;
1668 case ITBBID_TOOLSBAND: // tools band
1669 DeleteMenu(contextMenu, IDM_TOOLBARS_TEXTLABELS, MF_BYCOMMAND);
1670 DeleteMenu(contextMenu, IDM_TOOLBARS_GOBUTTON, MF_BYCOMMAND);
1671 break;
1672 case ITBBID_ADDRESSBAND: // navigation band
1673 DeleteMenu(contextMenu, IDM_TOOLBARS_CUSTOMIZE, MF_BYCOMMAND);
1674 DeleteMenu(contextMenu, IDM_TOOLBARS_TEXTLABELS, MF_BYCOMMAND);
1675 break;
1676 default:
1677 break;
1678 }
1679
1680 MENUITEMINFO mii;
1681 mii.cbSize = sizeof(mii);
1682 mii.fMask = MIIM_STATE;
1683 mii.fState = fLocked ? MFS_CHECKED : MFS_UNCHECKED;
1684 command = SetMenuItemInfo(contextMenu, IDM_TOOLBARS_LOCKTOOLBARS, FALSE, &mii);
1685
1686 // TODO: use GetSystemMetrics(SM_MENUDROPALIGNMENT) to determine menu alignment
1687 command = TrackPopupMenu(contextMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
1688 clickLocation.x, clickLocation.y, 0, m_hWnd, NULL);
1689 switch (command)
1690 {
1691 case IDM_TOOLBARS_STANDARDBUTTONS: // standard buttons
1692 break;
1693 case IDM_TOOLBARS_ADDRESSBAR: // address bar
1694 break;
1695 case IDM_TOOLBARS_LINKSBAR: // links
1696 break;
1697 case IDM_TOOLBARS_LOCKTOOLBARS: // lock the toolbars
1698 LockUnlockToolbars(!fLocked);
1699 break;
1700 case IDM_TOOLBARS_CUSTOMIZE: // customize
1701 SendMessage(fToolbarWindow, TB_CUSTOMIZE, 0, 0);
1702 break;
1703 }
1704
1705 DestroyMenu(contextMenuBar);
1706 return 1;
1707 }
1708
1709 LRESULT CInternetToolbar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1710 {
1711 if (wParam != SIZE_MINIMIZED)
1712 {
1713 ::SetWindowPos(fMainReBar, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam),
1714 SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
1715 }
1716 return 1;
1717 }
1718
1719 LRESULT CInternetToolbar::OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1720 {
1721 if ((short)lParam != HTCLIENT || (HWND)wParam != m_hWnd)
1722 {
1723 bHandled = FALSE;
1724 return 0;
1725 }
1726 SetCursor(LoadCursor(NULL, IDC_SIZENS));
1727 return 1;
1728 }
1729
1730 LRESULT CInternetToolbar::OnTipText(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
1731 {
1732 CComPtr<IBrowserService> browserService;
1733 CComPtr<ITravelLog> travelLog;
1734 TOOLTIPTEXTW *pTTTW;
1735 UINT nID;
1736 wchar_t tempString[300];
1737 HRESULT hResult;
1738
1739 pTTTW = reinterpret_cast<TOOLTIPTEXTW *>(pNMHDR);
1740 if ((pTTTW->uFlags & TTF_IDISHWND) != 0)
1741 nID = ::GetDlgCtrlID((HWND)pNMHDR->idFrom);
1742 else
1743 nID = (UINT)pNMHDR->idFrom;
1744
1745 if (nID != 0)
1746 {
1747 if (nID == (UINT)IDM_GOTO_BACK || nID == (UINT)IDM_GOTO_FORWARD)
1748 {
1749 // TODO: Should this call QueryService?
1750 hResult = fSite->QueryInterface(IID_PPV_ARG(IBrowserService, &browserService));
1751 hResult = browserService->GetTravelLog(&travelLog);
1752 hResult = travelLog->GetToolTipText(browserService,
1753 (nID == (UINT)IDM_GOTO_BACK) ? TLOG_BACK : TLOG_FORE,
1754 0, tempString, 299);
1755 if (FAILED(hResult))
1756 {
1757 bHandled = FALSE;
1758 return 0;
1759 }
1760 }
1761 else
1762 tempString[0] = 0;
1763 wcsncpy (pTTTW->szText, tempString, sizeof (pTTTW->szText) / sizeof (wchar_t));
1764 ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
1765 SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1766 return 0;
1767 }
1768 return 0;
1769 }
1770
1771 LRESULT CInternetToolbar::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1772 {
1773 LRESULT theResult;
1774 HRESULT hResult;
1775
1776 hResult = OnWinEvent((HWND) lParam, uMsg, wParam, lParam, &theResult);
1777
1778 bHandled = hResult == S_OK;
1779
1780 return FAILED_UNEXPECTEDLY(hResult) ? 0 : theResult;
1781 }
1782 LRESULT CInternetToolbar::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1783 {
1784 NMHDR *notifyHeader;
1785 LRESULT theResult;
1786 HRESULT hResult;
1787
1788 notifyHeader = reinterpret_cast<NMHDR *>(lParam);
1789
1790 hResult = OnWinEvent(notifyHeader->hwndFrom, uMsg, wParam, lParam, &theResult);
1791
1792 bHandled = hResult == S_OK;
1793
1794 return FAILED_UNEXPECTEDLY(hResult) ? 0 : theResult;
1795 }
1796
1797 LRESULT CInternetToolbar::OnLDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1798 {
1799 bHandled = FALSE;
1800 if (fLocked)
1801 return 0;
1802
1803 if (wParam & MK_CONTROL)
1804 return 0;
1805
1806 fSizing = TRUE;
1807
1808 DWORD msgp = GetMessagePos();
1809
1810 fStartPosition.x = GET_X_LPARAM(msgp);
1811 fStartPosition.y = GET_Y_LPARAM(msgp);
1812
1813 RECT rc;
1814 GetWindowRect(m_hWnd, &rc);
1815
1816 fStartHeight = rc.bottom - rc.top;
1817
1818 SetCapture();
1819
1820 bHandled = TRUE;
1821 return 0;
1822 }
1823
1824 LRESULT CInternetToolbar::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1825 {
1826 bHandled = FALSE;
1827 if (!fSizing)
1828 return 0;
1829
1830 DWORD msgp = GetMessagePos();
1831
1832 POINT pt;
1833 pt.x = GET_X_LPARAM(msgp);
1834 pt.y = GET_Y_LPARAM(msgp);
1835
1836 ReserveBorderSpace(fStartHeight - fStartPosition.y + pt.y);
1837
1838 bHandled = TRUE;
1839 return 0;
1840 }
1841
1842 LRESULT CInternetToolbar::OnLUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1843 {
1844 bHandled = FALSE;
1845 if (!fSizing)
1846 return 0;
1847
1848 OnMouseMove(uMsg, wParam, lParam, bHandled);
1849
1850 fSizing = FALSE;
1851
1852 ReleaseCapture();
1853
1854 return 0;
1855 }
1856
1857 HRESULT CreateInternetToolbar(REFIID riid, void **ppv)
1858 {
1859 CInternetToolbar *theToolbar;
1860 HRESULT hResult;
1861
1862 if (ppv == NULL)
1863 return E_POINTER;
1864 *ppv = NULL;
1865 ATLTRY (theToolbar = new CComObject<CInternetToolbar>);
1866 if (theToolbar == NULL)
1867 return E_OUTOFMEMORY;
1868 hResult = theToolbar->QueryInterface (riid, reinterpret_cast<void **>(ppv));
1869 if (FAILED(hResult))
1870 {
1871 delete theToolbar;
1872 return hResult;
1873 }
1874 return S_OK;
1875 }