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