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