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