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