* Sync up to trunk head (r64829).
[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 }
681
682 void CInternetToolbar::AddDockItem(IUnknown *newItem, int bandID, int flags)
683 {
684 CComPtr<CDockSite> newSite;
685
686 newSite = new CComObject<CDockSite>;
687 newSite->Initialize(newItem, this, fMainReBar, bandID, flags);
688 }
689
690 HRESULT CInternetToolbar::ReserveBorderSpace(LONG maxHeight)
691 {
692 CComPtr<IDockingWindowSite> dockingWindowSite;
693 RECT availableBorderSpace;
694
695 HRESULT hResult = fSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &dockingWindowSite));
696 if (FAILED_UNEXPECTEDLY(hResult))
697 return hResult;
698 hResult = dockingWindowSite->GetBorderDW(static_cast<IDockingWindow *>(this), &availableBorderSpace);
699 if (FAILED_UNEXPECTEDLY(hResult))
700 return hResult;
701
702 if (availableBorderSpace.top > maxHeight)
703 {
704 availableBorderSpace.top = maxHeight;
705 }
706
707 return ResizeBorderDW(&availableBorderSpace, fSite, FALSE);
708 }
709
710 HRESULT CInternetToolbar::CreateMenuBar(IShellMenu **pMenuBar)
711 {
712 CComPtr<IShellMenu> menubar;
713 CComPtr<IShellMenuCallback> callback;
714 VARIANT menuOut;
715 HWND ownerWindow;
716 HRESULT hResult;
717
718 if (!pMenuBar)
719 return E_POINTER;
720
721 *pMenuBar = NULL;
722
723 hResult = E_FAIL;
724 #if USE_CUSTOM_MENUBAND
725 HMODULE hrs = GetModuleHandleW(L"rshell.dll");
726
727 if (!hrs) hrs = LoadLibraryW(L"rshell.dll");
728
729 if (hrs)
730 {
731 PMENUBAND_CONSTRUCTOR func = (PMENUBAND_CONSTRUCTOR) GetProcAddress(hrs, "CMenuBand_Constructor");
732 if (func)
733 {
734 hResult = func(IID_PPV_ARG(IShellMenu, &menubar));
735 }
736 }
737 #endif
738
739 menubar->AddRef();
740
741 if (FAILED_UNEXPECTEDLY(hResult))
742 {
743 hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER,
744 IID_PPV_ARG(IShellMenu, &menubar));
745 if (FAILED_UNEXPECTEDLY(hResult))
746 return hResult;
747 }
748
749 hResult = fMenuCallback->QueryInterface(IID_PPV_ARG(IShellMenuCallback, &callback));
750 if (FAILED_UNEXPECTEDLY(hResult))
751 return hResult;
752
753 hResult = menubar->Initialize(callback, -1, ANCESTORDEFAULT, SMINIT_HORIZONTAL | SMINIT_TOPLEVEL);
754 if (FAILED_UNEXPECTEDLY(hResult))
755 return hResult;
756
757 // Set Menu
758 {
759 hResult = IUnknown_Exec(fSite, CGID_Explorer, 0x35, 0, NULL, &menuOut);
760 if (FAILED_UNEXPECTEDLY(hResult))
761 return hResult;
762
763 if (V_VT(&menuOut) != VT_INT_PTR || V_INTREF(&menuOut) == NULL)
764 return E_FAIL;
765
766 hResult = IUnknown_GetWindow(fSite, &ownerWindow);
767 if (FAILED_UNEXPECTEDLY(hResult))
768 return hResult;
769
770 hResult = menubar->SetMenu((HMENU) V_INTREF(&menuOut), ownerWindow, SMSET_DONTOWN);
771 if (FAILED_UNEXPECTEDLY(hResult))
772 return hResult;
773 }
774
775 hResult = IUnknown_Exec(menubar, CGID_MenuBand, 3, 1, NULL, NULL);
776 if (FAILED_UNEXPECTEDLY(hResult))
777 return hResult;
778
779 *pMenuBar = menubar.Detach();
780
781 return S_OK;
782 }
783
784 HRESULT CInternetToolbar::CreateBrandBand(IUnknown **logoBar)
785 {
786 #if 1
787 return ::CreateBrandBand(IID_PPV_ARG(IUnknown, logoBar));
788 #else
789 return CoCreateInstance(CLSID_BrandBand, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, logoBar));
790 #endif
791 }
792
793 HRESULT CInternetToolbar::CreateToolsBar(IUnknown **toolsBar)
794 {
795 return ::CreateToolsBar(IID_PPV_ARG(IUnknown, toolsBar));
796 }
797
798 HRESULT CInternetToolbar::CreateAddressBand(IUnknown **toolsBar)
799 {
800 #if 1
801 return ::CreateAddressBand(IID_PPV_ARG(IUnknown, toolsBar));
802 #else
803 return CoCreateInstance(CLSID_SH_AddressBand, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, toolsBar));
804 #endif
805 }
806
807 HRESULT CInternetToolbar::LockUnlockToolbars(bool locked)
808 {
809 REBARBANDINFOW rebarBandInfo;
810 int bandCount;
811 CDockSite *dockSite;
812 HRESULT hResult;
813
814 if (locked != fLocked)
815 {
816 fLocked = locked;
817 rebarBandInfo.cbSize = sizeof(rebarBandInfo);
818 rebarBandInfo.fMask = RBBIM_STYLE | RBBIM_LPARAM;
819 bandCount = (int)SendMessage(fMainReBar, RB_GETBANDCOUNT, 0, 0);
820 for (INT x = 0; x < bandCount; x++)
821 {
822 SendMessage(fMainReBar, RB_GETBANDINFOW, x, (LPARAM)&rebarBandInfo);
823 dockSite = reinterpret_cast<CDockSite *>(rebarBandInfo.lParam);
824 if (dockSite != NULL)
825 {
826 rebarBandInfo.fStyle &= ~(RBBS_NOGRIPPER | RBBS_GRIPPERALWAYS);
827 if (dockSite->fFlags & CDockSite::ITF_NOGRIPPER || fLocked)
828 rebarBandInfo.fStyle |= RBBS_NOGRIPPER;
829 if (dockSite->fFlags & CDockSite::ITF_GRIPPERALWAYS && !fLocked)
830 rebarBandInfo.fStyle |= RBBS_GRIPPERALWAYS;
831 SendMessage(fMainReBar, RB_SETBANDINFOW, x, (LPARAM)&rebarBandInfo);
832 }
833 }
834 hResult = ReserveBorderSpace();
835
836 // TODO: refresh view menu?
837 }
838 return S_OK;
839 }
840
841 HRESULT CInternetToolbar::CommandStateChanged(bool newValue, int commandID)
842 {
843 HRESULT hResult;
844
845 hResult = S_OK;
846 switch (commandID)
847 {
848 case -1:
849 // loop through buttons
850 //for buttons in CLSID_CommonButtons
851 // if up, QueryStatus for up state and update it
852 //
853 //for buttons in fCommandCategory, update with QueryStatus of fCommandTarget
854 break;
855 case 1:
856 // forward
857 hResult = SetState(&CLSID_CommonButtons, IDM_GOTO_FORWARD, newValue ? TBSTATE_ENABLED : 0);
858 break;
859 case 2:
860 // back
861 hResult = SetState(&CLSID_CommonButtons, IDM_GOTO_BACK, newValue ? TBSTATE_ENABLED : 0);
862 break;
863 }
864 return hResult;
865 }
866
867 HRESULT CInternetToolbar::CreateAndInitBandProxy()
868 {
869 CComPtr<IServiceProvider> serviceProvider;
870 HRESULT hResult;
871
872 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
873 if (FAILED_UNEXPECTEDLY(hResult))
874 return hResult;
875 hResult = serviceProvider->QueryService(SID_IBandProxy, IID_PPV_ARG(IBandProxy, &fBandProxy));
876 if (FAILED_UNEXPECTEDLY(hResult))
877 {
878 hResult = CreateBandProxy(IID_PPV_ARG(IBandProxy, &fBandProxy));
879 if (FAILED_UNEXPECTEDLY(hResult))
880 return hResult;
881 hResult = fBandProxy->SetSite(fSite);
882 if (FAILED_UNEXPECTEDLY(hResult))
883 return hResult;
884 }
885 return S_OK;
886 }
887
888 HRESULT STDMETHODCALLTYPE CInternetToolbar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
889 {
890 return E_NOTIMPL;
891 }
892
893 HRESULT STDMETHODCALLTYPE CInternetToolbar::HasFocusIO()
894 {
895 HRESULT hr = S_FALSE;
896
897 if (fMenuBar)
898 hr = IUnknown_HasFocusIO(fMenuBar);
899 if (hr != S_FALSE)
900 return hr;
901
902 if (fControlsBar)
903 hr = IUnknown_HasFocusIO(fControlsBar);
904 if (hr != S_FALSE)
905 return hr;
906
907 if (fNavigationBar)
908 hr = IUnknown_HasFocusIO(fNavigationBar);
909 if (hr != S_FALSE)
910 return hr;
911
912 return S_FALSE;
913 }
914
915 HRESULT STDMETHODCALLTYPE CInternetToolbar::TranslateAcceleratorIO(LPMSG lpMsg)
916 {
917 HRESULT hr = S_FALSE;
918
919 if (fMenuBar)
920 hr = IUnknown_TranslateAcceleratorIO(fMenuBar, lpMsg);
921 if (hr == S_OK)
922 return hr;
923
924 if (fControlsBar)
925 hr = IUnknown_TranslateAcceleratorIO(fControlsBar, lpMsg);
926 if (hr == S_OK)
927 return hr;
928
929 if (fNavigationBar)
930 hr = IUnknown_TranslateAcceleratorIO(fNavigationBar, lpMsg);
931 if (hr == S_OK)
932 return hr;
933
934 return S_FALSE;
935 }
936
937 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetWindow(HWND *lphwnd)
938 {
939 if (lphwnd == NULL)
940 return E_POINTER;
941 *lphwnd = m_hWnd;
942 return S_OK;
943 }
944
945 HRESULT STDMETHODCALLTYPE CInternetToolbar::ContextSensitiveHelp(BOOL fEnterMode)
946 {
947 return E_NOTIMPL;
948 }
949
950 HRESULT STDMETHODCALLTYPE CInternetToolbar::ShowDW(BOOL fShow)
951 {
952 HRESULT hResult;
953
954 // show the bar here
955 if (fShow)
956 {
957 hResult = ReserveBorderSpace();
958 if (FAILED_UNEXPECTEDLY(hResult))
959 return hResult;
960 }
961
962 if (fMenuBar)
963 {
964 hResult = IUnknown_ShowDW(fMenuBar, fShow);
965 if (FAILED_UNEXPECTEDLY(hResult))
966 return hResult;
967 }
968
969 if (fControlsBar)
970 {
971 hResult = IUnknown_ShowDW(fControlsBar, fShow);
972 if (FAILED_UNEXPECTEDLY(hResult))
973 return hResult;
974 }
975 if (fNavigationBar)
976 {
977 hResult = IUnknown_ShowDW(fNavigationBar, fShow);
978 if (FAILED_UNEXPECTEDLY(hResult))
979 return hResult;
980 }
981 if (fLogoBar)
982 {
983 hResult = IUnknown_ShowDW(fLogoBar, fShow);
984 if (FAILED_UNEXPECTEDLY(hResult))
985 return hResult;
986 }
987 return S_OK;
988 }
989
990 template<class T>
991 void ReleaseCComPtrExpectZero(CComPtr<T>& cptr, BOOL forceRelease = FALSE)
992 {
993 if (cptr.p != NULL)
994 {
995 int nrc = cptr->Release();
996 if (nrc > 0)
997 {
998 DbgPrint("WARNING: Unexpected RefCount > 0 (%d)!\n", nrc);
999 if (forceRelease)
1000 {
1001 while (nrc > 0)
1002 {
1003 nrc = cptr->Release();
1004 }
1005 }
1006 }
1007 cptr.Detach();
1008 }
1009 }
1010
1011 HRESULT STDMETHODCALLTYPE CInternetToolbar::CloseDW(DWORD dwReserved)
1012 {
1013 HRESULT hResult;
1014
1015 if (fMenuBar)
1016 {
1017 hResult = IUnknown_CloseDW(fMenuBar, dwReserved);
1018 if (FAILED_UNEXPECTEDLY(hResult))
1019 return hResult;
1020 ReleaseCComPtrExpectZero(fMenuBar);
1021 }
1022 if (fControlsBar)
1023 {
1024 hResult = IUnknown_CloseDW(fControlsBar, dwReserved);
1025 if (FAILED_UNEXPECTEDLY(hResult))
1026 return hResult;
1027 ReleaseCComPtrExpectZero(fControlsBar);
1028 }
1029 if (fNavigationBar)
1030 {
1031 hResult = IUnknown_CloseDW(fNavigationBar, dwReserved);
1032 if (FAILED_UNEXPECTEDLY(hResult))
1033 return hResult;
1034 ReleaseCComPtrExpectZero(fNavigationBar);
1035 }
1036 if (fLogoBar)
1037 {
1038 hResult = IUnknown_CloseDW(fLogoBar, dwReserved);
1039 if (FAILED_UNEXPECTEDLY(hResult))
1040 return hResult;
1041 ReleaseCComPtrExpectZero(fLogoBar);
1042 }
1043 return S_OK;
1044 }
1045
1046 HRESULT STDMETHODCALLTYPE CInternetToolbar::ResizeBorderDW(LPCRECT prcBorder,
1047 IUnknown *punkToolbarSite, BOOL fReserved)
1048 {
1049 RECT neededBorderSpace;
1050 RECT availableBorderSpace = *prcBorder;
1051
1052 SendMessage(fMainReBar, RB_SIZETORECT, RBSTR_CHANGERECT, reinterpret_cast<LPARAM>(&availableBorderSpace));
1053
1054 // RBSTR_CHANGERECT does not seem to set the proper size in the rect.
1055 // Let's make sure we fetch the actual size properly.
1056 GetWindowRect(fMainReBar, &availableBorderSpace);
1057 neededBorderSpace.left = 0;
1058 neededBorderSpace.top = availableBorderSpace.bottom - availableBorderSpace.top;
1059 if (!fLocked)
1060 neededBorderSpace.top += 3;
1061 neededBorderSpace.right = 0;
1062 neededBorderSpace.bottom = 0;
1063
1064 CComPtr<IDockingWindowSite> dockingWindowSite;
1065
1066 HRESULT hResult = fSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &dockingWindowSite));
1067 if (FAILED_UNEXPECTEDLY(hResult))
1068 return hResult;
1069
1070 hResult = dockingWindowSite->RequestBorderSpaceDW(static_cast<IDockingWindow *>(this), &neededBorderSpace);
1071 if (FAILED_UNEXPECTEDLY(hResult))
1072 return hResult;
1073
1074 hResult = dockingWindowSite->SetBorderSpaceDW(static_cast<IDockingWindow *>(this), &neededBorderSpace);
1075 if (FAILED_UNEXPECTEDLY(hResult))
1076 return hResult;
1077
1078 return S_OK;
1079 }
1080
1081 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetClassID(CLSID *pClassID)
1082 {
1083 if (pClassID == NULL)
1084 return E_POINTER;
1085 *pClassID = CLSID_InternetToolbar;
1086 return S_OK;
1087 }
1088
1089 HRESULT STDMETHODCALLTYPE CInternetToolbar::IsDirty()
1090 {
1091 return E_NOTIMPL;
1092 }
1093
1094 HRESULT STDMETHODCALLTYPE CInternetToolbar::Load(IStream *pStm)
1095 {
1096 return E_NOTIMPL;
1097 }
1098
1099 HRESULT STDMETHODCALLTYPE CInternetToolbar::Save(IStream *pStm, BOOL fClearDirty)
1100 {
1101 return E_NOTIMPL;
1102 }
1103
1104 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetSizeMax(ULARGE_INTEGER *pcbSize)
1105 {
1106 return E_NOTIMPL;
1107 }
1108
1109 HRESULT STDMETHODCALLTYPE CInternetToolbar::InitNew()
1110 {
1111 CComPtr<IShellMenu> menuBar;
1112 CComPtr<IUnknown> logoBar;
1113 CComPtr<IUnknown> toolsBar;
1114 CComPtr<IUnknown> navigationBar;
1115 HRESULT hResult;
1116
1117 /* Create and attach the menubar to the rebar */
1118 hResult = CreateMenuBar(&menuBar);
1119 if (FAILED_UNEXPECTEDLY(hResult))
1120 return hResult;
1121 AddDockItem(menuBar, ITBBID_MENUBAND, CDockSite::ITF_NOTITLE | CDockSite::ITF_NEWBANDALWAYS | CDockSite::ITF_GRIPPERALWAYS);
1122
1123 hResult = IUnknown_GetWindow(menuBar, &fMenuBandWindow);
1124 fMenuBar.Attach(menuBar.Detach()); // transfer the ref count
1125
1126 // FIXME: The ros Rebar does not properly support fixed-size items such as the brandband,
1127 // and it will put them in their own row, sized to take up the whole row.
1128 #if 0
1129 /* Create and attach the brand/logo to the rebar */
1130 hResult = CreateBrandBand(&logoBar);
1131 if (FAILED_UNEXPECTEDLY(hResult))
1132 return hResult;
1133 AddDockItem(logoBar, ITBBID_BRANDBAND, CDockSite::ITF_NOGRIPPER | CDockSite::ITF_NOTITLE | CDockSite::ITF_FIXEDSIZE);
1134 fLogoBar.Attach(logoBar.Detach()); // transfer the ref count
1135 #endif
1136
1137 /* Create and attach the standard toolbar to the rebar */
1138 hResult = CreateToolsBar(&toolsBar);
1139 if (FAILED_UNEXPECTEDLY(hResult))
1140 return hResult;
1141 AddDockItem(toolsBar, ITBBID_TOOLSBAND, CDockSite::ITF_NOTITLE | CDockSite::ITF_NEWBANDALWAYS | CDockSite::ITF_GRIPPERALWAYS);
1142 fControlsBar.Attach(toolsBar.Detach()); // transfer the ref count
1143 hResult = IUnknown_GetWindow(fControlsBar, &fToolbarWindow);
1144 if (FAILED_UNEXPECTEDLY(hResult))
1145 return hResult;
1146
1147 /* Create and attach the address/navigation toolbar to the rebar */
1148 hResult = CreateAddressBand(&navigationBar);
1149 if (FAILED_UNEXPECTEDLY(hResult))
1150 return hResult;
1151 AddDockItem(navigationBar, ITBBID_ADDRESSBAND, CDockSite::ITF_NEWBANDALWAYS | CDockSite::ITF_GRIPPERALWAYS);
1152 fNavigationBar.Attach(navigationBar.Detach());
1153 hResult = IUnknown_GetWindow(fNavigationBar, &fNavigationWindow);
1154
1155 return S_OK;
1156 }
1157
1158 HRESULT STDMETHODCALLTYPE CInternetToolbar::QueryStatus(const GUID *pguidCmdGroup,
1159 ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
1160 {
1161 if (IsEqualIID(*pguidCmdGroup, CGID_PrivCITCommands))
1162 {
1163 while (cCmds != 0)
1164 {
1165 switch (prgCmds->cmdID)
1166 {
1167 case ITID_TEXTLABELS: // Text Labels state
1168 prgCmds->cmdf = OLECMDF_SUPPORTED;
1169 break;
1170 case ITID_TOOLBARBANDSHOWN: // toolbar visibility
1171 prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1172 break;
1173 case ITID_ADDRESSBANDSHOWN: // address bar visibility
1174 prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1175 break;
1176 case ITID_LINKSBANDSHOWN: // links bar visibility
1177 prgCmds->cmdf = 0;
1178 break;
1179 case ITID_MENUBANDSHOWN: // Menubar band visibility
1180 prgCmds->cmdf = 0;
1181 break;
1182 case ITID_AUTOHIDEENABLED: // Auto hide enabled/disabled
1183 prgCmds->cmdf = 0;
1184 break;
1185 case ITID_CUSTOMIZEENABLED: // customize enabled
1186 prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1187 break;
1188 case ITID_TOOLBARLOCKED: // lock toolbars
1189 prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1190 if (fLocked)
1191 prgCmds->cmdf |= OLECMDF_LATCHED;
1192 break;
1193 default:
1194 prgCmds->cmdf = 0;
1195 break;
1196 }
1197 prgCmds++;
1198 cCmds--;
1199 }
1200 return S_OK;
1201 }
1202 return E_FAIL;
1203 }
1204
1205 HRESULT STDMETHODCALLTYPE CInternetToolbar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
1206 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
1207 {
1208 if (IsEqualIID(*pguidCmdGroup, CGID_PrivCITCommands))
1209 {
1210 switch (nCmdID)
1211 {
1212 case 1:
1213 // what do I do here?
1214 return S_OK;
1215 case ITID_TEXTLABELS:
1216 // toggle text labels
1217 return S_OK;
1218 case ITID_TOOLBARBANDSHOWN:
1219 // toggle toolbar band visibility
1220 return S_OK;
1221 case ITID_ADDRESSBANDSHOWN:
1222 // toggle address band visibility
1223 return S_OK;
1224 case ITID_LINKSBANDSHOWN:
1225 // toggle links band visibility
1226 return S_OK;
1227 case ITID_CUSTOMIZEENABLED:
1228 // run customize
1229 return S_OK;
1230 case ITID_TOOLBARLOCKED:
1231 return LockUnlockToolbars(!fLocked);
1232 }
1233 }
1234 return E_FAIL;
1235 }
1236
1237 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetTypeInfoCount(UINT *pctinfo)
1238 {
1239 return E_NOTIMPL;
1240 }
1241
1242 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1243 {
1244 return E_NOTIMPL;
1245 }
1246
1247 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
1248 LCID lcid, DISPID *rgDispId)
1249 {
1250 return E_NOTIMPL;
1251 }
1252
1253 HRESULT STDMETHODCALLTYPE CInternetToolbar::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
1254 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1255 {
1256 HRESULT hResult;
1257
1258 switch(dispIdMember)
1259 {
1260 case DISPID_BEFORENAVIGATE:
1261 hResult = S_OK;
1262 break;
1263 case DISPID_DOWNLOADCOMPLETE:
1264 hResult = S_OK;
1265 break;
1266 case DISPID_COMMANDSTATECHANGE:
1267 if (pDispParams->cArgs != 2)
1268 return E_INVALIDARG;
1269 if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL || V_VT(&pDispParams->rgvarg[1]) != VT_I4)
1270 return E_INVALIDARG;
1271 return CommandStateChanged(V_BOOL(&pDispParams->rgvarg[0]) != VARIANT_FALSE,
1272 V_I4(&pDispParams->rgvarg[1]));
1273 case DISPID_DOWNLOADBEGIN:
1274 hResult = S_OK;
1275 break;
1276 case DISPID_NAVIGATECOMPLETE2:
1277 hResult = S_OK;
1278 break;
1279 case DISPID_DOCUMENTCOMPLETE:
1280 hResult = S_OK;
1281 break;
1282 }
1283 return S_OK;
1284 }
1285
1286 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetCommandTarget(IUnknown *theTarget, GUID *category, long param14)
1287 {
1288 HRESULT hResult;
1289
1290 TRACE("SetCommandTarget %p category %s param %d\n", theTarget, wine_dbgstr_guid(category), param14);
1291
1292 fCommandTarget.Release();
1293 hResult = theTarget->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &fCommandTarget));
1294 if (FAILED_UNEXPECTEDLY(hResult))
1295 return hResult;
1296 fCommandCategory = *category;
1297 return S_OK;
1298 }
1299
1300 HRESULT STDMETHODCALLTYPE CInternetToolbar::Unknown1()
1301 {
1302 return E_NOTIMPL;
1303 }
1304
1305 HRESULT STDMETHODCALLTYPE CInternetToolbar::AddButtons(const GUID *pguidCmdGroup, long buttonCount, TBBUTTON *buttons)
1306 {
1307 return E_NOTIMPL;
1308 }
1309
1310 HRESULT STDMETHODCALLTYPE CInternetToolbar::AddString(const GUID *pguidCmdGroup,
1311 HINSTANCE param10, LPCTSTR param14, long *param18)
1312 {
1313 long result;
1314
1315 result = (long)::SendMessage(fToolbarWindow, TB_ADDSTRINGW,
1316 reinterpret_cast<WPARAM>(param10), reinterpret_cast<LPARAM>(param14));
1317 *param18 = result;
1318 if (result == -1)
1319 return E_FAIL;
1320 return S_OK;
1321 }
1322
1323 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetButton(const GUID *pguidCmdGroup, long param10, long param14)
1324 {
1325 return E_NOTIMPL;
1326 }
1327
1328 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetState(const GUID *pguidCmdGroup, long commandID, long *theState)
1329 {
1330 if (theState == NULL)
1331 return E_POINTER;
1332 // map the command id
1333 *theState = (long)::SendMessage(fToolbarWindow, TB_GETSTATE, commandID, 0);
1334 return S_OK;
1335 }
1336
1337 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetState(const GUID *pguidCmdGroup, long commandID, long theState)
1338 {
1339 // map the command id
1340 ::SendMessage(fToolbarWindow, TB_SETSTATE, commandID, MAKELONG(theState, 0));
1341 return S_OK;
1342 }
1343
1344 HRESULT STDMETHODCALLTYPE CInternetToolbar::AddBitmap(const GUID *pguidCmdGroup, long param10, long buttonCount,
1345 TBADDBITMAP *lParam, long *newIndex, COLORREF param20)
1346 {
1347 return E_NOTIMPL;
1348 }
1349
1350 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetBitmapSize(long *paramC)
1351 {
1352 if (paramC == NULL)
1353 return E_POINTER;
1354 *paramC = MAKELONG(24, 24);
1355 return S_OK;
1356 }
1357
1358 HRESULT STDMETHODCALLTYPE CInternetToolbar::SendToolbarMsg(const GUID *pguidCmdGroup, UINT uMsg,
1359 WPARAM wParam, LPARAM lParam, LRESULT *result)
1360 {
1361 return E_NOTIMPL;
1362 }
1363
1364 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetImageList(const GUID *pguidCmdGroup, HIMAGELIST param10,
1365 HIMAGELIST param14, HIMAGELIST param18)
1366 {
1367 return E_NOTIMPL;
1368 }
1369
1370 HRESULT STDMETHODCALLTYPE CInternetToolbar::ModifyButton(const GUID *pguidCmdGroup, long param10, long param14)
1371 {
1372 return E_NOTIMPL;
1373 }
1374
1375 HRESULT STDMETHODCALLTYPE CInternetToolbar::OnChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
1376 {
1377 return E_NOTIMPL;
1378 }
1379
1380 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetSite(IUnknown *pUnkSite)
1381 {
1382 CComPtr<IBrowserService> browserService;
1383 CComPtr<IServiceProvider> serviceProvider;
1384 CComPtr<IOleWindow> oleWindow;
1385 HWND ownerWindow;
1386 HWND dockContainer;
1387 HRESULT hResult;
1388
1389 if (pUnkSite == NULL)
1390 {
1391 hResult = AtlUnadvise(fSite, DIID_DWebBrowserEvents, fAdviseCookie);
1392 ::DestroyWindow(fMainReBar);
1393 DestroyWindow();
1394 fSite.Release();
1395 }
1396 else
1397 {
1398 // get window handle of owner
1399 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
1400 if (FAILED_UNEXPECTEDLY(hResult))
1401 return hResult;
1402 hResult = oleWindow->GetWindow(&ownerWindow);
1403 if (FAILED_UNEXPECTEDLY(hResult))
1404 return hResult;
1405 if (ownerWindow == NULL)
1406 return E_FAIL;
1407
1408 // create dock container
1409 fSite = pUnkSite;
1410 dockContainer = SHCreateWorkerWindowW(0, ownerWindow, 0,
1411 WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, NULL, 0);
1412 if (dockContainer == NULL)
1413 return E_FAIL;
1414 SubclassWindow(dockContainer);
1415
1416 // create rebar in dock container
1417 DWORD style = WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
1418 RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_REGISTERDROP | RBS_AUTOSIZE | RBS_DBLCLKTOGGLE |
1419 CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_TOP;
1420 DWORD exStyle = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_TOOLWINDOW;
1421 fMainReBar = CreateWindowEx(exStyle, REBARCLASSNAMEW, NULL, style,
1422 0, 0, 700, 60, dockContainer, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
1423 if (fMainReBar == NULL)
1424 return E_FAIL;
1425
1426 // take advice to watch events
1427 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
1428 hResult = serviceProvider->QueryService(
1429 SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
1430 hResult = AtlAdvise(browserService, static_cast<IDispatch *>(this), DIID_DWebBrowserEvents, &fAdviseCookie);
1431 }
1432 return S_OK;
1433 }
1434
1435 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetSite(REFIID riid, void **ppvSite)
1436 {
1437 if (ppvSite == NULL)
1438 return E_POINTER;
1439 if (fSite.p != NULL)
1440 return fSite->QueryInterface(riid, ppvSite);
1441 *ppvSite = NULL;
1442 return S_OK;
1443 }
1444
1445 HRESULT STDMETHODCALLTYPE CInternetToolbar::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
1446 {
1447 CComPtr<IServiceProvider> serviceProvider;
1448 HRESULT hResult;
1449
1450 if (IsEqualIID(guidService, IID_IBandSite))
1451 return this->QueryInterface(riid, ppvObject);
1452 if (IsEqualIID(guidService, SID_IBandProxy))
1453 {
1454 if (fBandProxy.p == NULL)
1455 {
1456 hResult = CreateAndInitBandProxy();
1457 if (FAILED_UNEXPECTEDLY(hResult))
1458 return hResult;
1459 }
1460 return fBandProxy->QueryInterface(riid, ppvObject);
1461 }
1462 return IUnknown_QueryService(fSite, guidService, riid, ppvObject);
1463 }
1464
1465 HRESULT STDMETHODCALLTYPE CInternetToolbar::OnWinEvent(
1466 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
1467 {
1468 HRESULT hResult;
1469
1470 if (fMenuBar)
1471 {
1472 hResult = IUnknown_RelayWinEvent(fMenuBar, hWnd, uMsg, wParam, lParam, theResult);
1473 if (hResult != S_FALSE)
1474 return hResult;
1475 }
1476
1477 if (fNavigationBar)
1478 {
1479 hResult = IUnknown_RelayWinEvent(fNavigationBar, hWnd, uMsg, wParam, lParam, theResult);
1480 if (hResult != S_FALSE)
1481 return hResult;
1482 }
1483
1484 if (fLogoBar)
1485 {
1486 hResult = IUnknown_RelayWinEvent(fLogoBar, hWnd, uMsg, wParam, lParam, theResult);
1487 if (hResult != S_FALSE)
1488 return hResult;
1489 }
1490
1491 return S_FALSE;
1492 }
1493
1494 HRESULT STDMETHODCALLTYPE CInternetToolbar::IsWindowOwner(HWND hWnd)
1495 {
1496 UNIMPLEMENTED;
1497 return E_NOTIMPL;
1498 }
1499
1500 HRESULT STDMETHODCALLTYPE CInternetToolbar::AddBand(IUnknown *punk)
1501 {
1502 UNIMPLEMENTED;
1503 return E_NOTIMPL;
1504 }
1505
1506 HRESULT STDMETHODCALLTYPE CInternetToolbar::EnumBands(UINT uBand, DWORD *pdwBandID)
1507 {
1508 UNIMPLEMENTED;
1509 return E_NOTIMPL;
1510 }
1511
1512 HRESULT STDMETHODCALLTYPE CInternetToolbar::QueryBand(DWORD dwBandID,
1513 IDeskBand **ppstb, DWORD *pdwState, LPWSTR pszName, int cchName)
1514 {
1515 if (ppstb == NULL)
1516 return E_POINTER;
1517 if (dwBandID == ITBBID_MENUBAND && fMenuBar.p != NULL)
1518 return fMenuBar->QueryInterface(IID_PPV_ARG(IDeskBand, ppstb));
1519 //if (dwBandID == ITBBID_BRANDBAND && fLogoBar.p != NULL)
1520 // return fLogoBar->QueryInterface(IID_PPV_ARG(IDeskBand, ppstb));
1521 *ppstb = NULL;
1522 return E_FAIL;
1523 }
1524
1525 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState)
1526 {
1527 UNIMPLEMENTED;
1528 return E_NOTIMPL;
1529 }
1530
1531 HRESULT STDMETHODCALLTYPE CInternetToolbar::RemoveBand(DWORD dwBandID)
1532 {
1533 UNIMPLEMENTED;
1534 return E_NOTIMPL;
1535 }
1536
1537 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetBandObject(DWORD dwBandID, REFIID riid, void **ppv)
1538 {
1539 UNIMPLEMENTED;
1540 return E_NOTIMPL;
1541 }
1542
1543 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetBandSiteInfo(const BANDSITEINFO *pbsinfo)
1544 {
1545 UNIMPLEMENTED;
1546 return E_NOTIMPL;
1547 }
1548
1549 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetBandSiteInfo(BANDSITEINFO *pbsinfo)
1550 {
1551 UNIMPLEMENTED;
1552 return E_NOTIMPL;
1553 }
1554
1555 LRESULT CInternetToolbar::OnTravelBack(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1556 {
1557 CComPtr<IServiceProvider> serviceProvider;
1558 CComPtr<IWebBrowser> webBrowser;
1559 HRESULT hResult;
1560
1561 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
1562 if (FAILED_UNEXPECTEDLY(hResult))
1563 return 0;
1564 hResult = serviceProvider->QueryService(SID_SShellBrowser,
1565 IID_PPV_ARG(IWebBrowser, &webBrowser));
1566 if (FAILED_UNEXPECTEDLY(hResult))
1567 return 0;
1568 hResult = webBrowser->GoBack();
1569 return 1;
1570 }
1571
1572 LRESULT CInternetToolbar::OnTravelForward(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1573 {
1574 CComPtr<IServiceProvider> serviceProvider;
1575 CComPtr<IWebBrowser> webBrowser;
1576 HRESULT hResult;
1577
1578 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
1579 if (FAILED_UNEXPECTEDLY(hResult))
1580 return 0;
1581 hResult = serviceProvider->QueryService(
1582 SID_SShellBrowser, IID_PPV_ARG(IWebBrowser, &webBrowser));
1583 if (FAILED_UNEXPECTEDLY(hResult))
1584 return 0;
1585 hResult = webBrowser->GoForward();
1586 return 1;
1587 }
1588
1589 LRESULT CInternetToolbar::OnUpLevel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1590 {
1591 CComPtr<IOleCommandTarget> oleCommandTarget;
1592 HRESULT hResult;
1593
1594 hResult = fSite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
1595 if (FAILED_UNEXPECTEDLY(hResult))
1596 return hResult;
1597 hResult = oleCommandTarget->Exec(&CGID_ShellBrowser, IDM_GOTO_UPONELEVEL, 0, NULL, NULL);
1598 return 1;
1599 }
1600
1601 LRESULT CInternetToolbar::OnSearch(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1602 {
1603 CComPtr<IObjectWithSite> objectWithSite;
1604 CComPtr<IContextMenu> contextMenu;
1605 CMINVOKECOMMANDINFO commandInfo;
1606 const char *searchGUID = "{169A0691-8DF9-11d1-A1C4-00C04FD75D13}";
1607 HRESULT hResult;
1608
1609 // TODO: Query shell if this command is enabled first
1610
1611 memset(&commandInfo, 0, sizeof(commandInfo));
1612 commandInfo.cbSize = sizeof(commandInfo);
1613 commandInfo.hwnd = m_hWnd;
1614 commandInfo.lpParameters = searchGUID;
1615 commandInfo.nShow = SW_SHOWNORMAL;
1616
1617 hResult = CoCreateInstance(CLSID_ShellSearchExt, NULL, CLSCTX_INPROC_SERVER,
1618 IID_PPV_ARG(IContextMenu, &contextMenu));
1619 if (FAILED_UNEXPECTEDLY(hResult))
1620 return 0;
1621 hResult = contextMenu->QueryInterface(IID_PPV_ARG(IObjectWithSite, &objectWithSite));
1622 if (FAILED_UNEXPECTEDLY(hResult))
1623 return 0;
1624 hResult = objectWithSite->SetSite(fSite);
1625 if (FAILED_UNEXPECTEDLY(hResult))
1626 return 0;
1627 hResult = contextMenu->InvokeCommand(&commandInfo);
1628 hResult = objectWithSite->SetSite(NULL);
1629 return 0;
1630 }
1631
1632 LRESULT CInternetToolbar::OnFolders(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1633 {
1634 CComPtr<IOleCommandTarget> oleCommandTarget;
1635 HRESULT hResult;
1636
1637 hResult = fSite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
1638 if (FAILED_UNEXPECTEDLY(hResult))
1639 return hResult;
1640 hResult = oleCommandTarget->Exec(&CGID_Explorer, 0x23, 0, NULL, NULL);
1641 return 1;
1642 }
1643
1644 LRESULT CInternetToolbar::OnForwardToCommandTarget(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
1645 {
1646 HRESULT hResult;
1647
1648 if (fCommandTarget.p != NULL)
1649 {
1650 hResult = fCommandTarget->Exec(&fCommandCategory, wID, 0, NULL, NULL);
1651 }
1652 return 1;
1653 }
1654
1655 LRESULT CInternetToolbar::OnMenuDropDown(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
1656 {
1657 CComPtr<IServiceProvider> serviceProvider;
1658 CComPtr<IBrowserService> browserService;
1659 CComPtr<IOleCommandTarget> commandTarget;
1660 CComPtr<ITravelLog> travelLog;
1661 NMTOOLBARW *notifyInfo;
1662 RECT bounds;
1663 HMENU newMenu;
1664 TPMPARAMS params;
1665 int selectedItem;
1666 VARIANT parmIn;
1667 OLECMD commandInfo;
1668 HRESULT hResult;
1669
1670 notifyInfo = (NMTOOLBARW *)pNMHDR;
1671 if (notifyInfo->hdr.hwndFrom != fToolbarWindow)
1672 {
1673 // not from the toolbar, keep looking for a message handler
1674 bHandled = FALSE;
1675 return 0;
1676 }
1677 SendMessage(fToolbarWindow, TB_GETRECT, notifyInfo->iItem, reinterpret_cast<LPARAM>(&bounds));
1678 ::MapWindowPoints(fToolbarWindow, NULL, reinterpret_cast<POINT *>(&bounds), 2);
1679 switch (notifyInfo->iItem)
1680 {
1681 case IDM_GOTO_BACK:
1682 newMenu = CreatePopupMenu();
1683 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
1684 hResult = serviceProvider->QueryService(
1685 SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
1686 hResult = browserService->GetTravelLog(&travelLog);
1687 hResult = travelLog->InsertMenuEntries(browserService, newMenu, 0, 1, 9, TLMENUF_BACK);
1688 hResult = browserService->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &commandTarget));
1689 commandInfo.cmdID = 0x1d;
1690 hResult = commandTarget->QueryStatus(&CGID_Explorer, 1, &commandInfo, NULL);
1691 if ((commandInfo.cmdf & (OLECMDF_ENABLED | OLECMDF_LATCHED)) == OLECMDF_ENABLED &&
1692 travelLog->CountEntries(browserService) > 1)
1693 {
1694 AppendMenu(newMenu, MF_SEPARATOR, -1, L"");
1695 AppendMenu(newMenu, MF_STRING /* | MF_OWNERDRAW */, IDM_EXPLORERBAR_HISTORY, L"&History\tCtrl+H");
1696 }
1697 params.cbSize = sizeof (params);
1698 params.rcExclude = bounds;
1699 selectedItem = TrackPopupMenuEx(newMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
1700 bounds.left, bounds.bottom, m_hWnd, &params);
1701 if (selectedItem == IDM_EXPLORERBAR_HISTORY)
1702 {
1703 V_VT(&parmIn) = VT_I4;
1704 V_I4(&parmIn) = 1;
1705 Exec(&CGID_Explorer, 0x1d, 2, &parmIn, NULL);
1706 }
1707 else if (selectedItem != 0)
1708 hResult = travelLog->Travel(browserService, -selectedItem);
1709 DestroyMenu(newMenu);
1710 break;
1711 case IDM_GOTO_FORWARD:
1712 newMenu = CreatePopupMenu();
1713 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
1714 hResult = serviceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
1715 hResult = browserService->GetTravelLog(&travelLog);
1716 hResult = travelLog->InsertMenuEntries(browserService, newMenu, 0, 1, 9, TLMENUF_FORE);
1717 hResult = browserService->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &commandTarget));
1718 commandInfo.cmdID = 0x1d;
1719 hResult = commandTarget->QueryStatus(&CGID_Explorer, 1, &commandInfo, NULL);
1720 if ((commandInfo.cmdf & (OLECMDF_ENABLED | OLECMDF_LATCHED)) == OLECMDF_ENABLED &&
1721 travelLog->CountEntries(browserService) > 1)
1722 {
1723 AppendMenu(newMenu, MF_SEPARATOR, -1, L"");
1724 AppendMenu(newMenu, MF_STRING /* | MF_OWNERDRAW */, IDM_EXPLORERBAR_HISTORY, L"&History\tCtrl+H");
1725 }
1726 params.cbSize = sizeof (params);
1727 params.rcExclude = bounds;
1728 selectedItem = TrackPopupMenuEx(newMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
1729 bounds.left, bounds.bottom, m_hWnd, &params);
1730 if (selectedItem == IDM_EXPLORERBAR_HISTORY)
1731 {
1732 V_VT(&parmIn) = VT_I4;
1733 V_I4(&parmIn) = 1;
1734 Exec(&CGID_Explorer, 0x1d, 2, &parmIn, NULL);
1735 }
1736 else if (selectedItem != 0)
1737 hResult = travelLog->Travel(browserService, -selectedItem);
1738 DestroyMenu(newMenu);
1739 break;
1740 case gViewsCommandID:
1741 VARIANT inValue;
1742 CComVariant outValue;
1743 HRESULT hResult;
1744
1745 V_VT(&inValue) = VT_INT_PTR;
1746 V_INTREF(&inValue) = reinterpret_cast<INT *>(&bounds);
1747
1748 if (fCommandTarget.p != NULL)
1749 hResult = fCommandTarget->Exec(&fCommandCategory, FCIDM_SHVIEW_AUTOARRANGE, 1, &inValue, &outValue);
1750 // pvaOut is VT_I4 with value 0x403
1751 break;
1752 }
1753 return TBDDRET_DEFAULT;
1754 }
1755
1756 LRESULT CInternetToolbar::OnQueryInsert(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
1757 {
1758 return 1;
1759 }
1760
1761 LRESULT CInternetToolbar::OnQueryDelete(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
1762 {
1763 return 1;
1764 }
1765
1766 LRESULT CInternetToolbar::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1767 {
1768 HMENU contextMenuBar;
1769 HMENU contextMenu;
1770 POINT clickLocation;
1771 int command;
1772 RBHITTESTINFO hitTestInfo;
1773 REBARBANDINFOW rebarBandInfo;
1774 int bandID;
1775
1776 clickLocation.x = LOWORD(lParam);
1777 clickLocation.y = HIWORD(lParam);
1778 hitTestInfo.pt = clickLocation;
1779 ScreenToClient(&hitTestInfo.pt);
1780 SendMessage(fMainReBar, RB_HITTEST, 0, (LPARAM)&hitTestInfo);
1781 if (hitTestInfo.iBand == -1)
1782 return 0;
1783 rebarBandInfo.cbSize = sizeof(rebarBandInfo);
1784 rebarBandInfo.fMask = RBBIM_ID;
1785 SendMessage(fMainReBar, RB_GETBANDINFOW, hitTestInfo.iBand, (LPARAM)&rebarBandInfo);
1786 bandID = rebarBandInfo.wID;
1787 contextMenuBar = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_CABINET_CONTEXTMENU));
1788 contextMenu = GetSubMenu(contextMenuBar, 0);
1789 switch (bandID)
1790 {
1791 case ITBBID_MENUBAND: // menu band
1792 DeleteMenu(contextMenu, IDM_TOOLBARS_CUSTOMIZE, MF_BYCOMMAND);
1793 DeleteMenu(contextMenu, IDM_TOOLBARS_TEXTLABELS, MF_BYCOMMAND);
1794 DeleteMenu(contextMenu, IDM_TOOLBARS_GOBUTTON, MF_BYCOMMAND);
1795 break;
1796 case ITBBID_BRANDBAND: // brand band
1797 DeleteMenu(contextMenu, IDM_TOOLBARS_CUSTOMIZE, MF_BYCOMMAND);
1798 DeleteMenu(contextMenu, IDM_TOOLBARS_TEXTLABELS, MF_BYCOMMAND);
1799 DeleteMenu(contextMenu, IDM_TOOLBARS_GOBUTTON, MF_BYCOMMAND);
1800 break;
1801 case ITBBID_TOOLSBAND: // tools band
1802 DeleteMenu(contextMenu, IDM_TOOLBARS_TEXTLABELS, MF_BYCOMMAND);
1803 DeleteMenu(contextMenu, IDM_TOOLBARS_GOBUTTON, MF_BYCOMMAND);
1804 break;
1805 case ITBBID_ADDRESSBAND: // navigation band
1806 DeleteMenu(contextMenu, IDM_TOOLBARS_CUSTOMIZE, MF_BYCOMMAND);
1807 DeleteMenu(contextMenu, IDM_TOOLBARS_TEXTLABELS, MF_BYCOMMAND);
1808 break;
1809 default:
1810 break;
1811 }
1812
1813 MENUITEMINFO mii;
1814 mii.cbSize = sizeof(mii);
1815 mii.fMask = MIIM_STATE;
1816 mii.fState = fLocked ? MFS_CHECKED : MFS_UNCHECKED;
1817 SetMenuItemInfo(contextMenu, IDM_TOOLBARS_LOCKTOOLBARS, FALSE, &mii);
1818
1819 // TODO: use GetSystemMetrics(SM_MENUDROPALIGNMENT) to determine menu alignment
1820 command = TrackPopupMenu(contextMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
1821 clickLocation.x, clickLocation.y, 0, m_hWnd, NULL);
1822 switch (command)
1823 {
1824 case IDM_TOOLBARS_STANDARDBUTTONS: // standard buttons
1825 break;
1826 case IDM_TOOLBARS_ADDRESSBAR: // address bar
1827 break;
1828 case IDM_TOOLBARS_LINKSBAR: // links
1829 break;
1830 case IDM_TOOLBARS_LOCKTOOLBARS: // lock the toolbars
1831 LockUnlockToolbars(!fLocked);
1832 break;
1833 case IDM_TOOLBARS_CUSTOMIZE: // customize
1834 SendMessage(fToolbarWindow, TB_CUSTOMIZE, 0, 0);
1835 break;
1836 }
1837
1838 DestroyMenu(contextMenuBar);
1839 return 1;
1840 }
1841
1842 LRESULT CInternetToolbar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1843 {
1844 if (wParam != SIZE_MINIMIZED)
1845 {
1846 ::SetWindowPos(fMainReBar, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam),
1847 SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
1848 }
1849 return 1;
1850 }
1851
1852 LRESULT CInternetToolbar::OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1853 {
1854 if ((short)lParam != HTCLIENT || (HWND)wParam != m_hWnd)
1855 {
1856 bHandled = FALSE;
1857 return 0;
1858 }
1859 SetCursor(LoadCursor(NULL, IDC_SIZENS));
1860 return 1;
1861 }
1862
1863 LRESULT CInternetToolbar::OnTipText(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
1864 {
1865 CComPtr<IBrowserService> browserService;
1866 CComPtr<ITravelLog> travelLog;
1867 TOOLTIPTEXTW *pTTTW;
1868 UINT nID;
1869 wchar_t tempString[300];
1870 HRESULT hResult;
1871
1872 pTTTW = reinterpret_cast<TOOLTIPTEXTW *>(pNMHDR);
1873 if ((pTTTW->uFlags & TTF_IDISHWND) != 0)
1874 nID = ::GetDlgCtrlID((HWND)pNMHDR->idFrom);
1875 else
1876 nID = (UINT)pNMHDR->idFrom;
1877
1878 if (nID != 0)
1879 {
1880 if (nID == (UINT)IDM_GOTO_BACK || nID == (UINT)IDM_GOTO_FORWARD)
1881 {
1882 // TODO: Should this call QueryService?
1883 hResult = fSite->QueryInterface(IID_PPV_ARG(IBrowserService, &browserService));
1884 hResult = browserService->GetTravelLog(&travelLog);
1885 hResult = travelLog->GetToolTipText(browserService,
1886 (nID == (UINT)IDM_GOTO_BACK) ? TLOG_BACK : TLOG_FORE,
1887 0, tempString, 299);
1888 if (FAILED_UNEXPECTEDLY(hResult))
1889 {
1890 bHandled = FALSE;
1891 return 0;
1892 }
1893 }
1894 else
1895 tempString[0] = 0;
1896 wcsncpy (pTTTW->szText, tempString, sizeof (pTTTW->szText) / sizeof (wchar_t));
1897 ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
1898 SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
1899 return 0;
1900 }
1901 return 0;
1902 }
1903
1904 LRESULT CInternetToolbar::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1905 {
1906 LRESULT theResult;
1907 HRESULT hResult;
1908
1909 hResult = OnWinEvent((HWND) lParam, uMsg, wParam, lParam, &theResult);
1910
1911 bHandled = hResult == S_OK;
1912
1913 return FAILED_UNEXPECTEDLY(hResult) ? 0 : theResult;
1914 }
1915 LRESULT CInternetToolbar::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1916 {
1917 NMHDR *notifyHeader;
1918 LRESULT theResult;
1919 HRESULT hResult;
1920
1921 notifyHeader = reinterpret_cast<NMHDR *>(lParam);
1922
1923 hResult = OnWinEvent(notifyHeader->hwndFrom, uMsg, wParam, lParam, &theResult);
1924
1925 bHandled = hResult == S_OK;
1926
1927 return FAILED_UNEXPECTEDLY(hResult) ? 0 : theResult;
1928 }
1929
1930 LRESULT CInternetToolbar::OnLDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1931 {
1932 bHandled = FALSE;
1933 if (fLocked)
1934 return 0;
1935
1936 if (wParam & MK_CONTROL)
1937 return 0;
1938
1939 fSizing = TRUE;
1940
1941 DWORD msgp = GetMessagePos();
1942
1943 fStartPosition.x = GET_X_LPARAM(msgp);
1944 fStartPosition.y = GET_Y_LPARAM(msgp);
1945
1946 RECT rc;
1947 GetWindowRect(m_hWnd, &rc);
1948
1949 fStartHeight = rc.bottom - rc.top;
1950
1951 SetCapture();
1952
1953 bHandled = TRUE;
1954 return 0;
1955 }
1956
1957 LRESULT CInternetToolbar::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1958 {
1959 bHandled = FALSE;
1960 if (!fSizing)
1961 return 0;
1962
1963 DWORD msgp = GetMessagePos();
1964
1965 POINT pt;
1966 pt.x = GET_X_LPARAM(msgp);
1967 pt.y = GET_Y_LPARAM(msgp);
1968
1969 ReserveBorderSpace(fStartHeight - fStartPosition.y + pt.y);
1970
1971 bHandled = TRUE;
1972 return 0;
1973 }
1974
1975 LRESULT CInternetToolbar::OnLUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1976 {
1977 bHandled = FALSE;
1978 if (!fSizing)
1979 return 0;
1980
1981 OnMouseMove(uMsg, wParam, lParam, bHandled);
1982
1983 fSizing = FALSE;
1984
1985 ReleaseCapture();
1986
1987 return 0;
1988 }
1989
1990 HRESULT CreateInternetToolbar(REFIID riid, void **ppv)
1991 {
1992 CInternetToolbar *theToolbar;
1993 HRESULT hResult;
1994
1995 if (ppv == NULL)
1996 return E_POINTER;
1997 *ppv = NULL;
1998 ATLTRY (theToolbar = new CComObject<CInternetToolbar>);
1999 if (theToolbar == NULL)
2000 return E_OUTOFMEMORY;
2001 hResult = theToolbar->QueryInterface (riid, reinterpret_cast<void **>(ppv));
2002 if (FAILED_UNEXPECTEDLY(hResult))
2003 {
2004 delete theToolbar;
2005 return hResult;
2006 }
2007 return S_OK;
2008 }