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