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