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