a178c4b77ff20ce4e7ff9ed287fa21a2b137318a
[reactos.git] / dll / win32 / browseui / basebar.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 This class knows how to contain base bar site in a cabinet window.
23 */
24
25 #include "precomp.h"
26
27 /*
28 Base bar that contains a vertical or horizontal explorer band. It also
29 provides resizing abilities.
30 */
31 /*
32 TODO:
33 **Make base bar support resizing
34 Add context menu for base bar
35 Fix base bar to correctly initialize fVertical field
36 Fix base bar to correctly reposition its base bar site when resized
37
38 */
39
40 class CBaseBar :
41 public CWindowImpl<CBaseBar, CWindow, CControlWinTraits>,
42 public CComObjectRootEx<CComMultiThreadModelNoCS>,
43 public IInputObjectSite,
44 public IOleCommandTarget,
45 public IServiceProvider,
46 public IInputObject,
47 public IDeskBar,
48 public IDockingWindow,
49 public IPersistStream,
50 public IPersistStreamInit,
51 public IPersistPropertyBag,
52 public IObjectWithSite
53 {
54 public:
55 CComPtr<IUnknown> fSite;
56 CComPtr<IUnknown> fClient;
57 HWND fClientWindow;
58 bool fVertical;
59 bool fVisible;
60 int fNeededSize; // width or height
61
62 // used by resize tracking loop
63 bool fTracking;
64 POINT fLastLocation;
65 public:
66 CBaseBar();
67 ~CBaseBar();
68 public:
69 HRESULT ReserveBorderSpace();
70
71 // *** IOleWindow methods ***
72 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
73 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
74
75 // *** IInputObjectSite specific methods ***
76 virtual HRESULT STDMETHODCALLTYPE OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus);
77
78 // *** IOleCommandTarget specific methods ***
79 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
80 OLECMD prgCmds[ ], OLECMDTEXT *pCmdText);
81 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
82 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
83
84 // *** IServiceProvider methods ***
85 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
86
87 // *** IInputObject methods ***
88 // forward the methods to the contained active bar
89 virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg);
90 virtual HRESULT STDMETHODCALLTYPE HasFocusIO();
91 virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg);
92
93 // *** IDeskBar methods ***
94 virtual HRESULT STDMETHODCALLTYPE SetClient(IUnknown *punkClient);
95 virtual HRESULT STDMETHODCALLTYPE GetClient(IUnknown **ppunkClient);
96 virtual HRESULT STDMETHODCALLTYPE OnPosRectChangeDB(LPRECT prc);
97
98 // *** IDockingWindow methods ***
99 virtual HRESULT STDMETHODCALLTYPE ShowDW(BOOL fShow);
100 virtual HRESULT STDMETHODCALLTYPE CloseDW(DWORD dwReserved);
101 virtual HRESULT STDMETHODCALLTYPE ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved);
102
103 // *** IObjectWithSite methods ***
104 virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
105 virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
106
107 // *** IPersist methods ***
108 virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
109
110 // *** IPersistStream methods ***
111 virtual HRESULT STDMETHODCALLTYPE IsDirty();
112 virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm);
113 virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
114 virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
115
116 // *** IPersistStreamInit methods ***
117 virtual HRESULT STDMETHODCALLTYPE InitNew();
118
119 // *** IPersistPropertyBag methods ***
120 virtual HRESULT STDMETHODCALLTYPE Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog);
121 virtual HRESULT STDMETHODCALLTYPE Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties);
122
123 // message handlers
124 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
125 LRESULT OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
126 LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
127 LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
128 LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
129 LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
130 LRESULT OnCancelMode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
131 LRESULT OnCaptureChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
132
133 DECLARE_WND_CLASS_EX(_T("BaseBar"), 0, COLOR_3DFACE)
134
135 BEGIN_MSG_MAP(CBaseBar)
136 MESSAGE_HANDLER(WM_SIZE, OnSize)
137 MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
138 MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
139 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
140 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
141 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
142 MESSAGE_HANDLER(WM_CANCELMODE, OnCancelMode)
143 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
144 END_MSG_MAP()
145
146 BEGIN_COM_MAP(CBaseBar)
147 COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, IDockingWindow)
148 COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite)
149 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
150 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
151 COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
152 COM_INTERFACE_ENTRY_IID(IID_IDeskBar, IDeskBar)
153 COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
154 COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
155 COM_INTERFACE_ENTRY2_IID(IID_IPersist, IPersist, IPersistStream)
156 COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
157 COM_INTERFACE_ENTRY_IID(IID_IPersistStreamInit, IPersistStreamInit)
158 COM_INTERFACE_ENTRY_IID(IID_IPersistPropertyBag, IPersistPropertyBag)
159 END_COM_MAP()
160 };
161
162 CBaseBar::CBaseBar()
163 {
164 fClientWindow = NULL;
165 fVertical = true;
166 fVisible = false;
167 fNeededSize = 200;
168 fTracking = false;
169 }
170
171 CBaseBar::~CBaseBar()
172 {
173 }
174
175 HRESULT CBaseBar::ReserveBorderSpace()
176 {
177 CComPtr<IDockingWindowSite> dockingWindowSite;
178 RECT availableBorderSpace;
179 RECT neededBorderSpace;
180 HRESULT hResult;
181
182 hResult = fSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &dockingWindowSite));
183 if (FAILED_UNEXPECTEDLY(hResult))
184 return hResult;
185 hResult = dockingWindowSite->GetBorderDW(static_cast<IDeskBar *>(this), &availableBorderSpace);
186 if (FAILED_UNEXPECTEDLY(hResult))
187 return hResult;
188 memset(&neededBorderSpace, 0, sizeof(neededBorderSpace));
189 if (fVisible)
190 {
191 if (fVertical)
192 neededBorderSpace.left = fNeededSize + GetSystemMetrics(SM_CXFRAME);
193 else
194 neededBorderSpace.bottom = fNeededSize + GetSystemMetrics(SM_CXFRAME);
195 }
196 hResult = dockingWindowSite->SetBorderSpaceDW(static_cast<IDeskBar *>(this), &neededBorderSpace);
197 if (FAILED_UNEXPECTEDLY(hResult))
198 return hResult;
199 return S_OK;
200 }
201
202 // current bar size is stored in the registry under
203 // key=HKCU\Software\Microsoft\Internet Explorer\Explorer Bars
204 // value=current bar GUID
205 // result is 8 bytes of binary data, 2 longs. First is the size, second is reserved and will always be 0
206 /*HRESULT CBaseBar::StopCurrentBar()
207 {
208 CComPtr<IOleCommandTarget> commandTarget;
209 HRESULT hResult;
210
211 if (fCurrentBar.p != NULL)
212 {
213 hResult = fCurrentBar->QueryInterface(IID_IOleCommandTarget, (void **)&commandTarget);
214 hResult = commandTarget->Exec(NULL, 0x17, 0, NULL, NULL);
215 }
216 // hide the current bar
217 memcpy(&fCurrentActiveClass, &GUID_NULL, sizeof(fCurrentActiveClass));
218 return S_OK;
219 }*/
220
221 HRESULT STDMETHODCALLTYPE CBaseBar::GetWindow(HWND *lphwnd)
222 {
223 if (lphwnd == NULL)
224 return E_POINTER;
225 *lphwnd = m_hWnd;
226 return S_OK;
227 }
228
229 HRESULT STDMETHODCALLTYPE CBaseBar::ContextSensitiveHelp(BOOL fEnterMode)
230 {
231 return E_NOTIMPL;
232 }
233
234 HRESULT STDMETHODCALLTYPE CBaseBar::OnFocusChangeIS (IUnknown *punkObj, BOOL fSetFocus)
235 {
236 // forward to owner
237 return E_NOTIMPL;
238 }
239
240 HRESULT STDMETHODCALLTYPE CBaseBar::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
241 OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
242 {
243 return E_NOTIMPL;
244 }
245
246 HRESULT STDMETHODCALLTYPE CBaseBar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
247 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
248 {
249 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer))
250 {
251 }
252 else if (IsEqualIID(*pguidCmdGroup, IID_IDeskBarClient))
253 {
254 switch (nCmdID)
255 {
256 case 0:
257 // hide current band
258 break;
259 case 2:
260 break;
261 case 3:
262 break;
263 }
264 }
265 return E_NOTIMPL;
266 }
267
268 HRESULT STDMETHODCALLTYPE CBaseBar::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
269 {
270 CComPtr<IServiceProvider> serviceProvider;
271 HRESULT hResult;
272
273 if (fSite == NULL)
274 return E_FAIL;
275 hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
276 if (FAILED_UNEXPECTEDLY(hResult))
277 return hResult;
278 // called for SID_STopLevelBrowser, IID_IBrowserService to find top level browser
279 // called for SID_IWebBrowserApp, IID_IConnectionPointContainer
280 // connection point called for DIID_DWebBrowserEvents2 to establish connection
281 return serviceProvider->QueryService(guidService, riid, ppvObject);
282 }
283
284 HRESULT STDMETHODCALLTYPE CBaseBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
285 {
286 // forward to contained bar
287 return S_OK;
288 }
289
290 HRESULT STDMETHODCALLTYPE CBaseBar::HasFocusIO()
291 {
292 // forward to contained bar
293 return S_OK;
294 }
295
296 HRESULT STDMETHODCALLTYPE CBaseBar::TranslateAcceleratorIO(LPMSG lpMsg)
297 {
298 // forward to contained bar
299 return S_OK;
300 }
301
302 HRESULT STDMETHODCALLTYPE CBaseBar::SetClient(IUnknown *punkClient)
303 {
304 CComPtr<IOleWindow> oleWindow;
305 HWND ownerWindow;
306 HRESULT hResult;
307
308 if (punkClient == NULL)
309 fClient.Release();
310 else
311 {
312 hResult = punkClient->QueryInterface(IID_PPV_ARG(IUnknown, &fClient));
313 if (FAILED_UNEXPECTEDLY(hResult))
314 return hResult;
315 hResult = fSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
316 if (FAILED_UNEXPECTEDLY(hResult))
317 return hResult;
318 hResult = oleWindow->GetWindow(&ownerWindow);
319 if (FAILED_UNEXPECTEDLY(hResult))
320 return hResult;
321 Create(ownerWindow, 0, NULL,
322 WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_TOOLWINDOW);
323 ReserveBorderSpace();
324 }
325 return S_OK;
326 }
327
328 HRESULT STDMETHODCALLTYPE CBaseBar::GetClient(IUnknown **ppunkClient)
329 {
330 if (ppunkClient == NULL)
331 return E_POINTER;
332 *ppunkClient = fClient;
333 if (fClient.p != NULL)
334 fClient.p->AddRef();
335 return S_OK;
336 }
337
338 HRESULT STDMETHODCALLTYPE CBaseBar::OnPosRectChangeDB(LPRECT prc)
339 {
340 if (prc == NULL)
341 return E_POINTER;
342 if (fVertical)
343 fNeededSize = prc->right - prc->left;
344 else
345 fNeededSize = prc->bottom - prc->top;
346 ReserveBorderSpace();
347 return S_OK;
348 }
349
350 HRESULT STDMETHODCALLTYPE CBaseBar::ShowDW(BOOL fShow)
351 {
352 fVisible = fShow ? true : false;
353 ReserveBorderSpace();
354 return S_OK;
355 }
356
357 HRESULT STDMETHODCALLTYPE CBaseBar::CloseDW(DWORD dwReserved)
358 {
359 fVisible = false;
360 ReserveBorderSpace();
361 return S_OK;
362 }
363
364 HRESULT STDMETHODCALLTYPE CBaseBar::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
365 {
366 ReserveBorderSpace();
367 return S_OK;
368 }
369
370 HRESULT STDMETHODCALLTYPE CBaseBar::SetSite(IUnknown *pUnkSite)
371 {
372 fSite = pUnkSite;
373 return S_OK;
374 }
375
376 HRESULT STDMETHODCALLTYPE CBaseBar::GetSite(REFIID riid, void **ppvSite)
377 {
378 if (ppvSite == NULL)
379 return E_POINTER;
380 *ppvSite = fSite;
381 if (fSite.p != NULL)
382 fSite.p->AddRef();
383 return S_OK;
384 }
385
386 HRESULT STDMETHODCALLTYPE CBaseBar::GetClassID(CLSID *pClassID)
387 {
388 if (pClassID == NULL)
389 return E_POINTER;
390 // TODO: what class to return here?
391 return E_NOTIMPL;
392 }
393
394 HRESULT STDMETHODCALLTYPE CBaseBar::IsDirty()
395 {
396 return E_NOTIMPL;
397 }
398
399 HRESULT STDMETHODCALLTYPE CBaseBar::Load(IStream *pStm)
400 {
401 return E_NOTIMPL;
402 }
403
404 HRESULT STDMETHODCALLTYPE CBaseBar::Save(IStream *pStm, BOOL fClearDirty)
405 {
406 return E_NOTIMPL;
407 }
408
409 HRESULT STDMETHODCALLTYPE CBaseBar::GetSizeMax(ULARGE_INTEGER *pcbSize)
410 {
411 if (pcbSize == NULL)
412 return E_POINTER;
413 return E_NOTIMPL;
414 }
415
416 HRESULT STDMETHODCALLTYPE CBaseBar::InitNew()
417 {
418 return E_NOTIMPL;
419 }
420
421 HRESULT STDMETHODCALLTYPE CBaseBar::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
422 {
423 return E_NOTIMPL;
424 }
425
426 HRESULT STDMETHODCALLTYPE CBaseBar::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
427 {
428 return E_NOTIMPL;
429 }
430
431 LRESULT CBaseBar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
432 {
433 return 0;
434 }
435
436 LRESULT CBaseBar::OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
437 {
438 if ((short)lParam != HTCLIENT || (HWND)wParam != m_hWnd)
439 {
440 bHandled = FALSE;
441 return 0;
442 }
443 if (fVertical)
444 SetCursor(LoadCursor(NULL, IDC_SIZEWE));
445 else
446 SetCursor(LoadCursor(NULL, IDC_SIZENS));
447 return 1;
448 }
449
450 LRESULT CBaseBar::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
451 {
452 CComPtr<IWinEventHandler> winEventHandler;
453 LRESULT result;
454 HRESULT hResult;
455
456 result = 0;
457 if (fClient.p != NULL)
458 {
459 hResult = fClient->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
460 if (SUCCEEDED(hResult) && winEventHandler.p != NULL)
461 hResult = winEventHandler->OnWinEvent(NULL, uMsg, wParam, lParam, &result);
462 }
463 return result;
464 }
465
466 LRESULT CBaseBar::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
467 {
468 SetCapture();
469 fTracking = true;
470 fLastLocation.x = (short)LOWORD(lParam);
471 fLastLocation.y = (short)HIWORD(lParam);
472 return 0;
473 }
474
475 LRESULT CBaseBar::OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
476 {
477 ReleaseCapture();
478 fTracking = false;
479 return 0;
480 }
481
482 LRESULT CBaseBar::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
483 {
484 POINT newLocation;
485 //int delta;
486
487 if (fTracking)
488 {
489 newLocation.x = (short)LOWORD(lParam);
490 newLocation.y = (short)HIWORD(lParam);
491 #if 0
492 if (fVertical)
493 delta = newLocation.x - fLastLocation.x;
494 else
495 delta = newLocation.y - fLastLocation.y;
496
497 #endif
498 fLastLocation = newLocation;
499 }
500 return 0;
501 }
502
503 LRESULT CBaseBar::OnCancelMode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
504 {
505 fTracking = false;
506 return 0;
507 }
508
509 LRESULT CBaseBar::OnCaptureChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
510 {
511 fTracking = false;
512 return 0;
513 }
514
515 HRESULT CreateBaseBar(REFIID riid, void **ppv)
516 {
517 return ShellObjectCreator<CBaseBar>(riid, ppv);
518 }