[BROWSEUI] Add Portuguese (neutral) translation.
[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 ****When a new bar is added, resize correctly the band inside instead of keeping current size.
31 *Translate close button label
32 **Add owner draw for base bar -- hackplemented atm
33 **Make label text in base bar always draw in black
34 ***Set rebar band style flags accordingly to what band object asked.
35 ***Set rebar style accordingly to direction
36 ****This class should also manage desktop bands ? (another kind of explorer bands)
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 HWND toolbarWnd;
68 HIMAGELIST toolImageList;
69 BOOL fVertical;
70 public:
71 CBaseBarSite();
72 ~CBaseBarSite();
73 HRESULT Initialize(BOOL vert) { fVertical = vert; return S_OK; };
74 private:
75 HRESULT InsertBar(IUnknown *newBar);
76
77 // *** IOleWindow methods ***
78 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
79 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
80
81 // *** IInputObject methods ***
82 virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg);
83 virtual HRESULT STDMETHODCALLTYPE HasFocusIO();
84 virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg);
85
86 // *** IServiceProvider methods ***
87 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
88
89 // *** IWinEventHandler methods ***
90 virtual HRESULT STDMETHODCALLTYPE OnWinEvent(
91 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult);
92 virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd);
93
94 // *** IInputObjectSite specific methods ***
95 virtual HRESULT STDMETHODCALLTYPE OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus);
96
97 // *** IDeskBarClient methods ***
98 virtual HRESULT STDMETHODCALLTYPE SetDeskBarSite(IUnknown *punkSite);
99 virtual HRESULT STDMETHODCALLTYPE SetModeDBC(DWORD dwMode);
100 virtual HRESULT STDMETHODCALLTYPE UIActivateDBC(DWORD dwState);
101 virtual HRESULT STDMETHODCALLTYPE GetSize(DWORD dwWhich, LPRECT prc);
102
103 // *** IOleCommandTarget methods ***
104 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
105 OLECMD prgCmds[ ], OLECMDTEXT *pCmdText);
106 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
107 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
108
109 // *** IBandSite specific methods ***
110 virtual HRESULT STDMETHODCALLTYPE AddBand(IUnknown *punk);
111 virtual HRESULT STDMETHODCALLTYPE EnumBands(UINT uBand, DWORD *pdwBandID);
112 virtual HRESULT STDMETHODCALLTYPE QueryBand(DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState,
113 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 LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
132 LRESULT OnCustomDraw(LPNMCUSTOMDRAW pnmcd);
133
134 // Helper functions
135 HFONT GetTitleFont();
136 HRESULT FindBandByGUID(REFIID pGuid, DWORD *pdwBandID);
137 HRESULT ShowBand(DWORD dwBandID);
138 HRESULT GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo);
139 HRESULT GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo, DWORD fMask);
140
141
142 BEGIN_MSG_MAP(CBaseBarSite)
143 MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
144 MESSAGE_HANDLER(WM_COMMAND, OnCommand)
145 END_MSG_MAP()
146
147 BEGIN_COM_MAP(CBaseBarSite)
148 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
149 // COM_INTERFACE_ENTRY_IID(IID_IDockingWindowSite, IDockingWindowSite)
150 COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
151 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
152 COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
153 COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite)
154 COM_INTERFACE_ENTRY_IID(IID_IDeskBarClient, IDeskBarClient)
155 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
156 COM_INTERFACE_ENTRY_IID(IID_IBandSite, IBandSite)
157 // COM_INTERFACE_ENTRY_IID(IID_IBandSiteHelper, IBandSiteHelper)
158 // COM_INTERFACE_ENTRY_IID(IID_IExplorerToolbar, IExplorerToolbar)
159 COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
160 COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
161 END_COM_MAP()
162 };
163
164 CBaseBarSite::CBaseBarSite() : fVertical(TRUE)
165 {
166 fCurrentActiveBar = NULL;
167 fNextBandID = 1;
168 }
169
170 CBaseBarSite::~CBaseBarSite()
171 {
172 TRACE("CBaseBarSite deleted\n");
173 }
174
175 HRESULT CBaseBarSite::InsertBar(IUnknown *newBar)
176 {
177 CComPtr<IPersist> persist;
178 CComPtr<IObjectWithSite> site;
179 CComPtr<IOleWindow> oleWindow;
180 CComPtr<IDeskBand> deskBand;
181 CBarInfo *newInfo;
182 REBARBANDINFOW bandInfo;
183 DESKBANDINFO deskBandInfo;
184 DWORD thisBandID;
185 HRESULT hResult;
186 CLSID tmp;
187
188 hResult = newBar->QueryInterface(IID_PPV_ARG(IPersist, &persist));
189 if (FAILED_UNEXPECTEDLY(hResult))
190 return hResult;
191 hResult = newBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &site));
192 if (FAILED_UNEXPECTEDLY(hResult))
193 return hResult;
194 hResult = newBar->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
195 if (FAILED_UNEXPECTEDLY(hResult))
196 return hResult;
197 hResult = newBar->QueryInterface(IID_PPV_ARG(IDeskBand, &deskBand));
198 if (FAILED_UNEXPECTEDLY(hResult))
199 return hResult;
200
201 // Check if the GUID already exists
202 hResult = persist->GetClassID(&tmp);
203 if (!SUCCEEDED(hResult))
204 {
205 return E_INVALIDARG;
206 }
207 if (FindBandByGUID(tmp, &thisBandID) == S_OK)
208 {
209 return ShowBand(thisBandID);
210 }
211
212 hResult = site->SetSite(static_cast<IOleWindow *>(this));
213 if (FAILED_UNEXPECTEDLY(hResult))
214 return hResult;
215
216 ATLTRY(newInfo = new CBarInfo);
217 if (newInfo == NULL)
218 return E_OUTOFMEMORY;
219
220 // set new bar info
221 thisBandID = fNextBandID++;
222 newInfo->fTheBar = newBar;
223 newInfo->fBandID = thisBandID;
224 newInfo->fBarClass = tmp;
225
226 // get band info
227 deskBandInfo.dwMask = DBIM_MINSIZE | DBIM_ACTUAL | DBIM_TITLE | DBIM_BKCOLOR;
228 deskBandInfo.wszTitle[0] = 0;
229 hResult = deskBand->GetBandInfo(0, (fVertical) ? DBIF_VIEWMODE_VERTICAL : DBIF_VIEWMODE_NORMAL, &deskBandInfo);
230
231 // insert band
232 memset(&bandInfo, 0, sizeof(bandInfo));
233 bandInfo.cbSize = sizeof(bandInfo);
234 bandInfo.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_TEXT |
235 RBBIM_LPARAM | RBBIM_ID;
236 bandInfo.fStyle = RBBS_TOPALIGN | RBBS_VARIABLEHEIGHT | RBBS_NOGRIPPER;
237 bandInfo.lpText = deskBandInfo.wszTitle;
238 hResult = oleWindow->GetWindow(&bandInfo.hwndChild);
239 /* It seems Windows XP doesn't take account of band minsize */
240 #if 0
241 bandInfo.cxMinChild = 200; //deskBandInfo.ptMinSize.x;
242 bandInfo.cyMinChild = 200; //deskBandInfo.ptMinSize.y;
243 #endif
244 bandInfo.cx = 0;
245 bandInfo.wID = thisBandID;
246 bandInfo.cyChild = -1; //deskBandInfo.ptActual.y;
247 bandInfo.cyMaxChild = 32000;
248 bandInfo.cyIntegral = 1;
249 bandInfo.cxIdeal = 0; //deskBandInfo.ptActual.x;
250 bandInfo.lParam = reinterpret_cast<LPARAM>(newInfo);
251 SendMessage(RB_INSERTBANDW, -1, reinterpret_cast<LPARAM>(&bandInfo));
252 hResult = ShowBand(newInfo->fBandID);
253 //fCurrentActiveBar = newInfo;
254 return hResult;
255 }
256
257 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetWindow(HWND *lphwnd)
258 {
259 if (lphwnd == NULL)
260 return E_POINTER;
261 *lphwnd = m_hWnd;
262 return S_OK;
263 }
264
265 HRESULT STDMETHODCALLTYPE CBaseBarSite::ContextSensitiveHelp(BOOL fEnterMode)
266 {
267 return E_NOTIMPL;
268 }
269
270 HRESULT STDMETHODCALLTYPE CBaseBarSite::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
271 {
272 if (!fCurrentActiveBar)
273 return S_OK;
274
275 return IUnknown_UIActivateIO(fCurrentActiveBar->fTheBar, fActivate, lpMsg);
276 }
277
278 HRESULT STDMETHODCALLTYPE CBaseBarSite::HasFocusIO()
279 {
280 if (!fCurrentActiveBar)
281 return S_FALSE;
282
283 return IUnknown_HasFocusIO(fCurrentActiveBar->fTheBar);
284 }
285
286 HRESULT STDMETHODCALLTYPE CBaseBarSite::TranslateAcceleratorIO(LPMSG lpMsg)
287 {
288 if (!fCurrentActiveBar)
289 {
290 if (lpMsg)
291 {
292 TranslateMessage(lpMsg);
293 DispatchMessage(lpMsg);
294 }
295 return S_OK;
296 }
297
298 return IUnknown_TranslateAcceleratorIO(fCurrentActiveBar->fTheBar, lpMsg);
299 }
300
301 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
302 {
303 CComPtr<IServiceProvider> serviceProvider;
304 HRESULT hResult;
305
306 if (fDeskBarSite == NULL)
307 return E_FAIL;
308 hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
309 if (FAILED_UNEXPECTEDLY(hResult))
310 return hResult;
311 // called for SID_STopLevelBrowser, IID_IBrowserService to find top level browser
312 // called for SID_IWebBrowserApp, IID_IConnectionPointContainer
313 // connection point called for DIID_DWebBrowserEvents2 to establish connection
314 return serviceProvider->QueryService(guidService, riid, ppvObject);
315 }
316
317 HRESULT STDMETHODCALLTYPE CBaseBarSite::OnWinEvent(
318 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
319 {
320 CComPtr<IDeskBar> deskBar;
321 CComPtr<IWinEventHandler> winEventHandler;
322 NMHDR *notifyHeader;
323 // RECT newBounds;
324 HRESULT hResult;
325 LRESULT result;
326
327 hResult = S_OK;
328 if (uMsg == WM_NOTIFY)
329 {
330 notifyHeader = (NMHDR *)lParam;
331 if (notifyHeader->hwndFrom == m_hWnd)
332 {
333 switch (notifyHeader->code)
334 {
335 case RBN_AUTOSIZE:
336 // For now, don't notify basebar we tried to resize ourselves, we don't
337 // get correct values at the moment.
338 #if 0
339 hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
340 GetClientRect(&newBounds);
341 hResult = deskBar->OnPosRectChangeDB(&newBounds);
342
343 #endif
344 break;
345 case NM_CUSTOMDRAW:
346 result = OnCustomDraw((LPNMCUSTOMDRAW)lParam);
347 if (theResult)
348 *theResult = result;
349 return S_OK;
350 }
351 }
352 }
353 if (fCurrentActiveBar != NULL)
354 {
355 hResult = fCurrentActiveBar->fTheBar->QueryInterface(
356 IID_PPV_ARG(IWinEventHandler, &winEventHandler));
357 if (SUCCEEDED(hResult) && winEventHandler.p != NULL)
358 hResult = winEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
359 }
360 return hResult;
361 }
362
363 HRESULT STDMETHODCALLTYPE CBaseBarSite::IsWindowOwner(HWND hWnd)
364 {
365 return E_NOTIMPL;
366 }
367
368 HRESULT STDMETHODCALLTYPE CBaseBarSite::OnFocusChangeIS (IUnknown *punkObj, BOOL fSetFocus)
369 {
370 // FIXME: should we directly pass-through, or advertise ourselves as focus owner ?
371 return IUnknown_OnFocusChangeIS(fDeskBarSite, punkObj, fSetFocus);
372 }
373
374 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetDeskBarSite(IUnknown *punkSite)
375 {
376 CComPtr<IOleWindow> oleWindow;
377 HWND ownerWindow;
378 HRESULT hResult;
379 DWORD dwBandID;
380
381 if (punkSite == NULL)
382 {
383
384 TRACE("Destroying site \n");
385 /* Cleanup our bands */
386 while(SUCCEEDED(EnumBands(-1, &dwBandID)) && dwBandID)
387 {
388 hResult = EnumBands(0, &dwBandID);
389 if(FAILED_UNEXPECTEDLY(hResult))
390 continue;
391 RemoveBand(dwBandID);
392 }
393 fDeskBarSite = NULL;
394 }
395 else
396 {
397 TBBUTTON closeBtn;
398 HBITMAP hBmp;
399
400 hResult = punkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
401 if (FAILED_UNEXPECTEDLY(hResult))
402 return hResult;
403 hResult = punkSite->QueryInterface(IID_PPV_ARG(IUnknown, &fDeskBarSite));
404 if (FAILED_UNEXPECTEDLY(hResult))
405 return hResult;
406 hResult = oleWindow->GetWindow(&ownerWindow);
407 if (FAILED_UNEXPECTEDLY(hResult))
408 return hResult;
409
410 DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER |
411 RBS_VARHEIGHT | RBS_REGISTERDROP | RBS_AUTOSIZE | RBS_VERTICALGRIPPER | RBS_DBLCLKTOGGLE |
412 CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE;
413 if (fVertical)
414 dwStyle |= CCS_VERT;
415
416 /* Create site window */
417 HWND tmp = CreateWindowW(REBARCLASSNAMEW, NULL, dwStyle, 0, 0, 0, 0, ownerWindow, NULL,
418 _AtlBaseModule.GetModuleInstance(), NULL);
419
420 /* Give window management to ATL */
421 SubclassWindow(tmp);
422
423 SendMessage(RB_SETTEXTCOLOR, 0, CLR_DEFAULT);
424 SendMessage(RB_SETBKCOLOR, 0, CLR_DEFAULT);
425
426 /* Create close toolbar and imagelist */
427 toolbarWnd = CreateWindowW(TOOLBARCLASSNAMEW, NULL,
428 WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
429 TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_TOOLTIPS |
430 CCS_NOMOVEY | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NODIVIDER
431 , 0, 0, 0, 0, m_hWnd, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
432
433 toolImageList = ImageList_Create(13, 11, ILC_COLOR24 | ILC_MASK, 3, 0);
434
435 hBmp = (HBITMAP)LoadImage(_AtlBaseModule.GetModuleInstance(),
436 MAKEINTRESOURCE(IDB_BANDBUTTONS), IMAGE_BITMAP, 0, 0,
437 LR_LOADTRANSPARENT);
438
439 ImageList_AddMasked(toolImageList, hBmp, RGB(192, 192, 192));
440 DeleteObject(hBmp);
441
442 SendMessage(toolbarWnd, TB_SETIMAGELIST, 0, (LPARAM)toolImageList);
443
444 /* Add button to toolbar */
445 closeBtn.iBitmap = MAKELONG(1, 0);
446 closeBtn.idCommand = IDM_BASEBAR_CLOSE;
447 closeBtn.fsState = TBSTATE_ENABLED;
448 closeBtn.fsStyle = BTNS_BUTTON;
449 ZeroMemory(closeBtn.bReserved, sizeof(closeBtn.bReserved));
450 closeBtn.dwData = 0;
451 closeBtn.iString = (INT_PTR)L"Close";
452
453 SendMessage(toolbarWnd, TB_INSERTBUTTON, 0, (LPARAM)&closeBtn);
454 SendMessage(toolbarWnd, TB_SETMAXTEXTROWS, 0, 0);
455 //SendMessage(toolbarWnd, TB_AUTOSIZE, 0, 0);
456 }
457 return S_OK;
458 }
459
460 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetModeDBC(DWORD dwMode)
461 {
462 return E_NOTIMPL;
463 }
464
465 HRESULT STDMETHODCALLTYPE CBaseBarSite::UIActivateDBC(DWORD dwState)
466 {
467 return E_NOTIMPL;
468 }
469
470 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetSize(DWORD dwWhich, LPRECT prc)
471 {
472 return E_NOTIMPL;
473 }
474
475 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryStatus(const GUID *pguidCmdGroup,
476 ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
477 {
478 return E_NOTIMPL;
479 }
480
481 HRESULT STDMETHODCALLTYPE CBaseBarSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
482 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
483 {
484 if (IsEqualIID(*pguidCmdGroup, IID_IDeskBand))
485 {
486 switch (nCmdID)
487 {
488 case 0:
489 //update band info ?
490 case 1: // insert a new band
491 if (V_VT(pvaIn) != VT_UNKNOWN)
492 return E_INVALIDARG;
493 return InsertBar(V_UNKNOWN(pvaIn));
494 case 0x17:
495 // redim band
496 break;
497 }
498 }
499 return E_FAIL;
500 }
501
502 HRESULT CBaseBarSite::GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo)
503 {
504 if (!pBandInfo)
505 return E_INVALIDARG;
506 memset(pBandInfo, 0, sizeof(REBARBANDINFO));
507 pBandInfo->cbSize = sizeof(REBARBANDINFO);
508 pBandInfo->fMask = RBBIM_LPARAM | RBBIM_ID;
509
510 // Grab our bandinfo from rebar control
511 if (!SendMessage(RB_GETBANDINFO, uBand, reinterpret_cast<LPARAM>(pBandInfo)))
512 return E_INVALIDARG;
513 return S_OK;
514 }
515
516 HRESULT CBaseBarSite::GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo, DWORD fMask)
517 {
518 if (!pBandInfo)
519 return E_INVALIDARG;
520 pBandInfo->cbSize = sizeof(REBARBANDINFO);
521 pBandInfo->fMask = fMask;
522
523 // Grab our bandinfo from rebar control
524 if (!SendMessage(RB_GETBANDINFO, uBand, reinterpret_cast<LPARAM>(pBandInfo)))
525 return E_INVALIDARG;
526 return S_OK;
527 }
528
529 HRESULT STDMETHODCALLTYPE CBaseBarSite::AddBand(IUnknown *punk)
530 {
531 return InsertBar(punk);
532 }
533
534 HRESULT STDMETHODCALLTYPE CBaseBarSite::EnumBands(UINT uBand, DWORD *pdwBandID)
535 {
536 REBARBANDINFO bandInfo;
537
538 if (pdwBandID == NULL)
539 return E_INVALIDARG;
540 if (uBand == 0xffffffff)
541 {
542 *pdwBandID = (DWORD)SendMessage(RB_GETBANDCOUNT, 0, 0);
543 return S_OK;
544 }
545 if (!SUCCEEDED(GetInternalBandInfo(uBand, &bandInfo)))
546 return E_INVALIDARG;
547 *pdwBandID = bandInfo.wID;
548 return S_OK;
549 }
550
551 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryBand(DWORD dwBandID, IDeskBand **ppstb,
552 DWORD *pdwState, LPWSTR pszName, int cchName)
553 {
554 return E_NOTIMPL;
555 }
556
557 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState)
558 {
559 return E_NOTIMPL;
560 }
561
562 HRESULT STDMETHODCALLTYPE CBaseBarSite::RemoveBand(DWORD dwBandID)
563 {
564 REBARBANDINFO bandInfo;
565 HRESULT hr;
566 CBarInfo *pInfo;
567 CComPtr<IObjectWithSite> pSite;
568 CComPtr<IDeskBand> pDockWnd;
569 DWORD index;
570
571 // Retrieve the right index of the coolbar knowing the id
572 index = SendMessage(RB_IDTOINDEX, dwBandID, 0);
573 if (index == 0xffffffff)
574 return E_INVALIDARG;
575
576 if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &bandInfo)))
577 return E_INVALIDARG;
578
579 pInfo = reinterpret_cast<CBarInfo*>(bandInfo.lParam);
580 if (!pInfo)
581 return E_INVALIDARG;
582
583 hr = pInfo->fTheBar->QueryInterface(IID_PPV_ARG(IDeskBand, &pDockWnd));
584 if (FAILED_UNEXPECTEDLY(hr))
585 {
586 return E_NOINTERFACE;
587 }
588 hr = pInfo->fTheBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pSite));
589 if (FAILED_UNEXPECTEDLY(hr))
590 {
591 return E_NOINTERFACE;
592 }
593 /* Windows sends a CloseDW before setting site to NULL */
594 pDockWnd->CloseDW(0);
595 pSite->SetSite(NULL);
596
597 // Delete the band from rebar
598 if (!SendMessage(RB_DELETEBAND, index, 0))
599 {
600 ERR("Can't delete the band\n");
601 return E_INVALIDARG;
602 }
603 if (pInfo == fCurrentActiveBar)
604 {
605 // FIXME: what to do when we are deleting active bar ? Let's assume we remove it for now
606 fCurrentActiveBar = NULL;
607 }
608 delete pInfo;
609 return S_OK;
610 }
611
612 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandObject(DWORD dwBandID, REFIID riid, void **ppv)
613 {
614 REBARBANDINFO bandInfo;
615 HRESULT hr;
616 CBarInfo *pInfo;
617 DWORD index;
618
619 if (ppv == NULL)
620 return E_POINTER;
621
622 // Retrieve the right index of the coolbar knowing the id
623 index = SendMessage(RB_IDTOINDEX, dwBandID, 0);
624 if (index == 0xffffffff)
625 return E_INVALIDARG;
626
627 if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &bandInfo)))
628 return E_INVALIDARG;
629
630 pInfo = reinterpret_cast<CBarInfo*>(bandInfo.lParam);
631 hr = pInfo->fTheBar->QueryInterface(riid, ppv);
632 if (!SUCCEEDED(hr))
633 return E_NOINTERFACE;
634 return S_OK;
635 }
636
637 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandSiteInfo(const BANDSITEINFO *pbsinfo)
638 {
639 if (pbsinfo == NULL)
640 return E_POINTER;
641 return E_NOTIMPL;
642 }
643
644 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandSiteInfo(BANDSITEINFO *pbsinfo)
645 {
646 if (pbsinfo == NULL)
647 return E_POINTER;
648 return E_NOTIMPL;
649 }
650
651 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetClassID(CLSID *pClassID)
652 {
653 if (pClassID == NULL)
654 return E_POINTER;
655 // TODO: what class to return here?
656 return E_NOTIMPL;
657 }
658
659 HRESULT STDMETHODCALLTYPE CBaseBarSite::IsDirty()
660 {
661 return E_NOTIMPL;
662 }
663
664 HRESULT STDMETHODCALLTYPE CBaseBarSite::Load(IStream *pStm)
665 {
666 return E_NOTIMPL;
667 }
668
669 HRESULT STDMETHODCALLTYPE CBaseBarSite::Save(IStream *pStm, BOOL fClearDirty)
670 {
671 return E_NOTIMPL;
672 }
673
674 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetSizeMax(ULARGE_INTEGER *pcbSize)
675 {
676 if (pcbSize == NULL)
677 return E_POINTER;
678 return E_NOTIMPL;
679 }
680
681 LRESULT CBaseBarSite::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
682 {
683 NMHDR *notifyHeader;
684
685 notifyHeader = reinterpret_cast<NMHDR *>(lParam);
686 if (notifyHeader->hwndFrom == m_hWnd)
687 {
688 }
689 bHandled = FALSE; /* forward notification to parent */
690 return 0;
691 }
692
693 LRESULT CBaseBarSite::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
694 {
695 if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDM_BASEBAR_CLOSE)
696 {
697 /* Tell the base bar to hide */
698 IUnknown_Exec(fDeskBarSite, IID_IDeskBarClient, 0, 0, NULL, NULL);
699 bHandled = TRUE;
700 }
701 return 0;
702 }
703
704 LRESULT CBaseBarSite::OnCustomDraw(LPNMCUSTOMDRAW pnmcd)
705 {
706 switch (pnmcd->dwDrawStage)
707 {
708 case CDDS_PREPAINT:
709 case CDDS_PREERASE:
710 return CDRF_NOTIFYITEMDRAW;
711 case CDDS_ITEMPREPAINT:
712 if (fVertical)
713 {
714 REBARBANDINFO info;
715 WCHAR wszTitle[MAX_PATH];
716 DWORD index;
717 RECT rt;
718 HFONT newFont, oldFont;
719
720 index = SendMessage(RB_IDTOINDEX, fCurrentActiveBar->fBandID , 0);
721 ZeroMemory(&info, sizeof(info));
722 ZeroMemory(wszTitle, sizeof(wszTitle));
723 DrawEdge(pnmcd->hdc, &pnmcd->rc, EDGE_ETCHED, BF_BOTTOM);
724 // We also resize our close button
725 ::SetWindowPos(toolbarWnd, HWND_TOP, pnmcd->rc.right - 22, 0, 20, 18, SWP_SHOWWINDOW);
726 // Draw the text
727 info.cch = MAX_PATH;
728 info.lpText = wszTitle;
729 rt = pnmcd->rc;
730 rt.right -= 24;
731 rt.left += 2;
732 if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &info, RBBIM_TEXT)))
733 return CDRF_SKIPDEFAULT;
734 newFont = GetTitleFont();
735 if (newFont)
736 oldFont = (HFONT)SelectObject(pnmcd->hdc, newFont);
737 DrawText(pnmcd->hdc, info.lpText, -1, &rt, DT_SINGLELINE | DT_LEFT);
738 SelectObject(pnmcd->hdc, oldFont);
739 DeleteObject(newFont);
740 return CDRF_SKIPDEFAULT;
741 }
742 else
743 {
744 DrawEdge(pnmcd->hdc, &pnmcd->rc, EDGE_ETCHED, BF_BOTTOM);
745 // We also resize our close button
746 ::SetWindowPos(toolbarWnd, HWND_TOP, 0, 2, 20, 18, SWP_SHOWWINDOW);
747 }
748 return CDRF_SKIPDEFAULT;
749 default:
750 break;
751 }
752 return CDRF_DODEFAULT;
753 }
754
755 HFONT CBaseBarSite::GetTitleFont()
756 {
757 NONCLIENTMETRICS mt;
758 mt.cbSize = sizeof(mt);
759 if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(mt), &mt, 0))
760 {
761 ERR("Can't get system parameters !\n");
762 return NULL;
763 }
764 return CreateFontIndirect(&mt.lfMenuFont);
765
766 }
767
768 HRESULT CBaseBarSite::FindBandByGUID(REFGUID pGuid, DWORD *pdwBandID)
769 {
770 DWORD numBands;
771 DWORD i;
772 HRESULT hr;
773 REBARBANDINFO bandInfo;
774 CBarInfo *realInfo;
775
776 hr = EnumBands(-1, &numBands);
777 if (FAILED_UNEXPECTEDLY(hr))
778 return E_FAIL;
779
780 for(i = 0; i < numBands; i++)
781 {
782 if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(i, &bandInfo)))
783 return E_FAIL;
784 realInfo = (CBarInfo*)bandInfo.lParam;
785 if (IsEqualGUID(pGuid, realInfo->fBarClass))
786 {
787 *pdwBandID = realInfo->fBandID;
788 return S_OK;
789 }
790 }
791 return S_FALSE;
792 }
793
794 HRESULT CBaseBarSite::ShowBand(DWORD dwBandID)
795 {
796 UINT index;
797 CComPtr<IDeskBand> dockingWindow;
798 HRESULT hResult;
799 REBARBANDINFO bandInfo;
800
801 // show our band
802 hResult = GetBandObject(dwBandID, IID_PPV_ARG(IDeskBand, &dockingWindow));
803 if (FAILED_UNEXPECTEDLY(hResult))
804 return E_FAIL;
805
806 hResult = dockingWindow->ShowDW(TRUE);
807
808 // Hide old band while adding new one
809 if (fCurrentActiveBar && fCurrentActiveBar->fBandID != dwBandID)
810 {
811 DWORD index;
812 index = SendMessage(RB_IDTOINDEX, fCurrentActiveBar->fBandID, 0);
813 if (index != 0xffffffff)
814 SendMessage(RB_SHOWBAND, index, 0);
815 }
816 if (FAILED_UNEXPECTEDLY(hResult))
817 return hResult;
818
819 // Display the current band
820 index = SendMessage(RB_IDTOINDEX, dwBandID, 0);
821 if (index != 0xffffffff)
822 SendMessage(RB_SHOWBAND, index, 1);
823 if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &bandInfo)))
824 return E_FAIL;
825 fCurrentActiveBar = (CBarInfo*)bandInfo.lParam;
826 return S_OK;
827 }
828
829 HRESULT CBaseBarSite_CreateInstance(REFIID riid, void **ppv, BOOL bVertical)
830 {
831 return ShellObjectCreatorInit<CBaseBarSite, BOOL>(bVertical, riid, ppv);
832 }