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