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