Improve IBandSite support a bit

svn path=/trunk/; revision=33924
This commit is contained in:
Thomas Bluemel 2008-06-11 03:37:56 +00:00
parent 46ccbc43af
commit 4a314da798

View file

@ -32,6 +32,7 @@
#include "shlwapi.h" #include "shlwapi.h"
#include "winerror.h" #include "winerror.h"
#include "objbase.h" #include "objbase.h"
#include "commctrl.h"
#include "docobj.h" #include "docobj.h"
#include "shlguid.h" #include "shlguid.h"
@ -46,9 +47,16 @@
WINE_DEFAULT_DEBUG_CHANNEL(browseui); WINE_DEFAULT_DEBUG_CHANNEL(browseui);
struct SubBand { #ifndef ASSERT
DWORD dwBandID; #define ASSERT(cond) \
IUnknown *punk; if (!(cond)) \
ERR ("ASSERTION %s AT %s:%d FAILED!\n", #cond, __FILE__, __LINE__)
#endif
extern HINSTANCE browseui_hinstance;
struct BandObject {
IDeskBand *DeskBand;
}; };
typedef struct tagBandSite { typedef struct tagBandSite {
@ -57,9 +65,12 @@ typedef struct tagBandSite {
const IDeskBarClientVtbl *deskbarVtbl; const IDeskBarClientVtbl *deskbarVtbl;
const IOleCommandTargetVtbl *oletargetVtbl; const IOleCommandTargetVtbl *oletargetVtbl;
LONG refCount; LONG refCount;
INT nObjs; LONG BandsCount;
struct SubBand *objs; LONG BandsAllocated;
struct BandObject *Bands;
IUnknown *pUnkOuter; IUnknown *pUnkOuter;
HWND hWndRebar;
IOleWindow *OleWindow;
} BandSite; } BandSite;
static const IBandSiteVtbl BandSiteVtbl; static const IBandSiteVtbl BandSiteVtbl;
@ -82,19 +93,90 @@ static inline BandSite *impl_from_IOleCommandTarget(IOleCommandTarget *iface)
return (BandSite *)((char *)iface - FIELD_OFFSET(BandSite, oletargetVtbl)); return (BandSite *)((char *)iface - FIELD_OFFSET(BandSite, oletargetVtbl));
} }
static struct SubBand *get_band(BandSite *This, DWORD dwBandID) static struct BandObject* GetBandByID(BandSite *This, DWORD dwBandID)
{ {
INT i; if (dwBandID >= This->BandsAllocated)
return NULL;
for (i = 0; i < This->nObjs; i++) if (This->Bands[dwBandID].DeskBand == NULL)
if (This->objs[i].dwBandID == dwBandID) return NULL;
return &This->objs[i];
return NULL; return &This->Bands[dwBandID];
} }
static void release_obj(struct SubBand *obj) static void FreeBand(BandSite *This, struct BandObject *Band)
{ {
IUnknown_Release(obj->punk); IUnknown_Release(Band->DeskBand);
ZeroMemory(Band, sizeof(*Band));
This->BandsCount--;
}
static DWORD GetBandSiteViewMode(BandSite *This)
{
DWORD dwStyle;
/* FIXME: What about DBIF_VIEWMODE_FLOATING and DBIF_VIEWMODE_TRANSPARENT? */
dwStyle = GetWindowLong(This->hWndRebar,
GWL_STYLE);
if (dwStyle & CCS_VERT)
return DBIF_VIEWMODE_VERTICAL;
else
return DBIF_VIEWMODE_NORMAL;
}
static HRESULT UpdateAllBands(BandSite *This)
{
DESKBANDINFO dbi;
DWORD dwViewMode;
LONG i;
HRESULT hRet;
dwViewMode = GetBandSiteViewMode(This);
for (i = 0; i < This->BandsAllocated; i++)
{
if (This->Bands[i].DeskBand != NULL)
{
ZeroMemory (&dbi, sizeof(dbi));
dbi.dwMask = 0;
/* FIXME */
hRet = IDeskBand_GetBandInfo(This->Bands[i].DeskBand,
i,
dwViewMode,
&dbi);
if (!SUCCEEDED(hRet))
return hRet;
}
}
return S_OK;
}
static HRESULT UpdateBand(BandSite *This, DWORD dwBandID)
{
struct BandObject *Band;
DESKBANDINFO dbi;
DWORD dwViewMode;
FIXME("UpdateBand(%x)\n", dwBandID);
Band = GetBandByID(This,
dwBandID);
if (Band == NULL)
return E_FAIL;
/* FIXME */
ZeroMemory (&dbi, sizeof(dbi));
dbi.dwMask = 0;
dwViewMode = GetBandSiteViewMode(This);
return IDeskBand_GetBandInfo(Band->DeskBand,
dwBandID,
dwViewMode,
&dbi);
} }
HRESULT WINAPI BandSite_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) HRESULT WINAPI BandSite_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
@ -126,10 +208,33 @@ static void WINAPI BandSite_Destructor(BandSite *This)
{ {
int i; int i;
TRACE("destroying %p\n", This); TRACE("destroying %p\n", This);
IUnknown_Release(This->pUnkOuter);
for (i = 0; i < This->nObjs; i++) if (This->hWndRebar != NULL)
release_obj(&This->objs[i]); {
CoTaskMemFree(This->objs); DestroyWindow(This->hWndRebar);
This->hWndRebar = NULL;
}
if (This->pUnkOuter != NULL)
{
IUnknown_Release(This->pUnkOuter);
This->pUnkOuter = NULL;
}
if (This->Bands != NULL)
{
for (i = 0; i < This->BandsAllocated; i++)
FreeBand(This, &This->Bands[i]);
CoTaskMemFree(This->Bands);
This->Bands = NULL;
}
if (This->OleWindow != NULL)
{
This->OleWindow->lpVtbl->Release(This->OleWindow);
This->OleWindow = NULL;
}
CoTaskMemFree(This); CoTaskMemFree(This);
BROWSEUI_refCount--; BROWSEUI_refCount--;
} }
@ -191,67 +296,175 @@ static ULONG WINAPI BandSite_Release(IBandSite *iface)
static HRESULT WINAPI BandSite_AddBand(IBandSite *iface, IUnknown *punk) static HRESULT WINAPI BandSite_AddBand(IBandSite *iface, IUnknown *punk)
{ {
BandSite *This = (BandSite *)iface; BandSite *This = (BandSite *)iface;
struct SubBand *newObjs, *current; INT i;
DWORD freeID; LONG NewAllocated;
struct BandObject *NewBand = NULL;
IDeskBand *DeskBand;
HRESULT hRet;
TRACE("(%p, %p)\n", iface, punk); TRACE("(%p, %p)\n", iface, punk);
newObjs = CoTaskMemAlloc((This->nObjs + 1) * sizeof(struct SubBand)); if (punk == NULL)
if (!newObjs) return E_FAIL;
return E_OUTOFMEMORY;
CopyMemory(newObjs, This->objs, This->nObjs * sizeof(struct SubBand));
current = &newObjs[This->nObjs];
freeID = This->nObjs; hRet = IUnknown_QueryInterface(punk,
while (get_band(This, freeID) != NULL) &IID_IDeskBand,
freeID--; (PVOID*)&DeskBand);
current->dwBandID = freeID; if (!SUCCEEDED(hRet) || DeskBand == NULL)
current->punk = punk; return E_FAIL;
CoTaskMemFree(This->objs); hRet = S_OK;
This->objs = newObjs; if (This->BandsAllocated > This->BandsCount)
This->nObjs++; {
/* Search for a free band object */
for (i = 0; i < This->BandsAllocated; i++)
{
if (This->Bands[i].DeskBand == NULL)
{
NewBand = &This->Bands[i];
break;
}
}
}
else if (This->BandsAllocated > 0)
{
ASSERT (This->Bands != NULL);
return S_OK; /* Reallocate the band object array */
NewAllocated = This->BandsAllocated + 8;
if (NewAllocated > 0xFFFF)
NewAllocated = 0xFFFF;
if (NewAllocated == This->BandsAllocated)
{
hRet = E_OUTOFMEMORY;
goto Cleanup;
}
NewBand = CoTaskMemAlloc(NewAllocated * sizeof(struct BandObject));
if (NewBand == NULL)
{
hRet = E_OUTOFMEMORY;
goto Cleanup;
}
/* Copy the old array */
CopyMemory(NewBand, This->Bands, This->BandsAllocated * sizeof(struct BandObject));
/* Initialize the added bands */
ZeroMemory(&NewBand[This->BandsAllocated], (NewAllocated - This->BandsAllocated) * sizeof(struct BandObject));
NewBand = &This->Bands[This->BandsAllocated];
This->BandsAllocated = NewAllocated;
CoTaskMemFree(This->Bands);
This->Bands = NewBand;
}
else
{
ASSERT(This->Bands == NULL);
ASSERT(This->BandsAllocated == 0);
ASSERT(This->BandsCount == 0);
/* Allocate new array */
This->Bands = CoTaskMemAlloc(8 * sizeof(struct BandObject));
if (This->Bands == NULL)
{
hRet = E_OUTOFMEMORY;
goto Cleanup;
}
/* Initialize the added bands */
ZeroMemory(This->Bands, 8 * sizeof(struct BandObject));
This->BandsAllocated += 8;
NewBand = &This->Bands[0];
}
if (SUCCEEDED(hRet))
{
ASSERT(NewBand != NULL);
NewBand->DeskBand = DeskBand;
This->BandsCount++;
return (HRESULT)((SHORT)(NewBand - This->Bands));
}
Cleanup:
if (DeskBand != NULL)
DeskBand->lpVtbl->Release(DeskBand);
return hRet;
} }
static HRESULT WINAPI BandSite_EnumBands(IBandSite *iface, UINT uBand, DWORD *pdwBandID) static HRESULT WINAPI BandSite_EnumBands(IBandSite *iface, UINT uBand, DWORD *pdwBandID)
{ {
BandSite *This = (BandSite *)iface; BandSite *This = (BandSite *)iface;
DWORD i;
TRACE("(%p, %u, %p)\n", iface, uBand, pdwBandID); TRACE("(%p, %u, %p)\n", iface, uBand, pdwBandID);
if (uBand >= This->nObjs) if (uBand == (UINT)-1)
return (UINT)This->BandsCount;
if (uBand >= This->BandsCount)
return E_FAIL; return E_FAIL;
*pdwBandID = This->objs[uBand].dwBandID; for (i = 0; i < This->BandsAllocated; i++)
return S_OK; {
if (This->Bands[i].DeskBand != NULL)
{
if (uBand == 0)
{
*pdwBandID = i;
return S_OK;
}
uBand--;
}
}
return E_FAIL;
} }
static HRESULT WINAPI BandSite_QueryBand(IBandSite *iface, DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState, LPWSTR pszName, int cchName) static HRESULT WINAPI BandSite_QueryBand(IBandSite *iface, DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState, LPWSTR pszName, int cchName)
{ {
BandSite *This = (BandSite *)iface; BandSite *This = (BandSite *)iface;
struct SubBand *band; struct BandObject *Band;
TRACE("(%p, %u, %p, %p, %p, %d)\n", iface, dwBandID, ppstb, pdwState, pszName, cchName); TRACE("(%p, %u, %p, %p, %p, %d)\n", iface, dwBandID, ppstb, pdwState, pszName, cchName);
band = get_band(This, dwBandID); Band = GetBandByID(This, dwBandID);
if (!band) if (Band == NULL)
return E_FAIL; return E_FAIL;
FIXME("Stub\n"); if (ppstb != NULL)
return E_NOTIMPL; {
Band->DeskBand->lpVtbl->AddRef(Band->DeskBand);
*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;
} }
static HRESULT WINAPI BandSite_SetBandState(IBandSite *iface, DWORD dwBandID, DWORD dwMask, DWORD dwState) static HRESULT WINAPI BandSite_SetBandState(IBandSite *iface, DWORD dwBandID, DWORD dwMask, DWORD dwState)
{ {
BandSite *This = (BandSite *)iface; BandSite *This = (BandSite *)iface;
struct SubBand *band; struct BandObject *Band;
TRACE("(%p, %u, %x, %x)\n", iface, dwBandID, dwMask, dwState); TRACE("(%p, %u, %x, %x)\n", iface, dwBandID, dwMask, dwState);
band = get_band(This, dwBandID); Band = GetBandByID(This, dwBandID);
if (!band) if (Band == NULL)
return E_FAIL; return E_FAIL;
FIXME("Stub\n"); FIXME("Stub\n");
@ -261,31 +474,33 @@ static HRESULT WINAPI BandSite_SetBandState(IBandSite *iface, DWORD dwBandID, DW
static HRESULT WINAPI BandSite_RemoveBand(IBandSite *iface, DWORD dwBandID) static HRESULT WINAPI BandSite_RemoveBand(IBandSite *iface, DWORD dwBandID)
{ {
BandSite *This = (BandSite *)iface; BandSite *This = (BandSite *)iface;
struct SubBand *band; struct BandObject *Band;
TRACE("(%p, %u)\n", iface, dwBandID); TRACE("(%p, %u)\n", iface, dwBandID);
band = get_band(This, dwBandID); Band = GetBandByID(This, dwBandID);
if (!band) if (Band == NULL)
return E_FAIL; return E_FAIL;
This->nObjs--; FreeBand(This, Band);
MoveMemory(band, band + 1, (This->objs - band - 1) * sizeof(struct SubBand));
return S_OK; return S_OK;
} }
static HRESULT WINAPI BandSite_GetBandObject(IBandSite *iface, DWORD dwBandID, REFIID riid, VOID **ppv) static HRESULT WINAPI BandSite_GetBandObject(IBandSite *iface, DWORD dwBandID, REFIID riid, VOID **ppv)
{ {
BandSite *This = (BandSite *)iface; BandSite *This = (BandSite *)iface;
struct SubBand *band; struct BandObject *Band;
TRACE("(%p, %u, %s, %p)\n", iface, dwBandID, debugstr_guid(riid), ppv); TRACE("(%p, %u, %s, %p)\n", iface, dwBandID, debugstr_guid(riid), ppv);
band = get_band(This, dwBandID); Band = GetBandByID(This, dwBandID);
if (!band) if (Band == NULL)
{
*ppv = NULL;
return E_FAIL; return E_FAIL;
}
return IUnknown_QueryInterface(band->punk, riid, ppv); return Band->DeskBand->lpVtbl->QueryInterface(Band->DeskBand, riid, ppv);
} }
static HRESULT WINAPI BandSite_SetBandSiteInfo(IBandSite *iface, const BANDSITEINFO *pbsinfo) static HRESULT WINAPI BandSite_SetBandSiteInfo(IBandSite *iface, const BANDSITEINFO *pbsinfo)
@ -382,8 +597,15 @@ static ULONG WINAPI BandSite_IDeskBarClient_Release(IDeskBarClient *iface)
static HRESULT WINAPI BandSite_IDeskBarClient_GetWindow(IDeskBarClient *iface, HWND *phWnd) static HRESULT WINAPI BandSite_IDeskBarClient_GetWindow(IDeskBarClient *iface, HWND *phWnd)
{ {
FIXME("(%p, %p)\n", iface, phWnd); BandSite *This = impl_from_IDeskBarClient(iface);
return E_NOTIMPL;
TRACE("(%p, %p)\n", iface, phWnd);
*phWnd = This->hWndRebar;
if (This->hWndRebar != NULL)
return S_OK;
return E_FAIL;
} }
static HRESULT WINAPI BandSite_IDeskBarClient_ContextSensitiveHelp(IDeskBarClient *iface, BOOL fEnterMode) static HRESULT WINAPI BandSite_IDeskBarClient_ContextSensitiveHelp(IDeskBarClient *iface, BOOL fEnterMode)
@ -394,20 +616,97 @@ static HRESULT WINAPI BandSite_IDeskBarClient_ContextSensitiveHelp(IDeskBarClien
static HRESULT WINAPI BandSite_IDeskBarClient_SetDeskBarSite(IDeskBarClient *iface, IUnknown *pUnk) static HRESULT WINAPI BandSite_IDeskBarClient_SetDeskBarSite(IDeskBarClient *iface, IUnknown *pUnk)
{ {
FIXME("(%p, %p)\n", iface, pUnk); BandSite *This = impl_from_IDeskBarClient(iface);
return E_NOTIMPL; HWND hWndParent;
HRESULT hRet;
TRACE("(%p, %p)\n", iface, pUnk);
if (This->OleWindow != NULL)
{
This->OleWindow->lpVtbl->Release(This->OleWindow);
This->OleWindow = NULL;
}
hRet = IUnknown_QueryInterface(pUnk,
&IID_IOleWindow,
(PVOID*)&This->OleWindow);
if (!SUCCEEDED(hRet))
{
This->OleWindow = NULL;
return E_FAIL;
}
hRet = IOleWindow_GetWindow(This->OleWindow,
&hWndParent);
if (!SUCCEEDED(hRet))
return E_FAIL;
This->hWndRebar = CreateWindowExW(WS_EX_TOOLWINDOW,
REBARCLASSNAMEW,
NULL,
WS_CHILD | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | RBS_VARHEIGHT |
CCS_NODIVIDER | RBS_BANDBORDERS,
0,
0,
0,
0,
hWndParent,
NULL,
browseui_hinstance,
NULL);
if (This->hWndRebar == NULL)
{
IOleWindow_Release(This->OleWindow);
This->OleWindow = NULL;
WARN("IDeskbarClient::SetDeskBarSite() failed to create ReBar control!\n");
return E_FAIL;
}
return S_OK;
} }
static HRESULT WINAPI BandSite_IDeskBarClient_SetModeDBC(IDeskBarClient *iface, DWORD unknown) static HRESULT WINAPI BandSite_IDeskBarClient_SetModeDBC(IDeskBarClient *iface, DWORD dwMode)
{ {
FIXME("(%p, %x)\n", iface, unknown); BandSite *This = impl_from_IDeskBarClient(iface);
return E_NOTIMPL; LONG dwStyle, dwPrevStyle;
TRACE("(%p, %x)\n", iface, dwMode);
if (This->hWndRebar == NULL)
return E_FAIL;
dwStyle = dwPrevStyle = GetWindowLong(This->hWndRebar,
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)
{
SetWindowLong(This->hWndRebar,
GWL_STYLE,
dwPrevStyle);
}
return S_OK;
} }
static HRESULT WINAPI BandSite_IDeskBarClient_UIActivateDBC(IDeskBarClient *iface, DWORD unknown) static HRESULT WINAPI BandSite_IDeskBarClient_UIActivateDBC(IDeskBarClient *iface, DWORD dwState)
{ {
FIXME("(%p, %x)\n", iface, unknown); BandSite *This = impl_from_IDeskBarClient(iface);
return E_NOTIMPL;
TRACE("(%p, %x)\n", iface, dwState);
if (This->hWndRebar == NULL)
return E_FAIL;
ShowWindow(This->hWndRebar, (dwState & DBC_SHOW) ? SW_SHOW : SW_HIDE);
FIXME("IDeskBarClient::UIActivateDBC() Properly notify bands?\n");
return S_OK;
} }
static HRESULT WINAPI BandSite_IDeskBarClient_GetSize(IDeskBarClient *iface, DWORD unknown1, LPRECT unknown2) static HRESULT WINAPI BandSite_IDeskBarClient_GetSize(IDeskBarClient *iface, DWORD unknown1, LPRECT unknown2)
@ -460,7 +759,44 @@ static HRESULT WINAPI BandSite_IOleCommandTarget_QueryStatus(IOleCommandTarget *
static HRESULT WINAPI BandSite_IOleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut) static HRESULT WINAPI BandSite_IOleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
{ {
FIXME("(%p, %p, %u, %u, %p, %p)\n", iface, pguidCmdGroup, nCmdID, nCmdExecOpt, pvaIn, pvaOut); BandSite *This = impl_from_IOleCommandTarget(iface);
HRESULT hRet = S_OK;
TRACE("(%p, %p, %u, %u, %p, %p)\n", iface, pguidCmdGroup, nCmdID, nCmdExecOpt, pvaIn, pvaOut);
if (This->hWndRebar == NULL)
return E_FAIL;
if (IsEqualIID(pguidCmdGroup, &IID_IDeskBand))
{
switch (nCmdID)
{
case DBID_BANDINFOCHANGED:
if (pvaIn == NULL)
hRet = UpdateAllBands(This);
else
{
/* Update a single band */
if (pvaIn->n1.n2.vt == VT_I4)
hRet = UpdateBand(This, 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 S_OK;
}
else
WARN("IOleCommandTarget::Exec(): Unsupported command group GUID\n");
return E_NOTIMPL; return E_NOTIMPL;
} }