mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
836 lines
27 KiB
C++
836 lines
27 KiB
C++
/*
|
|
* ReactOS Explorer
|
|
*
|
|
* Copyright 2009 Andrew Hill <ash77 at domain reactos.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/*
|
|
Base bar that contains a vertical or horizontal explorer band. It also
|
|
provides resizing abilities.
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
/*
|
|
TODO:
|
|
****When a new bar is added, resize correctly the band inside instead of keeping current size.
|
|
*Translate close button label
|
|
**Add owner draw for base bar -- hackplemented atm
|
|
**Make label text in base bar always draw in black
|
|
***Set rebar band style flags accordingly to what band object asked.
|
|
***Set rebar style accordingly to direction
|
|
****This class should also manage desktop bands ? (another kind of explorer bands)
|
|
*/
|
|
|
|
class CBaseBarSite :
|
|
public CWindowImpl<CBaseBarSite, CWindow, CControlWinTraits>,
|
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
|
// public IDockingWindowSite,
|
|
public IInputObject,
|
|
public IServiceProvider,
|
|
public IWinEventHandler,
|
|
public IInputObjectSite,
|
|
public IDeskBarClient,
|
|
public IOleCommandTarget,
|
|
public IBandSite,
|
|
// public IBandSiteHelper,
|
|
// public IExplorerToolbar,
|
|
public IPersistStream
|
|
{
|
|
private:
|
|
class CBarInfo
|
|
{
|
|
public:
|
|
CComPtr<IUnknown> fTheBar;
|
|
CLSID fBarClass; // class of active bar
|
|
DWORD fBandID;
|
|
|
|
};
|
|
CBarInfo *fCurrentActiveBar; //
|
|
// HWND fRebarWindow; // rebar for top of window
|
|
CComPtr<IUnknown> fDeskBarSite;
|
|
DWORD fNextBandID;
|
|
HWND toolbarWnd;
|
|
HIMAGELIST toolImageList;
|
|
BOOL fVertical;
|
|
public:
|
|
CBaseBarSite();
|
|
~CBaseBarSite();
|
|
HRESULT Initialize(BOOL vert) { fVertical = vert; return S_OK; };
|
|
private:
|
|
HRESULT InsertBar(IUnknown *newBar);
|
|
|
|
// *** IOleWindow methods ***
|
|
STDMETHOD(GetWindow)(HWND *lphwnd) override;
|
|
STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode) override;
|
|
|
|
// *** IInputObject methods ***
|
|
STDMETHOD(UIActivateIO)(BOOL fActivate, LPMSG lpMsg) override;
|
|
STDMETHOD(HasFocusIO)() override;
|
|
STDMETHOD(TranslateAcceleratorIO)(LPMSG lpMsg) override;
|
|
|
|
// *** IServiceProvider methods ***
|
|
STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void **ppvObject) override;
|
|
|
|
// *** IWinEventHandler methods ***
|
|
STDMETHOD(OnWinEvent)(
|
|
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) override;
|
|
STDMETHOD(IsWindowOwner)(HWND hWnd) override;
|
|
|
|
// *** IInputObjectSite specific methods ***
|
|
STDMETHOD(OnFocusChangeIS)(IUnknown *punkObj, BOOL fSetFocus) override;
|
|
|
|
// *** IDeskBarClient methods ***
|
|
STDMETHOD(SetDeskBarSite)(IUnknown *punkSite) override;
|
|
STDMETHOD(SetModeDBC)(DWORD dwMode) override;
|
|
STDMETHOD(UIActivateDBC)(DWORD dwState) override;
|
|
STDMETHOD(GetSize)(DWORD dwWhich, LPRECT prc) override;
|
|
|
|
// *** IOleCommandTarget methods ***
|
|
STDMETHOD(QueryStatus)(const GUID *pguidCmdGroup, ULONG cCmds,
|
|
OLECMD prgCmds[ ], OLECMDTEXT *pCmdText) override;
|
|
STDMETHOD(Exec)(const GUID *pguidCmdGroup, DWORD nCmdID,
|
|
DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) override;
|
|
|
|
// *** IBandSite specific methods ***
|
|
STDMETHOD(AddBand)(IUnknown *punk) override;
|
|
STDMETHOD(EnumBands)(UINT uBand, DWORD *pdwBandID) override;
|
|
STDMETHOD(QueryBand)(DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState,
|
|
LPWSTR pszName, int cchName) override;
|
|
STDMETHOD(SetBandState)(DWORD dwBandID, DWORD dwMask, DWORD dwState) override;
|
|
STDMETHOD(RemoveBand)(DWORD dwBandID) override;
|
|
STDMETHOD(GetBandObject)(DWORD dwBandID, REFIID riid, void **ppv) override;
|
|
STDMETHOD(SetBandSiteInfo)(const BANDSITEINFO *pbsinfo) override;
|
|
STDMETHOD(GetBandSiteInfo)(BANDSITEINFO *pbsinfo) override;
|
|
|
|
// *** IPersist methods ***
|
|
STDMETHOD(GetClassID)(CLSID *pClassID) override;
|
|
|
|
// *** IPersistStream methods ***
|
|
STDMETHOD(IsDirty)() override;
|
|
STDMETHOD(Load)(IStream *pStm) override;
|
|
STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty) override;
|
|
STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize) override;
|
|
|
|
// message handlers
|
|
LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
|
|
LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
|
|
LRESULT OnCustomDraw(LPNMCUSTOMDRAW pnmcd);
|
|
|
|
// Helper functions
|
|
HFONT GetTitleFont();
|
|
HRESULT FindBandByGUID(REFIID pGuid, DWORD *pdwBandID);
|
|
HRESULT ShowBand(DWORD dwBandID);
|
|
HRESULT GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo);
|
|
HRESULT GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo, DWORD fMask);
|
|
|
|
|
|
BEGIN_MSG_MAP(CBaseBarSite)
|
|
MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
|
|
MESSAGE_HANDLER(WM_COMMAND, OnCommand)
|
|
END_MSG_MAP()
|
|
|
|
BEGIN_COM_MAP(CBaseBarSite)
|
|
COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
|
|
// COM_INTERFACE_ENTRY_IID(IID_IDockingWindowSite, IDockingWindowSite)
|
|
COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
|
|
COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
|
|
COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
|
|
COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite)
|
|
COM_INTERFACE_ENTRY_IID(IID_IDeskBarClient, IDeskBarClient)
|
|
COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
|
|
COM_INTERFACE_ENTRY_IID(IID_IBandSite, IBandSite)
|
|
// COM_INTERFACE_ENTRY_IID(IID_IBandSiteHelper, IBandSiteHelper)
|
|
// COM_INTERFACE_ENTRY_IID(IID_IExplorerToolbar, IExplorerToolbar)
|
|
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
|
COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
|
|
END_COM_MAP()
|
|
};
|
|
|
|
CBaseBarSite::CBaseBarSite() : fVertical(TRUE)
|
|
{
|
|
fCurrentActiveBar = NULL;
|
|
fNextBandID = 1;
|
|
}
|
|
|
|
CBaseBarSite::~CBaseBarSite()
|
|
{
|
|
TRACE("CBaseBarSite deleted\n");
|
|
}
|
|
|
|
HRESULT CBaseBarSite::InsertBar(IUnknown *newBar)
|
|
{
|
|
CComPtr<IPersist> persist;
|
|
CComPtr<IObjectWithSite> site;
|
|
CComPtr<IOleWindow> oleWindow;
|
|
CComPtr<IDeskBand> deskBand;
|
|
CBarInfo *newInfo;
|
|
REBARBANDINFOW bandInfo;
|
|
DESKBANDINFO deskBandInfo;
|
|
DWORD thisBandID;
|
|
HRESULT hResult;
|
|
CLSID tmp;
|
|
|
|
hResult = newBar->QueryInterface(IID_PPV_ARG(IPersist, &persist));
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return hResult;
|
|
hResult = newBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &site));
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return hResult;
|
|
hResult = newBar->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return hResult;
|
|
hResult = newBar->QueryInterface(IID_PPV_ARG(IDeskBand, &deskBand));
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return hResult;
|
|
|
|
// Check if the GUID already exists
|
|
hResult = persist->GetClassID(&tmp);
|
|
if (!SUCCEEDED(hResult))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
if (FindBandByGUID(tmp, &thisBandID) == S_OK)
|
|
{
|
|
return ShowBand(thisBandID);
|
|
}
|
|
|
|
hResult = site->SetSite(static_cast<IOleWindow *>(this));
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return hResult;
|
|
|
|
ATLTRY(newInfo = new CBarInfo);
|
|
if (newInfo == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// set new bar info
|
|
thisBandID = fNextBandID++;
|
|
newInfo->fTheBar = newBar;
|
|
newInfo->fBandID = thisBandID;
|
|
newInfo->fBarClass = tmp;
|
|
|
|
// get band info
|
|
deskBandInfo.dwMask = DBIM_MINSIZE | DBIM_ACTUAL | DBIM_TITLE | DBIM_BKCOLOR;
|
|
deskBandInfo.wszTitle[0] = 0;
|
|
hResult = deskBand->GetBandInfo(0, (fVertical) ? DBIF_VIEWMODE_VERTICAL : DBIF_VIEWMODE_NORMAL, &deskBandInfo);
|
|
|
|
// insert band
|
|
memset(&bandInfo, 0, sizeof(bandInfo));
|
|
bandInfo.cbSize = sizeof(bandInfo);
|
|
bandInfo.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_TEXT |
|
|
RBBIM_LPARAM | RBBIM_ID;
|
|
bandInfo.fStyle = RBBS_TOPALIGN | RBBS_VARIABLEHEIGHT | RBBS_NOGRIPPER;
|
|
bandInfo.lpText = deskBandInfo.wszTitle;
|
|
hResult = oleWindow->GetWindow(&bandInfo.hwndChild);
|
|
/* It seems Windows XP doesn't take account of band minsize */
|
|
#if 0
|
|
bandInfo.cxMinChild = 200; //deskBandInfo.ptMinSize.x;
|
|
bandInfo.cyMinChild = 200; //deskBandInfo.ptMinSize.y;
|
|
#endif
|
|
bandInfo.cx = 0;
|
|
bandInfo.wID = thisBandID;
|
|
bandInfo.cyChild = -1; //deskBandInfo.ptActual.y;
|
|
bandInfo.cyMaxChild = 32000;
|
|
bandInfo.cyIntegral = 1;
|
|
bandInfo.cxIdeal = 0; //deskBandInfo.ptActual.x;
|
|
bandInfo.lParam = reinterpret_cast<LPARAM>(newInfo);
|
|
SendMessage(RB_INSERTBANDW, -1, reinterpret_cast<LPARAM>(&bandInfo));
|
|
hResult = ShowBand(newInfo->fBandID);
|
|
//fCurrentActiveBar = newInfo;
|
|
return hResult;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::GetWindow(HWND *lphwnd)
|
|
{
|
|
if (lphwnd == NULL)
|
|
return E_POINTER;
|
|
*lphwnd = m_hWnd;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::ContextSensitiveHelp(BOOL fEnterMode)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
|
|
{
|
|
if (!fCurrentActiveBar)
|
|
return S_OK;
|
|
|
|
return IUnknown_UIActivateIO(fCurrentActiveBar->fTheBar, fActivate, lpMsg);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::HasFocusIO()
|
|
{
|
|
if (!fCurrentActiveBar)
|
|
return S_FALSE;
|
|
|
|
return IUnknown_HasFocusIO(fCurrentActiveBar->fTheBar);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::TranslateAcceleratorIO(LPMSG lpMsg)
|
|
{
|
|
if (!fCurrentActiveBar)
|
|
{
|
|
if (lpMsg)
|
|
{
|
|
TranslateMessage(lpMsg);
|
|
DispatchMessage(lpMsg);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
return IUnknown_TranslateAcceleratorIO(fCurrentActiveBar->fTheBar, lpMsg);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
|
|
{
|
|
CComPtr<IServiceProvider> serviceProvider;
|
|
HRESULT hResult;
|
|
|
|
if (fDeskBarSite == NULL)
|
|
return E_FAIL;
|
|
hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return hResult;
|
|
// called for SID_STopLevelBrowser, IID_IBrowserService to find top level browser
|
|
// called for SID_IWebBrowserApp, IID_IConnectionPointContainer
|
|
// connection point called for DIID_DWebBrowserEvents2 to establish connection
|
|
return serviceProvider->QueryService(guidService, riid, ppvObject);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::OnWinEvent(
|
|
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
|
|
{
|
|
CComPtr<IDeskBar> deskBar;
|
|
CComPtr<IWinEventHandler> winEventHandler;
|
|
NMHDR *notifyHeader;
|
|
// RECT newBounds;
|
|
HRESULT hResult;
|
|
LRESULT result;
|
|
|
|
hResult = S_OK;
|
|
if (uMsg == WM_NOTIFY)
|
|
{
|
|
notifyHeader = (NMHDR *)lParam;
|
|
if (notifyHeader->hwndFrom == m_hWnd)
|
|
{
|
|
switch (notifyHeader->code)
|
|
{
|
|
case RBN_AUTOSIZE:
|
|
// For now, don't notify basebar we tried to resize ourselves, we don't
|
|
// get correct values at the moment.
|
|
#if 0
|
|
hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
|
|
GetClientRect(&newBounds);
|
|
hResult = deskBar->OnPosRectChangeDB(&newBounds);
|
|
|
|
#endif
|
|
break;
|
|
case NM_CUSTOMDRAW:
|
|
result = OnCustomDraw((LPNMCUSTOMDRAW)lParam);
|
|
if (theResult)
|
|
*theResult = result;
|
|
return S_OK;
|
|
}
|
|
}
|
|
}
|
|
if (fCurrentActiveBar != NULL)
|
|
{
|
|
hResult = fCurrentActiveBar->fTheBar->QueryInterface(
|
|
IID_PPV_ARG(IWinEventHandler, &winEventHandler));
|
|
if (SUCCEEDED(hResult) && winEventHandler.p != NULL)
|
|
hResult = winEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
|
|
}
|
|
return hResult;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::IsWindowOwner(HWND hWnd)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::OnFocusChangeIS (IUnknown *punkObj, BOOL fSetFocus)
|
|
{
|
|
// FIXME: should we directly pass-through, or advertise ourselves as focus owner ?
|
|
return IUnknown_OnFocusChangeIS(fDeskBarSite, punkObj, fSetFocus);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::SetDeskBarSite(IUnknown *punkSite)
|
|
{
|
|
CComPtr<IOleWindow> oleWindow;
|
|
HWND ownerWindow;
|
|
HRESULT hResult;
|
|
DWORD dwBandID;
|
|
|
|
if (punkSite == NULL)
|
|
{
|
|
|
|
TRACE("Destroying site \n");
|
|
/* Cleanup our bands */
|
|
while(SUCCEEDED(EnumBands(-1, &dwBandID)) && dwBandID)
|
|
{
|
|
hResult = EnumBands(0, &dwBandID);
|
|
if(FAILED_UNEXPECTEDLY(hResult))
|
|
continue;
|
|
RemoveBand(dwBandID);
|
|
}
|
|
fDeskBarSite = NULL;
|
|
}
|
|
else
|
|
{
|
|
TBBUTTON closeBtn;
|
|
HBITMAP hBmp;
|
|
|
|
hResult = punkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return hResult;
|
|
hResult = punkSite->QueryInterface(IID_PPV_ARG(IUnknown, &fDeskBarSite));
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return hResult;
|
|
hResult = oleWindow->GetWindow(&ownerWindow);
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return hResult;
|
|
|
|
DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER |
|
|
RBS_VARHEIGHT | RBS_REGISTERDROP | RBS_AUTOSIZE | RBS_VERTICALGRIPPER | RBS_DBLCLKTOGGLE |
|
|
CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE;
|
|
if (fVertical)
|
|
dwStyle |= CCS_VERT;
|
|
|
|
/* Create site window */
|
|
HWND tmp = CreateWindowW(REBARCLASSNAMEW, NULL, dwStyle, 0, 0, 0, 0, ownerWindow, NULL,
|
|
_AtlBaseModule.GetModuleInstance(), NULL);
|
|
|
|
/* Give window management to ATL */
|
|
SubclassWindow(tmp);
|
|
|
|
SendMessage(RB_SETTEXTCOLOR, 0, CLR_DEFAULT);
|
|
SendMessage(RB_SETBKCOLOR, 0, CLR_DEFAULT);
|
|
|
|
/* Create close toolbar and imagelist */
|
|
toolbarWnd = CreateWindowW(TOOLBARCLASSNAMEW, NULL,
|
|
WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
|
|
TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_TOOLTIPS |
|
|
CCS_NOMOVEY | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NODIVIDER
|
|
, 0, 0, 0, 0, m_hWnd, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
|
|
|
|
toolImageList = ImageList_Create(13, 11, ILC_COLOR24 | ILC_MASK, 3, 0);
|
|
|
|
hBmp = (HBITMAP)LoadImage(_AtlBaseModule.GetModuleInstance(),
|
|
MAKEINTRESOURCE(IDB_BANDBUTTONS), IMAGE_BITMAP, 0, 0,
|
|
LR_LOADTRANSPARENT);
|
|
|
|
ImageList_AddMasked(toolImageList, hBmp, RGB(192, 192, 192));
|
|
DeleteObject(hBmp);
|
|
|
|
SendMessage(toolbarWnd, TB_SETIMAGELIST, 0, (LPARAM)toolImageList);
|
|
|
|
/* Add button to toolbar */
|
|
closeBtn.iBitmap = MAKELONG(1, 0);
|
|
closeBtn.idCommand = IDM_BASEBAR_CLOSE;
|
|
closeBtn.fsState = TBSTATE_ENABLED;
|
|
closeBtn.fsStyle = BTNS_BUTTON;
|
|
ZeroMemory(closeBtn.bReserved, sizeof(closeBtn.bReserved));
|
|
closeBtn.dwData = 0;
|
|
closeBtn.iString = (INT_PTR)L"Close";
|
|
|
|
SendMessage(toolbarWnd, TB_INSERTBUTTON, 0, (LPARAM)&closeBtn);
|
|
SendMessage(toolbarWnd, TB_SETMAXTEXTROWS, 0, 0);
|
|
//SendMessage(toolbarWnd, TB_AUTOSIZE, 0, 0);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::SetModeDBC(DWORD dwMode)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::UIActivateDBC(DWORD dwState)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::GetSize(DWORD dwWhich, LPRECT prc)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryStatus(const GUID *pguidCmdGroup,
|
|
ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
|
|
DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
|
|
{
|
|
if (IsEqualIID(*pguidCmdGroup, IID_IDeskBand))
|
|
{
|
|
switch (nCmdID)
|
|
{
|
|
case 0:
|
|
//update band info ?
|
|
case 1: // insert a new band
|
|
if (V_VT(pvaIn) != VT_UNKNOWN)
|
|
return E_INVALIDARG;
|
|
return InsertBar(V_UNKNOWN(pvaIn));
|
|
case 0x17:
|
|
// redim band
|
|
break;
|
|
}
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT CBaseBarSite::GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo)
|
|
{
|
|
if (!pBandInfo)
|
|
return E_INVALIDARG;
|
|
memset(pBandInfo, 0, sizeof(REBARBANDINFO));
|
|
pBandInfo->cbSize = sizeof(REBARBANDINFO);
|
|
pBandInfo->fMask = RBBIM_LPARAM | RBBIM_ID;
|
|
|
|
// Grab our bandinfo from rebar control
|
|
if (!SendMessage(RB_GETBANDINFO, uBand, reinterpret_cast<LPARAM>(pBandInfo)))
|
|
return E_INVALIDARG;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CBaseBarSite::GetInternalBandInfo(UINT uBand, REBARBANDINFO *pBandInfo, DWORD fMask)
|
|
{
|
|
if (!pBandInfo)
|
|
return E_INVALIDARG;
|
|
pBandInfo->cbSize = sizeof(REBARBANDINFO);
|
|
pBandInfo->fMask = fMask;
|
|
|
|
// Grab our bandinfo from rebar control
|
|
if (!SendMessage(RB_GETBANDINFO, uBand, reinterpret_cast<LPARAM>(pBandInfo)))
|
|
return E_INVALIDARG;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::AddBand(IUnknown *punk)
|
|
{
|
|
return InsertBar(punk);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::EnumBands(UINT uBand, DWORD *pdwBandID)
|
|
{
|
|
REBARBANDINFO bandInfo;
|
|
|
|
if (pdwBandID == NULL)
|
|
return E_INVALIDARG;
|
|
if (uBand == 0xffffffff)
|
|
{
|
|
*pdwBandID = (DWORD)SendMessage(RB_GETBANDCOUNT, 0, 0);
|
|
return S_OK;
|
|
}
|
|
if (!SUCCEEDED(GetInternalBandInfo(uBand, &bandInfo)))
|
|
return E_INVALIDARG;
|
|
*pdwBandID = bandInfo.wID;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryBand(DWORD dwBandID, IDeskBand **ppstb,
|
|
DWORD *pdwState, LPWSTR pszName, int cchName)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::RemoveBand(DWORD dwBandID)
|
|
{
|
|
REBARBANDINFO bandInfo;
|
|
HRESULT hr;
|
|
CBarInfo *pInfo;
|
|
CComPtr<IObjectWithSite> pSite;
|
|
CComPtr<IDeskBand> pDockWnd;
|
|
DWORD index;
|
|
|
|
// Retrieve the right index of the coolbar knowing the id
|
|
index = SendMessage(RB_IDTOINDEX, dwBandID, 0);
|
|
if (index == 0xffffffff)
|
|
return E_INVALIDARG;
|
|
|
|
if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &bandInfo)))
|
|
return E_INVALIDARG;
|
|
|
|
pInfo = reinterpret_cast<CBarInfo*>(bandInfo.lParam);
|
|
if (!pInfo)
|
|
return E_INVALIDARG;
|
|
|
|
hr = pInfo->fTheBar->QueryInterface(IID_PPV_ARG(IDeskBand, &pDockWnd));
|
|
if (FAILED_UNEXPECTEDLY(hr))
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
hr = pInfo->fTheBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pSite));
|
|
if (FAILED_UNEXPECTEDLY(hr))
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
/* Windows sends a CloseDW before setting site to NULL */
|
|
pDockWnd->CloseDW(0);
|
|
pSite->SetSite(NULL);
|
|
|
|
// Delete the band from rebar
|
|
if (!SendMessage(RB_DELETEBAND, index, 0))
|
|
{
|
|
ERR("Can't delete the band\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
if (pInfo == fCurrentActiveBar)
|
|
{
|
|
// FIXME: what to do when we are deleting active bar ? Let's assume we remove it for now
|
|
fCurrentActiveBar = NULL;
|
|
}
|
|
delete pInfo;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandObject(DWORD dwBandID, REFIID riid, void **ppv)
|
|
{
|
|
REBARBANDINFO bandInfo;
|
|
HRESULT hr;
|
|
CBarInfo *pInfo;
|
|
DWORD index;
|
|
|
|
if (ppv == NULL)
|
|
return E_POINTER;
|
|
|
|
// Retrieve the right index of the coolbar knowing the id
|
|
index = SendMessage(RB_IDTOINDEX, dwBandID, 0);
|
|
if (index == 0xffffffff)
|
|
return E_INVALIDARG;
|
|
|
|
if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &bandInfo)))
|
|
return E_INVALIDARG;
|
|
|
|
pInfo = reinterpret_cast<CBarInfo*>(bandInfo.lParam);
|
|
hr = pInfo->fTheBar->QueryInterface(riid, ppv);
|
|
if (!SUCCEEDED(hr))
|
|
return E_NOINTERFACE;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandSiteInfo(const BANDSITEINFO *pbsinfo)
|
|
{
|
|
if (pbsinfo == NULL)
|
|
return E_POINTER;
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandSiteInfo(BANDSITEINFO *pbsinfo)
|
|
{
|
|
if (pbsinfo == NULL)
|
|
return E_POINTER;
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::GetClassID(CLSID *pClassID)
|
|
{
|
|
if (pClassID == NULL)
|
|
return E_POINTER;
|
|
// TODO: what class to return here?
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::IsDirty()
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::Load(IStream *pStm)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::Save(IStream *pStm, BOOL fClearDirty)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CBaseBarSite::GetSizeMax(ULARGE_INTEGER *pcbSize)
|
|
{
|
|
if (pcbSize == NULL)
|
|
return E_POINTER;
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
LRESULT CBaseBarSite::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
|
|
{
|
|
NMHDR *notifyHeader;
|
|
|
|
notifyHeader = reinterpret_cast<NMHDR *>(lParam);
|
|
if (notifyHeader->hwndFrom == m_hWnd)
|
|
{
|
|
}
|
|
bHandled = FALSE; /* forward notification to parent */
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CBaseBarSite::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
|
|
{
|
|
if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDM_BASEBAR_CLOSE)
|
|
{
|
|
/* Tell the base bar to hide */
|
|
IUnknown_Exec(fDeskBarSite, IID_IDeskBarClient, 0, 0, NULL, NULL);
|
|
bHandled = TRUE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CBaseBarSite::OnCustomDraw(LPNMCUSTOMDRAW pnmcd)
|
|
{
|
|
switch (pnmcd->dwDrawStage)
|
|
{
|
|
case CDDS_PREPAINT:
|
|
case CDDS_PREERASE:
|
|
return CDRF_NOTIFYITEMDRAW;
|
|
case CDDS_ITEMPREPAINT:
|
|
if (fVertical)
|
|
{
|
|
REBARBANDINFO info;
|
|
WCHAR wszTitle[MAX_PATH];
|
|
DWORD index;
|
|
UINT pad = GetSystemMetrics(SM_CXEDGE), leftpad = max(pad * 2, 4);
|
|
UINT btnw = 20, btnh = 18, btnarea = 1 + btnw + 1;
|
|
HFONT newFont, oldFont;
|
|
|
|
index = SendMessage(RB_IDTOINDEX, fCurrentActiveBar->fBandID , 0);
|
|
ZeroMemory(&info, sizeof(info));
|
|
ZeroMemory(wszTitle, sizeof(wszTitle));
|
|
DrawEdge(pnmcd->hdc, &pnmcd->rc, EDGE_ETCHED, BF_BOTTOM);
|
|
// We also resize our close button
|
|
::SetWindowPos(toolbarWnd, HWND_TOP, pnmcd->rc.right - btnarea, 0, btnw, btnh, SWP_SHOWWINDOW);
|
|
// Draw the text
|
|
info.cch = MAX_PATH;
|
|
info.lpText = wszTitle;
|
|
RECT rt = pnmcd->rc;
|
|
rt.right -= btnarea;
|
|
rt.left += leftpad;
|
|
rt.bottom -= 1;
|
|
if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &info, RBBIM_TEXT)))
|
|
return CDRF_SKIPDEFAULT;
|
|
newFont = GetTitleFont();
|
|
if (newFont)
|
|
oldFont = (HFONT)SelectObject(pnmcd->hdc, newFont);
|
|
COLORREF orgclrtxt = SetTextColor(pnmcd->hdc, GetSysColor(COLOR_BTNTEXT));
|
|
DrawText(pnmcd->hdc, info.lpText, -1, &rt, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
|
|
SetTextColor(pnmcd->hdc, orgclrtxt);
|
|
SelectObject(pnmcd->hdc, oldFont);
|
|
DeleteObject(newFont);
|
|
return CDRF_SKIPDEFAULT;
|
|
}
|
|
else
|
|
{
|
|
DrawEdge(pnmcd->hdc, &pnmcd->rc, EDGE_ETCHED, BF_BOTTOM);
|
|
// We also resize our close button
|
|
::SetWindowPos(toolbarWnd, HWND_TOP, 0, 2, 20, 18, SWP_SHOWWINDOW);
|
|
}
|
|
return CDRF_SKIPDEFAULT;
|
|
default:
|
|
break;
|
|
}
|
|
return CDRF_DODEFAULT;
|
|
}
|
|
|
|
HFONT CBaseBarSite::GetTitleFont()
|
|
{
|
|
NONCLIENTMETRICS mt;
|
|
mt.cbSize = sizeof(mt);
|
|
if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(mt), &mt, 0))
|
|
{
|
|
ERR("Can't get system parameters !\n");
|
|
return NULL;
|
|
}
|
|
return CreateFontIndirect(&mt.lfMenuFont);
|
|
|
|
}
|
|
|
|
HRESULT CBaseBarSite::FindBandByGUID(REFGUID pGuid, DWORD *pdwBandID)
|
|
{
|
|
DWORD numBands;
|
|
DWORD i;
|
|
HRESULT hr;
|
|
REBARBANDINFO bandInfo;
|
|
CBarInfo *realInfo;
|
|
|
|
hr = EnumBands(-1, &numBands);
|
|
if (FAILED_UNEXPECTEDLY(hr))
|
|
return E_FAIL;
|
|
|
|
for(i = 0; i < numBands; i++)
|
|
{
|
|
if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(i, &bandInfo)))
|
|
return E_FAIL;
|
|
realInfo = (CBarInfo*)bandInfo.lParam;
|
|
if (IsEqualGUID(pGuid, realInfo->fBarClass))
|
|
{
|
|
*pdwBandID = realInfo->fBandID;
|
|
return S_OK;
|
|
}
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT CBaseBarSite::ShowBand(DWORD dwBandID)
|
|
{
|
|
UINT index;
|
|
CComPtr<IDeskBand> dockingWindow;
|
|
HRESULT hResult;
|
|
REBARBANDINFO bandInfo;
|
|
|
|
// show our band
|
|
hResult = GetBandObject(dwBandID, IID_PPV_ARG(IDeskBand, &dockingWindow));
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return E_FAIL;
|
|
|
|
hResult = dockingWindow->ShowDW(TRUE);
|
|
|
|
// Hide old band while adding new one
|
|
if (fCurrentActiveBar && fCurrentActiveBar->fBandID != dwBandID)
|
|
{
|
|
DWORD index;
|
|
index = SendMessage(RB_IDTOINDEX, fCurrentActiveBar->fBandID, 0);
|
|
if (index != 0xffffffff)
|
|
SendMessage(RB_SHOWBAND, index, 0);
|
|
}
|
|
if (FAILED_UNEXPECTEDLY(hResult))
|
|
return hResult;
|
|
|
|
// Display the current band
|
|
index = SendMessage(RB_IDTOINDEX, dwBandID, 0);
|
|
if (index != 0xffffffff)
|
|
SendMessage(RB_SHOWBAND, index, 1);
|
|
if (FAILED_UNEXPECTEDLY(GetInternalBandInfo(index, &bandInfo)))
|
|
return E_FAIL;
|
|
fCurrentActiveBar = (CBarInfo*)bandInfo.lParam;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CBaseBarSite_CreateInstance(REFIID riid, void **ppv, BOOL bVertical)
|
|
{
|
|
return ShellObjectCreatorInit<CBaseBarSite, BOOL>(bVertical, riid, ppv);
|
|
}
|