xref: /reactos/dll/win32/browseui/basebarsite.cpp (revision fd029c97)
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_PPV_ARG(IPersist, &persist));
174     if (FAILED_UNEXPECTEDLY(hResult))
175         return hResult;
176     hResult = newBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &site));
177     if (FAILED_UNEXPECTEDLY(hResult))
178         return hResult;
179     hResult = newBar->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
180     if (FAILED_UNEXPECTEDLY(hResult))
181         return hResult;
182     hResult = newBar->QueryInterface(IID_PPV_ARG(IDeskBand, &deskBand));
183     if (FAILED_UNEXPECTEDLY(hResult))
184         return hResult;
185     hResult = newBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
186     if (FAILED_UNEXPECTEDLY(hResult))
187         return hResult;
188     hResult = site->SetSite(static_cast<IOleWindow *>(this));
189     if (FAILED_UNEXPECTEDLY(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_UNEXPECTEDLY(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_PPV_ARG(IServiceProvider, &serviceProvider));
270     if (FAILED_UNEXPECTEDLY(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_PPV_ARG(IDeskBar, &deskBar));
294             GetClientRect(&newBounds);
295             hResult = deskBar->OnPosRectChangeDB(&newBounds);
296         }
297     }
298     if (fCurrentActiveBar != NULL)
299     {
300         hResult = fCurrentActiveBar->fTheBar->QueryInterface(
301             IID_PPV_ARG(IWinEventHandler, &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_PPV_ARG(IOleWindow, &oleWindow));
329         if (FAILED_UNEXPECTEDLY(hResult))
330             return hResult;
331         hResult = punkSite->QueryInterface(IID_PPV_ARG(IUnknown, &fDeskBarSite));
332         if (FAILED_UNEXPECTEDLY(hResult))
333             return hResult;
334         hResult = oleWindow->GetWindow(&ownerWindow);
335         if (FAILED_UNEXPECTEDLY(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     return ShellObjectCreator<CBaseBarSite>(riid, ppv);
481 }
482