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