* Sync up to trunk HEAD (r62975).
[reactos.git] / dll / win32 / browseui / basebarsite.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 Base bar that contains a vertical or horizontal explorer band. It also
23 provides resizing abilities.
24 */
25
26 #include "precomp.h"
27
28 /*
29 TODO:
30 ****Fix so an already created bar will be detected and just shown instead of added again
31 ****When a new bar is added, initiate a resize
32 **Add owner draw for base bar
33 **Make label text in base bar always draw in black
34 **Make base bar show close box
35 **Create close toolbar button
36 **Fix to delete all CBarInfo on deletion
37
38 */
39
40 class CBaseBarSite :
41 public CWindowImpl<CBaseBarSite, CWindow, CControlWinTraits>,
42 public CComObjectRootEx<CComMultiThreadModelNoCS>,
43 // public IDockingWindowSite,
44 public IInputObject,
45 public IServiceProvider,
46 public IWinEventHandler,
47 public IInputObjectSite,
48 public IDeskBarClient,
49 public IOleCommandTarget,
50 public IBandSite,
51 // public IBandSiteHelper,
52 // public IExplorerToolbar,
53 public IPersistStream
54 {
55 private:
56 class CBarInfo
57 {
58 public:
59 CComPtr<IUnknown> fTheBar;
60 CLSID fBarClass; // class of active bar
61 DWORD fBandID;
62
63 };
64 CBarInfo *fCurrentActiveBar; //
65 // HWND fRebarWindow; // rebar for top of window
66 CComPtr<IUnknown> fDeskBarSite;
67 DWORD fNextBandID;
68 public:
69 CBaseBarSite();
70 ~CBaseBarSite();
71 private:
72 HRESULT InsertBar(IUnknown *newBar);
73
74 // *** IOleWindow methods ***
75 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
76 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
77
78 // *** IInputObject methods ***
79 virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg);
80 virtual HRESULT STDMETHODCALLTYPE HasFocusIO();
81 virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg);
82
83 // *** IServiceProvider methods ***
84 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
85
86 // *** IWinEventHandler methods ***
87 virtual HRESULT STDMETHODCALLTYPE OnWinEvent(
88 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult);
89 virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd);
90
91 // *** IInputObjectSite specific methods ***
92 virtual HRESULT STDMETHODCALLTYPE OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus);
93
94 // *** IDeskBarClient methods ***
95 virtual HRESULT STDMETHODCALLTYPE SetDeskBarSite(IUnknown *punkSite);
96 virtual HRESULT STDMETHODCALLTYPE SetModeDBC(DWORD dwMode);
97 virtual HRESULT STDMETHODCALLTYPE UIActivateDBC(DWORD dwState);
98 virtual HRESULT STDMETHODCALLTYPE GetSize(DWORD dwWhich, LPRECT prc);
99
100 // *** IOleCommandTarget methods ***
101 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
102 OLECMD prgCmds[ ], OLECMDTEXT *pCmdText);
103 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
104 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
105
106 // *** IBandSite specific methods ***
107 virtual HRESULT STDMETHODCALLTYPE AddBand(IUnknown *punk);
108 virtual HRESULT STDMETHODCALLTYPE EnumBands(UINT uBand, DWORD *pdwBandID);
109 virtual HRESULT STDMETHODCALLTYPE QueryBand(DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState,
110 LPWSTR pszName, int cchName);
111 virtual HRESULT STDMETHODCALLTYPE SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState);
112 virtual HRESULT STDMETHODCALLTYPE RemoveBand(DWORD dwBandID);
113 virtual HRESULT STDMETHODCALLTYPE GetBandObject(DWORD dwBandID, REFIID riid, void **ppv);
114 virtual HRESULT STDMETHODCALLTYPE SetBandSiteInfo(const BANDSITEINFO *pbsinfo);
115 virtual HRESULT STDMETHODCALLTYPE GetBandSiteInfo(BANDSITEINFO *pbsinfo);
116
117 // *** IPersist methods ***
118 virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
119
120 // *** IPersistStream methods ***
121 virtual HRESULT STDMETHODCALLTYPE IsDirty();
122 virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm);
123 virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
124 virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
125
126 // message handlers
127 LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
128
129 BEGIN_MSG_MAP(CBaseBarSite)
130 MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
131 END_MSG_MAP()
132
133 BEGIN_COM_MAP(CBaseBarSite)
134 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
135 // COM_INTERFACE_ENTRY_IID(IID_IDockingWindowSite, IDockingWindowSite)
136 COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
137 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
138 COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
139 COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite)
140 COM_INTERFACE_ENTRY_IID(IID_IDeskBarClient, IDeskBarClient)
141 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
142 COM_INTERFACE_ENTRY_IID(IID_IBandSite, IBandSite)
143 // COM_INTERFACE_ENTRY_IID(IID_IBandSiteHelper, IBandSiteHelper)
144 // COM_INTERFACE_ENTRY_IID(IID_IExplorerToolbar, IExplorerToolbar)
145 COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
146 COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
147 END_COM_MAP()
148 };
149
150 CBaseBarSite::CBaseBarSite()
151 {
152 fCurrentActiveBar = NULL;
153 fNextBandID = 1;
154 }
155
156 CBaseBarSite::~CBaseBarSite()
157 {
158 }
159
160 HRESULT CBaseBarSite::InsertBar(IUnknown *newBar)
161 {
162 CComPtr<IPersist> persist;
163 CComPtr<IObjectWithSite> site;
164 CComPtr<IOleWindow> oleWindow;
165 CComPtr<IDeskBand> deskBand;
166 CComPtr<IDockingWindow> dockingWindow;
167 CBarInfo *newInfo;
168 REBARBANDINFOW bandInfo;
169 DESKBANDINFO deskBandInfo;
170 DWORD thisBandID;
171 HRESULT hResult;
172
173 hResult = newBar->QueryInterface(IID_IPersist, reinterpret_cast<void **>(&persist));
174 if (FAILED(hResult))
175 return hResult;
176 hResult = newBar->QueryInterface(IID_IObjectWithSite, reinterpret_cast<void **>(&site));
177 if (FAILED(hResult))
178 return hResult;
179 hResult = newBar->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
180 if (FAILED(hResult))
181 return hResult;
182 hResult = newBar->QueryInterface(IID_IDeskBand, reinterpret_cast<void **>(&deskBand));
183 if (FAILED(hResult))
184 return hResult;
185 hResult = newBar->QueryInterface(IID_IDockingWindow, reinterpret_cast<void **>(&dockingWindow));
186 if (FAILED(hResult))
187 return hResult;
188 hResult = site->SetSite(static_cast<IOleWindow *>(this));
189 if (FAILED(hResult))
190 return hResult;
191 ATLTRY(newInfo = new CBarInfo);
192 if (newInfo == NULL)
193 return E_OUTOFMEMORY;
194
195 // set new bar info
196 thisBandID = fNextBandID++;
197 newInfo->fTheBar = newBar;
198 newInfo->fBandID = thisBandID;
199 hResult = persist->GetClassID(&newInfo->fBarClass);
200
201 // get band info
202 deskBandInfo.dwMask = DBIM_MINSIZE | DBIM_ACTUAL | DBIM_TITLE;
203 deskBandInfo.wszTitle[0] = 0;
204 hResult = deskBand->GetBandInfo(0, 0, &deskBandInfo);
205
206 // insert band
207 memset(&bandInfo, 0, sizeof(bandInfo));
208 bandInfo.cbSize = sizeof(bandInfo);
209 bandInfo.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_TEXT |
210 RBBIM_LPARAM | RBBIM_ID;
211 bandInfo.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT;
212 bandInfo.lpText = deskBandInfo.wszTitle;
213 hResult = oleWindow->GetWindow(&bandInfo.hwndChild);
214 bandInfo.cxMinChild = 200; //deskBandInfo.ptMinSize.x;
215 bandInfo.cyMinChild = 200; //deskBandInfo.ptMinSize.y;
216 bandInfo.cx = 0;
217 bandInfo.wID = thisBandID;
218 bandInfo.cyChild = -1; //deskBandInfo.ptActual.y;
219 bandInfo.cyMaxChild = 32000;
220 bandInfo.cyIntegral = 1;
221 bandInfo.cxIdeal = 0; //deskBandInfo.ptActual.x;
222 bandInfo.lParam = reinterpret_cast<LPARAM>(newInfo);
223 SendMessage(RB_INSERTBANDW, -1, reinterpret_cast<LPARAM>(&bandInfo));
224
225 // this call is what makes the tree fill with contents
226 hResult = dockingWindow->ShowDW(TRUE);
227 if (FAILED(hResult))
228 return hResult;
229 // for now
230 fCurrentActiveBar = newInfo;
231 return S_OK;
232 }
233
234 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetWindow(HWND *lphwnd)
235 {
236 if (lphwnd == NULL)
237 return E_POINTER;
238 *lphwnd = m_hWnd;
239 return S_OK;
240 }
241
242 HRESULT STDMETHODCALLTYPE CBaseBarSite::ContextSensitiveHelp(BOOL fEnterMode)
243 {
244 return E_NOTIMPL;
245 }
246
247 HRESULT STDMETHODCALLTYPE CBaseBarSite::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
248 {
249 return E_NOTIMPL;
250 }
251
252 HRESULT STDMETHODCALLTYPE CBaseBarSite::HasFocusIO()
253 {
254 return E_NOTIMPL;
255 }
256
257 HRESULT STDMETHODCALLTYPE CBaseBarSite::TranslateAcceleratorIO(LPMSG lpMsg)
258 {
259 return E_NOTIMPL;
260 }
261
262 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
263 {
264 CComPtr<IServiceProvider> serviceProvider;
265 HRESULT hResult;
266
267 if (fDeskBarSite == NULL)
268 return E_FAIL;
269 hResult = fDeskBarSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&serviceProvider));
270 if (FAILED(hResult))
271 return hResult;
272 // called for SID_STopLevelBrowser, IID_IBrowserService to find top level browser
273 // called for SID_IWebBrowserApp, IID_IConnectionPointContainer
274 // connection point called for DIID_DWebBrowserEvents2 to establish connection
275 return serviceProvider->QueryService(guidService, riid, ppvObject);
276 }
277
278 HRESULT STDMETHODCALLTYPE CBaseBarSite::OnWinEvent(
279 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
280 {
281 CComPtr<IDeskBar> deskBar;
282 CComPtr<IWinEventHandler> winEventHandler;
283 NMHDR *notifyHeader;
284 RECT newBounds;
285 HRESULT hResult;
286
287 hResult = S_OK;
288 if (uMsg == WM_NOTIFY)
289 {
290 notifyHeader = (NMHDR *)lParam;
291 if (notifyHeader->hwndFrom == m_hWnd && notifyHeader->code == RBN_AUTOSIZE)
292 {
293 hResult = fDeskBarSite->QueryInterface(IID_IDeskBar, reinterpret_cast<void **>(&deskBar));
294 GetClientRect(&newBounds);
295 hResult = deskBar->OnPosRectChangeDB(&newBounds);
296 }
297 }
298 if (fCurrentActiveBar != NULL)
299 {
300 hResult = fCurrentActiveBar->fTheBar->QueryInterface(
301 IID_IWinEventHandler, reinterpret_cast<void **>(&winEventHandler));
302 if (SUCCEEDED(hResult) && winEventHandler.p != NULL)
303 hResult = winEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
304 }
305 return hResult;
306 }
307
308 HRESULT STDMETHODCALLTYPE CBaseBarSite::IsWindowOwner(HWND hWnd)
309 {
310 return E_NOTIMPL;
311 }
312
313 HRESULT STDMETHODCALLTYPE CBaseBarSite::OnFocusChangeIS (IUnknown *punkObj, BOOL fSetFocus)
314 {
315 return E_NOTIMPL;
316 }
317
318 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetDeskBarSite(IUnknown *punkSite)
319 {
320 CComPtr<IOleWindow> oleWindow;
321 HWND ownerWindow;
322 HRESULT hResult;
323
324 if (punkSite == NULL)
325 fDeskBarSite.Release();
326 else
327 {
328 hResult = punkSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
329 if (FAILED(hResult))
330 return hResult;
331 hResult = punkSite->QueryInterface(IID_IUnknown, reinterpret_cast<void **>(&fDeskBarSite));
332 if (FAILED(hResult))
333 return hResult;
334 hResult = oleWindow->GetWindow(&ownerWindow);
335 if (FAILED(hResult))
336 return hResult;
337 m_hWnd = CreateWindow(REBARCLASSNAMEW, NULL, WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS |
338 WS_CLIPCHILDREN |
339 RBS_VARHEIGHT | RBS_REGISTERDROP | RBS_AUTOSIZE | RBS_VERTICALGRIPPER | RBS_DBLCLKTOGGLE |
340 CCS_LEFT | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE, 0, 0, 0, 0, ownerWindow, NULL,
341 _AtlBaseModule.GetModuleInstance(), NULL);
342 SendMessage(RB_SETTEXTCOLOR, 0, CLR_DEFAULT);
343 SendMessage(RB_SETBKCOLOR, 0, CLR_DEFAULT);
344 }
345 return S_OK;
346 }
347
348 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetModeDBC(DWORD dwMode)
349 {
350 return E_NOTIMPL;
351 }
352
353 HRESULT STDMETHODCALLTYPE CBaseBarSite::UIActivateDBC(DWORD dwState)
354 {
355 return E_NOTIMPL;
356 }
357
358 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetSize(DWORD dwWhich, LPRECT prc)
359 {
360 return E_NOTIMPL;
361 }
362
363 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryStatus(const GUID *pguidCmdGroup,
364 ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
365 {
366 return E_NOTIMPL;
367 }
368
369 HRESULT STDMETHODCALLTYPE CBaseBarSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
370 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
371 {
372 if (IsEqualIID(*pguidCmdGroup, IID_IDeskBand))
373 {
374 switch (nCmdID)
375 {
376 case 1: // insert a new band
377 if (V_VT(pvaIn) != VT_UNKNOWN)
378 return E_INVALIDARG;
379 return InsertBar(V_UNKNOWN(pvaIn));
380 }
381 }
382 return E_FAIL;
383 }
384
385 HRESULT STDMETHODCALLTYPE CBaseBarSite::AddBand(IUnknown *punk)
386 {
387 return InsertBar(punk);
388 }
389
390 HRESULT STDMETHODCALLTYPE CBaseBarSite::EnumBands(UINT uBand, DWORD *pdwBandID)
391 {
392 if (uBand == 0xffffffff)
393 {
394 *pdwBandID = (DWORD)SendMessage(RB_GETBANDCOUNT, 0, 0);
395 return S_OK;
396 }
397 return E_NOTIMPL;
398 }
399
400 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryBand(DWORD dwBandID, IDeskBand **ppstb,
401 DWORD *pdwState, LPWSTR pszName, int cchName)
402 {
403 return E_NOTIMPL;
404 }
405
406 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState)
407 {
408 return E_NOTIMPL;
409 }
410
411 HRESULT STDMETHODCALLTYPE CBaseBarSite::RemoveBand(DWORD dwBandID)
412 {
413 return E_NOTIMPL;
414 }
415
416 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandObject(DWORD dwBandID, REFIID riid, void **ppv)
417 {
418 if (ppv == NULL)
419 return E_POINTER;
420 return E_NOTIMPL;
421 }
422
423 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandSiteInfo(const BANDSITEINFO *pbsinfo)
424 {
425 if (pbsinfo == NULL)
426 return E_POINTER;
427 return E_NOTIMPL;
428 }
429
430 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandSiteInfo(BANDSITEINFO *pbsinfo)
431 {
432 if (pbsinfo == NULL)
433 return E_POINTER;
434 return E_NOTIMPL;
435 }
436
437 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetClassID(CLSID *pClassID)
438 {
439 if (pClassID == NULL)
440 return E_POINTER;
441 // TODO: what class to return here?
442 return E_NOTIMPL;
443 }
444
445 HRESULT STDMETHODCALLTYPE CBaseBarSite::IsDirty()
446 {
447 return E_NOTIMPL;
448 }
449
450 HRESULT STDMETHODCALLTYPE CBaseBarSite::Load(IStream *pStm)
451 {
452 return E_NOTIMPL;
453 }
454
455 HRESULT STDMETHODCALLTYPE CBaseBarSite::Save(IStream *pStm, BOOL fClearDirty)
456 {
457 return E_NOTIMPL;
458 }
459
460 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetSizeMax(ULARGE_INTEGER *pcbSize)
461 {
462 if (pcbSize == NULL)
463 return E_POINTER;
464 return E_NOTIMPL;
465 }
466
467 LRESULT CBaseBarSite::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
468 {
469 NMHDR *notifyHeader;
470
471 notifyHeader = reinterpret_cast<NMHDR *>(lParam);
472 if (notifyHeader->hwndFrom == m_hWnd)
473 {
474 }
475 return 0;
476 }
477
478 HRESULT CreateBaseBarSite(REFIID riid, void **ppv)
479 {
480 CComObject<CBaseBarSite> *theBaseBarSite;
481 HRESULT hResult;
482
483 if (ppv == NULL)
484 return E_POINTER;
485 *ppv = NULL;
486 ATLTRY (theBaseBarSite = new CComObject<CBaseBarSite>);
487 if (theBaseBarSite == NULL)
488 return E_OUTOFMEMORY;
489 hResult = theBaseBarSite->QueryInterface(riid, reinterpret_cast<void **>(ppv));
490 if (FAILED(hResult))
491 {
492 delete theBaseBarSite;
493 return hResult;
494 }
495 return S_OK;
496 }