diff --git a/reactos/base/shell/rshell/CBandSite.cpp b/reactos/base/shell/rshell/CBandSite.cpp new file mode 100644 index 00000000000..b6f97a4a7b8 --- /dev/null +++ b/reactos/base/shell/rshell/CBandSite.cpp @@ -0,0 +1,842 @@ +/* + * Rebar band site + * + * Copyright 2007 Hervé Poussineau + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "precomp.h" +#include + +#include "CBandSite.h" + +WINE_DEFAULT_DEBUG_CHANNEL(CBandSite); + +#ifndef ASSERT +#define ASSERT(cond) \ + if (!(cond)) \ + ERR ("ASSERTION %s AT %s:%d FAILED!\n", #cond, __FILE__, __LINE__) +#endif + +extern "C" +HRESULT WINAPI CBandSite_Constructor(REFIID riid, LPVOID *ppv) +{ + return ShellObjectCreator(riid, ppv); +} + +CBandSiteBase::CBandSiteBase() +{ + fBandsCount = 0; + fBandsAllocated = 0; + fBands = NULL; + fRebarWindow = NULL; +} + +UINT CBandSiteBase::GetBandID(struct BandObject *Band) +{ + return (UINT)(Band - fBands); +} + +struct CBandSiteBase::BandObject *CBandSiteBase::GetBandByID(DWORD dwBandID) +{ + if ((LONG)dwBandID >= fBandsAllocated) + return NULL; + + if (fBands[dwBandID].DeskBand == NULL) + return NULL; + + return &fBands[dwBandID]; +} + +void CBandSiteBase::FreeBand(struct BandObject *Band) +{ + ATLASSERT(Band->DeskBand != NULL); + ATLASSERT(Band->OleWindow != NULL); + ATLASSERT(Band->WndEvtHandler != NULL); + Band->DeskBand->Release(); + Band->OleWindow->Release(); + Band->WndEvtHandler->Release(); + memset(Band, 0, sizeof(*Band)); + fBandsCount--; +} + +DWORD CBandSiteBase::GetBandSiteViewMode() +{ + DWORD dwStyle; + + /* FIXME: What about DBIF_VIEWMODE_FLOATING and DBIF_VIEWMODE_TRANSPARENT? */ + dwStyle = GetWindowLongPtr(fRebarWindow, GWL_STYLE); + + if (dwStyle & CCS_VERT) + return DBIF_VIEWMODE_VERTICAL; + else + return DBIF_VIEWMODE_NORMAL; +} + +VOID CBandSiteBase::BuildRebarBandInfo(struct BandObject *Band, REBARBANDINFOW *prbi) +{ + ZeroMemory(prbi, sizeof(*prbi)); + prbi->cbSize = sizeof(*prbi); + + prbi->fMask = RBBIM_ID; + prbi->wID = GetBandID(Band); + + if (Band->dbi.dwMask & DBIM_MINSIZE) + { + prbi->fMask |= RBBIM_CHILDSIZE; + prbi->cxMinChild = Band->dbi.ptMinSize.x; + prbi->cyMinChild = Band->dbi.ptMinSize.y; + } + + if (Band->dbi.dwMask & DBIM_MAXSIZE) + { + prbi->fMask |= RBBIM_CHILDSIZE; + prbi->cyMaxChild = Band->dbi.ptMaxSize.y; + } + + if ((Band->dbi.dwMask & (DBIM_INTEGRAL | DBIM_MODEFLAGS)) == (DBIM_INTEGRAL | DBIM_MODEFLAGS) && + (Band->dbi.dwModeFlags & DBIMF_VARIABLEHEIGHT)) + { + prbi->fMask |= RBBIM_CHILDSIZE; + prbi->cyIntegral = Band->dbi.ptIntegral.y; + } + + if (Band->dbi.dwMask & DBIM_ACTUAL) + { + prbi->fMask |= RBBIM_IDEALSIZE | RBBIM_SIZE | RBBIM_CHILDSIZE; + prbi->cxIdeal = Band->dbi.ptActual.x; + prbi->cx = Band->dbi.ptActual.x; + prbi->cyChild = Band->dbi.ptActual.y; + } + + if (Band->dbi.dwMask & DBIM_TITLE) + { + prbi->fMask |= RBBIM_TEXT; + prbi->lpText = Band->dbi.wszTitle; + prbi->cch = wcslen(Band->dbi.wszTitle); + } + + if (Band->dbi.dwMask & DBIM_MODEFLAGS) + { + prbi->fMask |= RBBIM_STYLE; + + if (Band->dbi.dwModeFlags & DBIMF_FIXED) + prbi->fStyle |= RBBS_FIXEDSIZE | RBBS_NOGRIPPER; + if (Band->dbi.dwModeFlags & DBIMF_FIXEDBMP) + prbi->fStyle |= RBBS_FIXEDBMP; + if (Band->dbi.dwModeFlags & DBIMF_VARIABLEHEIGHT) + prbi->fStyle |= RBBS_VARIABLEHEIGHT; + if (Band->dbi.dwModeFlags & DBIMF_DEBOSSED) + prbi->fStyle |= RBBS_CHILDEDGE; + if (Band->dbi.dwModeFlags & DBIMF_USECHEVRON) + prbi->fStyle |= RBBS_USECHEVRON; + if (Band->dbi.dwModeFlags & DBIMF_BREAK) + prbi->fStyle |= RBBS_BREAK; + if (Band->dbi.dwModeFlags & DBIMF_TOPALIGN) + prbi->fStyle |= RBBS_TOPALIGN; + if (Band->dbi.dwModeFlags & DBIMF_NOGRIPPER) + prbi->fStyle |= RBBS_NOGRIPPER; + if (Band->dbi.dwModeFlags & DBIMF_ALWAYSGRIPPER) + prbi->fStyle |= RBBS_GRIPPERALWAYS; + } + + if ((Band->dbi.dwMask & (DBIM_BKCOLOR | DBIM_MODEFLAGS)) == (DBIM_BKCOLOR | DBIM_MODEFLAGS) && + (Band->dbi.dwModeFlags & DBIMF_BKCOLOR)) + { + prbi->fMask |= RBBIM_COLORS; + prbi->clrFore = (COLORREF)(COLOR_WINDOWTEXT + 1); + prbi->clrBack = Band->dbi.crBkgnd; + } +} + +HRESULT CBandSiteBase::UpdateSingleBand(struct BandObject *Band) +{ + REBARBANDINFOW rbi; + DWORD dwViewMode; + UINT uBand; + HRESULT hRet; + + ZeroMemory(&Band->dbi, sizeof(Band->dbi)); + Band->dbi.dwMask = DBIM_MINSIZE | DBIM_MAXSIZE | DBIM_INTEGRAL | + DBIM_ACTUAL | DBIM_TITLE | DBIM_MODEFLAGS | DBIM_BKCOLOR; + + dwViewMode = GetBandSiteViewMode(); + + hRet = Band->DeskBand->GetBandInfo((DWORD)GetBandID(Band), dwViewMode, &Band->dbi); + if (SUCCEEDED(hRet)) + { + BuildRebarBandInfo(Band, &rbi); + if (SUCCEEDED(Band->OleWindow->GetWindow(&rbi.hwndChild)) && + rbi.hwndChild != NULL) + { + rbi.fMask |= RBBIM_CHILD; + WARN ("ReBar band uses child window 0x%p\n", rbi.hwndChild); + } + + uBand = (UINT)SendMessageW(fRebarWindow, RB_IDTOINDEX, (WPARAM)rbi.wID, 0); + if (uBand != (UINT)-1) + { + if (!SendMessageW(fRebarWindow, RB_SETBANDINFOW, (WPARAM)uBand, reinterpret_cast(&rbi))) + { + WARN("Failed to update the rebar band!\n"); + } + } + else + WARN("Failed to map rebar band id to index!\n"); + + } + + return hRet; +} + +HRESULT CBandSiteBase::UpdateAllBands() +{ + LONG i; + HRESULT hRet; + + for (i = 0; i < fBandsAllocated; i++) + { + if (fBands[i].DeskBand != NULL) + { + hRet = UpdateSingleBand(&fBands[i]); + if (FAILED_UNEXPECTEDLY(hRet)) + return hRet; + } + } + + return S_OK; +} + +HRESULT CBandSiteBase::UpdateBand(DWORD dwBandID) +{ + struct BandObject *Band; + + Band = GetBandByID(dwBandID); + if (Band == NULL) + return E_FAIL; + + return UpdateSingleBand(Band); +} + +struct CBandSiteBase::BandObject *CBandSiteBase::GetBandFromHwnd(HWND hwnd) +{ + HRESULT hRet; + HWND hWndBand; + LONG i; + + for (i = 0; i < fBandsAllocated; i++) + { + if (fBands[i].DeskBand != NULL) + { + ASSERT(fBands[i].OleWindow); + + hWndBand = NULL; + hRet = fBands[i].OleWindow->GetWindow(&hWndBand); + if (SUCCEEDED(hRet) && hWndBand == hwnd) + return &fBands[i]; + } + } + + return NULL; +} + +CBandSiteBase::~CBandSiteBase() +{ + + TRACE("destroying %p\n", this); + + if (fRebarWindow != NULL) + { + DestroyWindow(fRebarWindow); + fRebarWindow = NULL; + } + + if (fBands != NULL) + { + for (INT i = 0; i < fBandsAllocated; i++) + { + if (fBands[i].DeskBand != NULL) + FreeBand(&fBands[i]); + } + CoTaskMemFree(fBands); + fBands = NULL; + } +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::AddBand(IUnknown *punk) +{ + LONG NewAllocated; + struct BandObject *NewBand = NULL; + CComPtr DeskBand; + CComPtr ObjWithSite; + CComPtr OleWindow; + CComPtr WndEvtHandler; + REBARBANDINFOW rbi; + HRESULT hRet; + UINT uBand; + + TRACE("(%p, %p)\n", this, punk); + + if (punk == NULL || fRebarWindow == NULL) + return E_FAIL; + + hRet = punk->QueryInterface(IID_PPV_ARG(IDeskBand, &DeskBand)); + if (!SUCCEEDED(hRet) || DeskBand == NULL) + goto Cleanup; + hRet = punk->QueryInterface(IID_PPV_ARG(IObjectWithSite, &ObjWithSite)); + if (!SUCCEEDED(hRet) || ObjWithSite == NULL) + goto Cleanup; + hRet = punk->QueryInterface(IID_PPV_ARG(IOleWindow, &OleWindow)); + if (!SUCCEEDED(hRet) || OleWindow == NULL) + goto Cleanup; + hRet = punk->QueryInterface(IID_PPV_ARG(IWinEventHandler, &WndEvtHandler)); + if (!SUCCEEDED(hRet) || WndEvtHandler == NULL) + goto Cleanup; + + hRet = S_OK; + if (fBandsAllocated > fBandsCount) + { + /* Search for a free band object */ + for (INT i = 0; i < fBandsAllocated; i++) + { + if (fBands[i].DeskBand == NULL) + { + NewBand = &fBands[i]; + break; + } + } + } + else if (fBandsAllocated > 0) + { + ASSERT (fBands != NULL); + + /* Reallocate the band object array */ + NewAllocated = fBandsAllocated + 8; + if (NewAllocated > 0xFFFF) + NewAllocated = 0xFFFF; + if (NewAllocated == fBandsAllocated) + { + hRet = E_OUTOFMEMORY; + goto Cleanup; + } + + + NewBand = static_cast(CoTaskMemAlloc(NewAllocated * sizeof(struct BandObject))); + if (NewBand == NULL) + { + hRet = E_OUTOFMEMORY; + goto Cleanup; + } + + /* Copy the old array */ + memcpy(NewBand, fBands, fBandsAllocated * sizeof(struct BandObject)); + + /* Initialize the added bands */ + memset(&NewBand[fBandsAllocated], 0, (NewAllocated - fBandsAllocated) * sizeof(struct BandObject)); + + fBandsAllocated = NewAllocated; + CoTaskMemFree(fBands); + fBands = NewBand; + } + else + { + ASSERT(fBands == NULL); + ASSERT(fBandsAllocated == 0); + ASSERT(fBandsCount == 0); + + /* Allocate new array */ + fBands = static_cast(CoTaskMemAlloc(8 * sizeof(struct BandObject))); + if (fBands == NULL) + { + hRet = E_OUTOFMEMORY; + goto Cleanup; + } + + /* Initialize the added bands */ + memset(fBands, 0, 8 * sizeof(struct BandObject)); + + fBandsAllocated += 8; + NewBand = &fBands[0]; + } + + if (SUCCEEDED(hRet)) + { + ASSERT(NewBand != NULL); + + fBandsCount++; + NewBand->DeskBand = DeskBand.Detach(); + NewBand->OleWindow = OleWindow.Detach(); + NewBand->WndEvtHandler = WndEvtHandler.Detach(); + + /* Create the ReBar band */ + hRet = ObjWithSite->SetSite(static_cast(this)); + if (SUCCEEDED(hRet)) + { + uBand = 0xffffffff; + if (SUCCEEDED(UpdateSingleBand(NewBand))) + { + if (NewBand->dbi.dwMask & DBIM_MODEFLAGS) + { + if (NewBand->dbi.dwModeFlags & DBIMF_ADDTOFRONT) + uBand = 0; + } + } + + BuildRebarBandInfo(NewBand, &rbi); + + if (SUCCEEDED(NewBand->OleWindow->GetWindow(&rbi.hwndChild)) && + rbi.hwndChild != NULL) + { + rbi.fMask |= RBBIM_CHILD; + WARN ("ReBar band uses child window 0x%p\n", rbi.hwndChild); + } + + if (!SendMessageW(fRebarWindow, RB_INSERTBANDW, (WPARAM)uBand, reinterpret_cast(&rbi))) + return E_FAIL; + + hRet = (HRESULT)((USHORT)GetBandID(NewBand)); + } + else + { + WARN("IBandSite::AddBand(): Call to IDeskBand::SetSite() failed: %x\n", hRet); + + /* Remove the band from the ReBar control */ + BuildRebarBandInfo(NewBand, &rbi); + uBand = (UINT)SendMessageW(fRebarWindow, RB_IDTOINDEX, (WPARAM)rbi.wID, 0); + if (uBand != (UINT)-1) + { + if (!SendMessageW(fRebarWindow, RB_DELETEBAND, (WPARAM)uBand, 0)) + { + ERR("Failed to delete band!\n"); + } + } + else + ERR("Failed to map band id to index!\n"); + + FreeBand(NewBand); + + hRet = E_FAIL; + /* goto Cleanup; */ + } + } +Cleanup: + return hRet; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::EnumBands(UINT uBand, DWORD *pdwBandID) +{ + DWORD i; + + TRACE("(%p, %u, %p)\n", this, uBand, pdwBandID); + + if (uBand == 0xffffffff) + return (UINT)fBandsCount; + + if (uBand >= (UINT)fBandsCount) + return E_FAIL; + + for (i = 0; i < (DWORD)fBandsAllocated; i++) + { + if (fBands[i].DeskBand != NULL) + { + if (uBand == 0) + { + *pdwBandID = i; + return S_OK; + } + + uBand--; + } + } + + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::QueryBand(DWORD dwBandID, IDeskBand **ppstb, + DWORD *pdwState, LPWSTR pszName, int cchName) +{ + struct BandObject *Band; + + TRACE("(%p, %u, %p, %p, %p, %d)\n", this, dwBandID, ppstb, pdwState, pszName, cchName); + + Band = GetBandByID(dwBandID); + if (Band == NULL) + return E_FAIL; + + if (ppstb != NULL) + { + Band->DeskBand->AddRef(); + *ppstb = Band->DeskBand; + } + + if (pdwState != NULL) + { + FIXME("IBandSite::QueryBand() requests band state!\n"); + *pdwState = 0; + } + + if (pszName != NULL && cchName > 0) + { + FIXME("IBandSite::QueryBand() requests band name!\n"); + pszName[0] = 0; + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState) +{ + struct BandObject *Band; + + TRACE("(%p, %u, %x, %x)\n", this, dwBandID, dwMask, dwState); + + Band = GetBandByID(dwBandID); + if (Band == NULL) + return E_FAIL; + + FIXME("Stub\n"); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::RemoveBand(DWORD dwBandID) +{ + struct BandObject *Band; + UINT uBand; + + TRACE("(%p, %u)\n", this, dwBandID); + + if (fRebarWindow == NULL) + return E_FAIL; + + Band = GetBandByID(dwBandID); + if (Band == NULL) + return E_FAIL; + + uBand = (UINT)SendMessageW(fRebarWindow, RB_IDTOINDEX, (WPARAM)GetBandID(Band), 0); + if (uBand != (UINT)-1) + { + if (!SendMessageW(fRebarWindow, RB_DELETEBAND, (WPARAM)uBand, 0)) + { + ERR("Could not delete band!\n"); + } + } + else + ERR("Could not map band id to index!\n"); + + FreeBand(Band); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::GetBandObject(DWORD dwBandID, REFIID riid, VOID **ppv) +{ + struct BandObject *Band; + + TRACE("(%p, %u, %s, %p)\n", this, dwBandID, debugstr_guid(&riid), ppv); + + Band = GetBandByID(dwBandID); + if (Band == NULL) + { + *ppv = NULL; + return E_FAIL; + } + + return Band->DeskBand->QueryInterface(riid, ppv); +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::SetBandSiteInfo(const BANDSITEINFO *pbsinfo) +{ + FIXME("(%p, %p)\n", this, pbsinfo); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::GetBandSiteInfo(BANDSITEINFO *pbsinfo) +{ + FIXME("(%p, %p)\n", this, pbsinfo); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plrResult) +{ + struct BandObject *Band; + + TRACE("(%p, %p, %u, %p, %p, %p)\n", this, hWnd, uMsg, wParam, lParam, plrResult); + + *plrResult = 0; + if (fRebarWindow == NULL) + return E_FAIL; + + if (hWnd == fRebarWindow) + { + /* FIXME: Just send the message? */ + *plrResult = SendMessageW(hWnd, uMsg, wParam, lParam); + return S_OK; + } + + Band = GetBandFromHwnd(hWnd); + if (Band != NULL) + { + return Band->WndEvtHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, plrResult); + } + + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::IsWindowOwner(HWND hWnd) +{ + struct BandObject *Band; + + TRACE("(%p, %p)\n", this, hWnd); + + if (fRebarWindow == NULL) + return E_FAIL; + + Band = GetBandFromHwnd(hWnd); + if (Band != NULL) + return S_OK; + + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::GetWindow(HWND *phWnd) +{ + TRACE("(%p, %p)\n", this, phWnd); + + *phWnd = fRebarWindow; + if (fRebarWindow != NULL) + return S_OK; + + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::ContextSensitiveHelp(BOOL fEnterMode) +{ + FIXME("(%p, %d)\n", this, fEnterMode); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::SetDeskBarSite(IUnknown *pUnk) +{ + HWND hWndParent; + HRESULT hRet; + DWORD style; + + TRACE("(%p, %p)\n", this, pUnk); + + fOleWindow.Release(); + + hRet = pUnk->QueryInterface(IID_PPV_ARG(IOleWindow, &fOleWindow)); + if (FAILED_UNEXPECTEDLY(hRet)) + return E_FAIL; + + hRet = fOleWindow->GetWindow(&hWndParent); + if (FAILED_UNEXPECTEDLY(hRet)) + return E_FAIL; + + style = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | RBS_VARHEIGHT | RBS_AUTOSIZE | + RBS_BANDBORDERS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN; + + fRebarWindow = CreateWindowExW(WS_EX_TOOLWINDOW, + REBARCLASSNAMEW, + NULL, + style, + 0, 0, 0, 0, + hWndParent, + NULL, + _AtlBaseModule.GetModuleInstance(), + NULL); + if (fRebarWindow == NULL) + { + fOleWindow.Release(); + WARN("IDeskbarClient::SetDeskBarSite() failed to create ReBar control!\n"); + return E_FAIL; + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::SetModeDBC(DWORD dwMode) +{ + LONG dwStyle; + LONG dwPrevStyle; + + TRACE("(%p, %x)\n", this, dwMode); + + if (fRebarWindow == NULL) + return E_FAIL; + + dwStyle = dwPrevStyle = GetWindowLongPtr(fRebarWindow, GWL_STYLE); + if (dwMode & DBIF_VIEWMODE_VERTICAL) + dwStyle |= CCS_VERT; + + if (dwMode & ~DBIF_VIEWMODE_VERTICAL) + FIXME("IDeskBarClient::SetModeDBC() unhandled modes: %x\n", dwStyle & ~DBIF_VIEWMODE_VERTICAL); + + if (dwStyle != dwPrevStyle) + { + SetWindowLongPtr(fRebarWindow, GWL_STYLE, dwPrevStyle); + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::UIActivateDBC(DWORD dwState) +{ + TRACE("(%p, %x)\n", this, dwState); + + if (fRebarWindow == NULL) + return E_FAIL; + + ShowWindow(fRebarWindow, (dwState & DBC_SHOW) ? SW_SHOW : SW_HIDE); + FIXME("IDeskBarClient::UIActivateDBC() Properly notify bands?\n"); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::GetSize(DWORD unknown1, LPRECT unknown2) +{ + FIXME("(%p, %x, %p)\n", this, unknown1, unknown2); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::QueryStatus(const GUID *pguidCmdGroup, + DWORD cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText) +{ + FIXME("(%p, %p, %u, %p, %p)\n", this, pguidCmdGroup, cCmds, prgCmds, pCmdText); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, + DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut) +{ + HRESULT hRet = S_OK; + + TRACE("(%p, %p, %u, %u, %p, %p)\n", this, pguidCmdGroup, nCmdID, nCmdExecOpt, pvaIn, pvaOut); + + if (fRebarWindow == NULL) + return E_FAIL; + + if (IsEqualIID(*pguidCmdGroup, IID_IDeskBand)) + { + switch (nCmdID) + { + case DBID_BANDINFOCHANGED: + if (pvaIn == NULL) + hRet = UpdateAllBands(); + else + { + /* Update a single band */ + if (pvaIn->n1.n2.vt == VT_I4) + hRet = UpdateBand(pvaIn->n1.n2.n3.lVal); + else + hRet = E_FAIL; + } + break; + + case DBID_SHOWONLY: + case DBID_MAXIMIZEBAND: + case DBID_PUSHCHEVRON: + FIXME("IOleCommandTarget::Exec(): Unsupported command ID %d\n", nCmdID); + return E_NOTIMPL; + default: + return E_FAIL; + } + return hRet; + } + else + WARN("IOleCommandTarget::Exec(): Unsupported command group GUID\n"); + + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::UIActivateIO(BOOL fActivate, LPMSG lpMsg) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::HasFocusIO() +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::TranslateAcceleratorIO(LPMSG lpMsg) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::OnFocusChangeIS(struct IUnknown *paramC, int param10) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::GetClassID(CLSID *pClassID) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::IsDirty() +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::Load(IStream *pStm) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::Save(IStream *pStm, BOOL fClearDirty) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::GetSizeMax(ULARGE_INTEGER *pcbSize) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::DragEnter( + IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::DragLeave() +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::LoadFromStreamBS(IStream *, const GUID &, void **) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE CBandSiteBase::SaveToStreamBS(IUnknown *, IStream *) +{ + return E_NOTIMPL; +} diff --git a/reactos/base/shell/rshell/CBandSite.h b/reactos/base/shell/rshell/CBandSite.h new file mode 100644 index 00000000000..4ae4a1f5522 --- /dev/null +++ b/reactos/base/shell/rshell/CBandSite.h @@ -0,0 +1,148 @@ +/* + * Rebar band site + * + * Copyright 2007 Hervé Poussineau + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +class CBandSiteBase : + public CComObjectRootEx, + public IBandSite, + public IInputObjectSite, + public IInputObject, + public IDeskBarClient, + public IWinEventHandler, + public IPersistStream, + public IDropTarget, + public IServiceProvider, + public IBandSiteHelper, + public IOleCommandTarget +{ +private: + struct BandObject + { + IDeskBand *DeskBand; + IOleWindow *OleWindow; + IWinEventHandler *WndEvtHandler; + DESKBANDINFO dbi; + }; + + LONG fBandsCount; + LONG fBandsAllocated; + struct BandObject *fBands; + HWND fRebarWindow; + CComPtr fOleWindow; +public: + CBandSiteBase(); + ~CBandSiteBase(); + + // *** IBandSite 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); + + // *** IWinEventHandler methods *** + virtual HRESULT STDMETHODCALLTYPE OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult); + virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd); + + // *** IOleWindow methods *** + virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd); + virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); + + // *** 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); + + // *** IInputObject methods *** + virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg); + virtual HRESULT STDMETHODCALLTYPE HasFocusIO(); + virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg); + + // *** IInputObjectSite methods *** + virtual HRESULT STDMETHODCALLTYPE OnFocusChangeIS(struct IUnknown *paramC, int param10); + + // *** IServiceProvider methods *** + virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject); + + // *** 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); + + // *** IDropTarget methods *** + virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT STDMETHODCALLTYPE DragLeave(); + virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); + + // *** IBandSiteHelper methods *** + virtual HRESULT STDMETHODCALLTYPE LoadFromStreamBS(IStream *, const GUID &, void **); + virtual HRESULT STDMETHODCALLTYPE SaveToStreamBS(IUnknown *, IStream *); + +private: + UINT GetBandID(struct BandObject *Band); + struct BandObject *GetBandByID(DWORD dwBandID); + void FreeBand(struct BandObject *Band); + DWORD GetBandSiteViewMode(); + VOID BuildRebarBandInfo(struct BandObject *Band, REBARBANDINFOW *prbi); + HRESULT UpdateSingleBand(struct BandObject *Band); + HRESULT UpdateAllBands(); + HRESULT UpdateBand(DWORD dwBandID); + struct BandObject *GetBandFromHwnd(HWND hwnd); + + BEGIN_COM_MAP(CBandSiteBase) + COM_INTERFACE_ENTRY_IID(IID_IBandSite, IBandSite) + COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler) + COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow) + COM_INTERFACE_ENTRY_IID(IID_IDeskBarClient, IDeskBarClient) + COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) + COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject) + COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite) + COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider) + COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) + COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) + COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) + COM_INTERFACE_ENTRY_IID(IID_IBandSiteHelper, IBandSiteHelper) + END_COM_MAP() +}; + +class CBandSite : + public CComCoClass, + public CBandSiteBase +{ +public: + DECLARE_AGGREGATABLE(CBandSite) + + DECLARE_PROTECT_FINAL_CONSTRUCT() +}; diff --git a/reactos/base/shell/rshell/CMakeLists.txt b/reactos/base/shell/rshell/CMakeLists.txt index cb54c196af0..281b167af5a 100644 --- a/reactos/base/shell/rshell/CMakeLists.txt +++ b/reactos/base/shell/rshell/CMakeLists.txt @@ -7,6 +7,7 @@ include_directories(${REACTOS_SOURCE_DIR}/lib/atl) spec2def(rshell.dll rshell.spec ADD_IMPORTLIB) list(APPEND SOURCE + CBandSite.cpp CDesktopBrowser.cpp CMenuBand.cpp CMenuDeskBar.cpp diff --git a/reactos/base/shell/rshell/misc.cpp b/reactos/base/shell/rshell/misc.cpp index f2b835da2bb..28a03d14ba0 100644 --- a/reactos/base/shell/rshell/misc.cpp +++ b/reactos/base/shell/rshell/misc.cpp @@ -149,6 +149,7 @@ DllRegisterServer(void) RegisterComponent(CLSID_MenuBand, L"Shell Menu Band"); RegisterComponent(CLSID_MenuBandSite, L"Shell Menu Band Site"); RegisterComponent(CLSID_MergedFolder, L"Merged Shell Folder"); + RegisterComponent(CLSID_RebarBandSite, L"Shell Rebar Band Site"); return S_OK; } @@ -160,6 +161,7 @@ DllUnregisterServer(void) UnregisterComponent(CLSID_MenuBand); UnregisterComponent(CLSID_MenuBandSite); UnregisterComponent(CLSID_MergedFolder); + UnregisterComponent(CLSID_RebarBandSite); return S_OK; } @@ -200,6 +202,9 @@ public: if (IsEqualCLSID(m_Clsid, CLSID_MergedFolder)) return CMergedFolder_Constructor(riid, ppvObject); + if (IsEqualCLSID(m_Clsid, CLSID_RebarBandSite)) + return CBandSite_Constructor(riid, ppvObject); + return E_NOINTERFACE; } diff --git a/reactos/base/shell/rshell/precomp.h b/reactos/base/shell/rshell/precomp.h index 755eecbcc5b..17a508c317d 100644 --- a/reactos/base/shell/rshell/precomp.h +++ b/reactos/base/shell/rshell/precomp.h @@ -74,8 +74,5 @@ extern "C" HRESULT WINAPI CStartMenu_Constructor(REFIID riid, void **ppv); extern "C" HRESULT WINAPI CMenuDeskBar_Constructor(REFIID riid, LPVOID *ppv); extern "C" HRESULT WINAPI CMenuSite_Constructor(REFIID riid, LPVOID *ppv); extern "C" HRESULT WINAPI CMenuBand_Constructor(REFIID riid, LPVOID *ppv); -extern "C" HRESULT WINAPI CMenuDeskBar_Wrapper(IDeskBar * db, REFIID riid, LPVOID *ppv); -extern "C" HRESULT WINAPI CMenuSite_Wrapper(IBandSite * bs, REFIID riid, LPVOID *ppv); -extern "C" HRESULT WINAPI CMenuBand_Wrapper(IShellMenu * sm, REFIID riid, LPVOID *ppv); +extern "C" HRESULT WINAPI CBandSite_Constructor(REFIID riid, LPVOID *ppv); extern "C" HRESULT WINAPI CMergedFolder_Constructor(REFIID riid, LPVOID *ppv); -extern "C" HRESULT WINAPI CStartMenuSite_Wrapper(ITrayPriv * trayPriv, REFIID riid, LPVOID *ppv);