/* * ReactOS Explorer * * Copyright 2009 Andrew Hill * * 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: ****Fix so an already created bar will be detected and just shown instead of added again ****When a new bar is added, initiate a resize **Add owner draw for base bar **Make label text in base bar always draw in black **Make base bar show close box **Create close toolbar button **Fix to delete all CBarInfo on deletion */ class CBaseBarSite : public CWindowImpl, public CComObjectRootEx, // 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 fTheBar; CLSID fBarClass; // class of active bar DWORD fBandID; }; CBarInfo *fCurrentActiveBar; // // HWND fRebarWindow; // rebar for top of window CComPtr fDeskBarSite; DWORD fNextBandID; public: CBaseBarSite(); ~CBaseBarSite(); private: HRESULT InsertBar(IUnknown *newBar); // *** IOleWindow methods *** virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd); virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); // *** IInputObject methods *** virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg); virtual HRESULT STDMETHODCALLTYPE HasFocusIO(); virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg); // *** IServiceProvider methods *** virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject); // *** IWinEventHandler methods *** virtual HRESULT STDMETHODCALLTYPE OnWinEvent( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult); virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd); // *** IInputObjectSite specific methods *** virtual HRESULT STDMETHODCALLTYPE OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus); // *** IDeskBarClient methods *** virtual HRESULT STDMETHODCALLTYPE SetDeskBarSite(IUnknown *punkSite); virtual HRESULT STDMETHODCALLTYPE SetModeDBC(DWORD dwMode); virtual HRESULT STDMETHODCALLTYPE UIActivateDBC(DWORD dwState); virtual HRESULT STDMETHODCALLTYPE GetSize(DWORD dwWhich, LPRECT prc); // *** IOleCommandTarget methods *** virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText); virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut); // *** IBandSite specific methods *** virtual HRESULT STDMETHODCALLTYPE AddBand(IUnknown *punk); virtual HRESULT STDMETHODCALLTYPE EnumBands(UINT uBand, DWORD *pdwBandID); virtual HRESULT STDMETHODCALLTYPE QueryBand(DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState, LPWSTR pszName, int cchName); virtual HRESULT STDMETHODCALLTYPE SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState); virtual HRESULT STDMETHODCALLTYPE RemoveBand(DWORD dwBandID); virtual HRESULT STDMETHODCALLTYPE GetBandObject(DWORD dwBandID, REFIID riid, void **ppv); virtual HRESULT STDMETHODCALLTYPE SetBandSiteInfo(const BANDSITEINFO *pbsinfo); virtual HRESULT STDMETHODCALLTYPE GetBandSiteInfo(BANDSITEINFO *pbsinfo); // *** IPersist methods *** virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID); // *** IPersistStream methods *** virtual HRESULT STDMETHODCALLTYPE IsDirty(); virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm); virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty); virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize); // message handlers LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); BEGIN_MSG_MAP(CBaseBarSite) MESSAGE_HANDLER(WM_NOTIFY, OnNotify) 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() { fCurrentActiveBar = NULL; fNextBandID = 1; } CBaseBarSite::~CBaseBarSite() { } HRESULT CBaseBarSite::InsertBar(IUnknown *newBar) { CComPtr persist; CComPtr site; CComPtr oleWindow; CComPtr deskBand; CComPtr dockingWindow; CBarInfo *newInfo; REBARBANDINFOW bandInfo; DESKBANDINFO deskBandInfo; DWORD thisBandID; HRESULT hResult; 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; hResult = newBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow)); if (FAILED_UNEXPECTEDLY(hResult)) return hResult; hResult = site->SetSite(static_cast(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; hResult = persist->GetClassID(&newInfo->fBarClass); // get band info deskBandInfo.dwMask = DBIM_MINSIZE | DBIM_ACTUAL | DBIM_TITLE; deskBandInfo.wszTitle[0] = 0; hResult = deskBand->GetBandInfo(0, 0, &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_NOGRIPPER | RBBS_VARIABLEHEIGHT; bandInfo.lpText = deskBandInfo.wszTitle; hResult = oleWindow->GetWindow(&bandInfo.hwndChild); bandInfo.cxMinChild = 200; //deskBandInfo.ptMinSize.x; bandInfo.cyMinChild = 200; //deskBandInfo.ptMinSize.y; 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(newInfo); SendMessage(RB_INSERTBANDW, -1, reinterpret_cast(&bandInfo)); // this call is what makes the tree fill with contents hResult = dockingWindow->ShowDW(TRUE); if (FAILED_UNEXPECTEDLY(hResult)) return hResult; // for now fCurrentActiveBar = newInfo; return S_OK; } 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) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBaseBarSite::HasFocusIO() { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBaseBarSite::TranslateAcceleratorIO(LPMSG lpMsg) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) { CComPtr 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 deskBar; CComPtr winEventHandler; NMHDR *notifyHeader; RECT newBounds; HRESULT hResult; hResult = S_OK; if (uMsg == WM_NOTIFY) { notifyHeader = (NMHDR *)lParam; if (notifyHeader->hwndFrom == m_hWnd && notifyHeader->code == RBN_AUTOSIZE) { hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar)); GetClientRect(&newBounds); hResult = deskBar->OnPosRectChangeDB(&newBounds); } } 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) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBaseBarSite::SetDeskBarSite(IUnknown *punkSite) { CComPtr oleWindow; HWND ownerWindow; HRESULT hResult; if (punkSite == NULL) fDeskBarSite.Release(); else { 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; m_hWnd = CreateWindow(REBARCLASSNAMEW, NULL, WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | RBS_VARHEIGHT | RBS_REGISTERDROP | RBS_AUTOSIZE | RBS_VERTICALGRIPPER | RBS_DBLCLKTOGGLE | CCS_LEFT | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE, 0, 0, 0, 0, ownerWindow, NULL, _AtlBaseModule.GetModuleInstance(), NULL); SendMessage(RB_SETTEXTCOLOR, 0, CLR_DEFAULT); SendMessage(RB_SETBKCOLOR, 0, CLR_DEFAULT); } 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 1: // insert a new band if (V_VT(pvaIn) != VT_UNKNOWN) return E_INVALIDARG; return InsertBar(V_UNKNOWN(pvaIn)); } } return E_FAIL; } HRESULT STDMETHODCALLTYPE CBaseBarSite::AddBand(IUnknown *punk) { return InsertBar(punk); } HRESULT STDMETHODCALLTYPE CBaseBarSite::EnumBands(UINT uBand, DWORD *pdwBandID) { if (uBand == 0xffffffff) { *pdwBandID = (DWORD)SendMessage(RB_GETBANDCOUNT, 0, 0); return S_OK; } return E_NOTIMPL; } 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) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandObject(DWORD dwBandID, REFIID riid, void **ppv) { if (ppv == NULL) return E_POINTER; return E_NOTIMPL; } 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(lParam); if (notifyHeader->hwndFrom == m_hWnd) { } return 0; } HRESULT CreateBaseBarSite(REFIID riid, void **ppv) { return ShellObjectCreator(riid, ppv); }