* Sync up to trunk HEAD (r62975).
[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_IDockingWindowSite, reinterpret_cast<void **>(&dockingWindowSite));
183 if (FAILED(hResult))
184 return hResult;
185 hResult = dockingWindowSite->GetBorderDW(static_cast<IDeskBar *>(this), &availableBorderSpace);
186 if (FAILED(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(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_IServiceProvider, reinterpret_cast<void **>(&serviceProvider));
276 if (FAILED(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_IUnknown, reinterpret_cast<void **>(&fClient));
313 if (FAILED(hResult))
314 return hResult;
315 hResult = fSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
316 if (FAILED(hResult))
317 return hResult;
318 hResult = oleWindow->GetWindow(&ownerWindow);
319 if (FAILED(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 /* CComPtr<IOleWindow> oleWindow;
434 RECT clientRect;
435 HRESULT hResult;
436
437 if (fClientWindow == NULL && fClient.p != NULL)
438 {
439 hResult = fClient->QueryInterface(IID_IOleWindow, (void **)&oleWindow);
440 hResult = oleWindow->GetWindow(&fClientWindow);
441 }
442 if (fClientWindow != NULL)
443 {
444 GetClientRect(&clientRect);
445 ::SetWindowPos(fClientWindow, NULL, clientRect.left, clientRect.top, clientRect.right - clientRect.left - GetSystemMetrics(SM_CXFRAME),
446 clientRect.bottom - clientRect.top, SWP_NOOWNERZORDER | SWP_NOZORDER);
447 }*/
448 return 0;
449 }
450
451 LRESULT CBaseBar::OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
452 {
453 if ((short)lParam != HTCLIENT || (HWND)wParam != m_hWnd)
454 {
455 bHandled = FALSE;
456 return 0;
457 }
458 if (fVertical)
459 SetCursor(LoadCursor(NULL, IDC_SIZEWE));
460 else
461 SetCursor(LoadCursor(NULL, IDC_SIZENS));
462 return 1;
463 }
464
465 LRESULT CBaseBar::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
466 {
467 CComPtr<IWinEventHandler> winEventHandler;
468 LRESULT result;
469 HRESULT hResult;
470
471 result = 0;
472 if (fClient.p != NULL)
473 {
474 hResult = fClient->QueryInterface(IID_IWinEventHandler, reinterpret_cast<void **>(&winEventHandler));
475 if (SUCCEEDED(hResult) && winEventHandler.p != NULL)
476 hResult = winEventHandler->OnWinEvent(NULL, uMsg, wParam, lParam, &result);
477 }
478 return result;
479 }
480
481 LRESULT CBaseBar::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
482 {
483 SetCapture();
484 fTracking = true;
485 fLastLocation.x = (short)LOWORD(lParam);
486 fLastLocation.y = (short)HIWORD(lParam);
487 return 0;
488 }
489
490 LRESULT CBaseBar::OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
491 {
492 ReleaseCapture();
493 fTracking = false;
494 return 0;
495 }
496
497 LRESULT CBaseBar::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
498 {
499 POINT newLocation;
500 //int delta;
501
502 if (fTracking)
503 {
504 newLocation.x = (short)LOWORD(lParam);
505 newLocation.y = (short)HIWORD(lParam);
506 #if 0
507 if (fVertical)
508 delta = newLocation.x - fLastLocation.x;
509 else
510 delta = newLocation.y - fLastLocation.y;
511
512 #endif
513 fLastLocation = newLocation;
514 }
515 return 0;
516 }
517
518 LRESULT CBaseBar::OnCancelMode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
519 {
520 fTracking = false;
521 return 0;
522 }
523
524 LRESULT CBaseBar::OnCaptureChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
525 {
526 fTracking = false;
527 return 0;
528 }
529
530 HRESULT CreateBaseBar(REFIID riid, void **ppv)
531 {
532 CComObject<CBaseBar> *theBaseBar;
533 HRESULT hResult;
534
535 if (ppv == NULL)
536 return E_POINTER;
537 *ppv = NULL;
538 ATLTRY (theBaseBar = new CComObject<CBaseBar>);
539 if (theBaseBar == NULL)
540 return E_OUTOFMEMORY;
541 hResult = theBaseBar->QueryInterface (riid, reinterpret_cast<void **>(ppv));
542 if (FAILED(hResult))
543 {
544 delete theBaseBar;
545 return hResult;
546 }
547 return S_OK;
548 }