Author: weiden
Date: Tue Jun 10 22:37:56 2008
New Revision: 33924
URL:
http://svn.reactos.org/svn/reactos?rev=33924&view=rev
Log:
Improve IBandSite support a bit
Modified:
trunk/reactos/dll/win32/browseui/bandsite.c
Modified: trunk/reactos/dll/win32/browseui/bandsite.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/browseui/bandsit…
==============================================================================
--- trunk/reactos/dll/win32/browseui/bandsite.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/browseui/bandsite.c [iso-8859-1] Tue Jun 10 22:37:56 2008
@@ -32,6 +32,7 @@
#include "shlwapi.h"
#include "winerror.h"
#include "objbase.h"
+#include "commctrl.h"
#include "docobj.h"
#include "shlguid.h"
@@ -46,9 +47,16 @@
WINE_DEFAULT_DEBUG_CHANNEL(browseui);
-struct SubBand {
- DWORD dwBandID;
- IUnknown *punk;
+#ifndef ASSERT
+#define ASSERT(cond) \
+ 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 {
@@ -57,9 +65,12 @@
const IDeskBarClientVtbl *deskbarVtbl;
const IOleCommandTargetVtbl *oletargetVtbl;
LONG refCount;
- INT nObjs;
- struct SubBand *objs;
+ LONG BandsCount;
+ LONG BandsAllocated;
+ struct BandObject *Bands;
IUnknown *pUnkOuter;
+ HWND hWndRebar;
+ IOleWindow *OleWindow;
} BandSite;
static const IBandSiteVtbl BandSiteVtbl;
@@ -82,19 +93,90 @@
return (BandSite *)((char *)iface - FIELD_OFFSET(BandSite, oletargetVtbl));
}
-static struct SubBand *get_band(BandSite *This, DWORD dwBandID)
-{
- INT i;
-
- for (i = 0; i < This->nObjs; i++)
- if (This->objs[i].dwBandID == dwBandID)
- return &This->objs[i];
- return NULL;
-}
-
-static void release_obj(struct SubBand *obj)
-{
- IUnknown_Release(obj->punk);
+static struct BandObject* GetBandByID(BandSite *This, DWORD dwBandID)
+{
+ if (dwBandID >= This->BandsAllocated)
+ return NULL;
+
+ if (This->Bands[dwBandID].DeskBand == NULL)
+ return NULL;
+
+ return &This->Bands[dwBandID];
+}
+
+static void FreeBand(BandSite *This, struct BandObject *Band)
+{
+ 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)
@@ -126,10 +208,33 @@
{
int i;
TRACE("destroying %p\n", This);
- IUnknown_Release(This->pUnkOuter);
- for (i = 0; i < This->nObjs; i++)
- release_obj(&This->objs[i]);
- CoTaskMemFree(This->objs);
+
+ if (This->hWndRebar != NULL)
+ {
+ 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);
BROWSEUI_refCount--;
}
@@ -191,101 +296,211 @@
static HRESULT WINAPI BandSite_AddBand(IBandSite *iface, IUnknown *punk)
{
BandSite *This = (BandSite *)iface;
- struct SubBand *newObjs, *current;
- DWORD freeID;
+ INT i;
+ LONG NewAllocated;
+ struct BandObject *NewBand = NULL;
+ IDeskBand *DeskBand;
+ HRESULT hRet;
TRACE("(%p, %p)\n", iface, punk);
- newObjs = CoTaskMemAlloc((This->nObjs + 1) * sizeof(struct SubBand));
- if (!newObjs)
- return E_OUTOFMEMORY;
- CopyMemory(newObjs, This->objs, This->nObjs * sizeof(struct SubBand));
- current = &newObjs[This->nObjs];
-
- freeID = This->nObjs;
- while (get_band(This, freeID) != NULL)
- freeID--;
- current->dwBandID = freeID;
- current->punk = punk;
-
- CoTaskMemFree(This->objs);
- This->objs = newObjs;
- This->nObjs++;
-
+ if (punk == NULL)
+ return E_FAIL;
+
+ hRet = IUnknown_QueryInterface(punk,
+ &IID_IDeskBand,
+ (PVOID*)&DeskBand);
+ if (!SUCCEEDED(hRet) || DeskBand == NULL)
+ return E_FAIL;
+
+ hRet = S_OK;
+ if (This->BandsAllocated > This->BandsCount)
+ {
+ /* 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);
+
+ /* 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)
+{
+ BandSite *This = (BandSite *)iface;
+ DWORD i;
+
+ TRACE("(%p, %u, %p)\n", iface, uBand, pdwBandID);
+
+ if (uBand == (UINT)-1)
+ return (UINT)This->BandsCount;
+
+ if (uBand >= This->BandsCount)
+ return E_FAIL;
+
+ for (i = 0; i < This->BandsAllocated; i++)
+ {
+ 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)
+{
+ BandSite *This = (BandSite *)iface;
+ struct BandObject *Band;
+
+ TRACE("(%p, %u, %p, %p, %p, %d)\n", iface, dwBandID, ppstb, pdwState,
pszName, cchName);
+
+ Band = GetBandByID(This, dwBandID);
+ if (Band == NULL)
+ return E_FAIL;
+
+ if (ppstb != NULL)
+ {
+ 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_EnumBands(IBandSite *iface, UINT uBand, DWORD *pdwBandID)
+static HRESULT WINAPI BandSite_SetBandState(IBandSite *iface, DWORD dwBandID, DWORD
dwMask, DWORD dwState)
{
BandSite *This = (BandSite *)iface;
-
- TRACE("(%p, %u, %p)\n", iface, uBand, pdwBandID);
-
- if (uBand >= This->nObjs)
- return E_FAIL;
-
- *pdwBandID = This->objs[uBand].dwBandID;
- return S_OK;
-}
-
-static HRESULT WINAPI BandSite_QueryBand(IBandSite *iface, DWORD dwBandID, IDeskBand
**ppstb, DWORD *pdwState, LPWSTR pszName, int cchName)
-{
- BandSite *This = (BandSite *)iface;
- struct SubBand *band;
-
- TRACE("(%p, %u, %p, %p, %p, %d)\n", iface, dwBandID, ppstb, pdwState,
pszName, cchName);
-
- band = get_band(This, dwBandID);
- if (!band)
+ struct BandObject *Band;
+
+ TRACE("(%p, %u, %x, %x)\n", iface, dwBandID, dwMask, dwState);
+
+ Band = GetBandByID(This, dwBandID);
+ if (Band == NULL)
return E_FAIL;
FIXME("Stub\n");
return E_NOTIMPL;
}
-static HRESULT WINAPI BandSite_SetBandState(IBandSite *iface, DWORD dwBandID, DWORD
dwMask, DWORD dwState)
+static HRESULT WINAPI BandSite_RemoveBand(IBandSite *iface, DWORD dwBandID)
{
BandSite *This = (BandSite *)iface;
- struct SubBand *band;
-
- TRACE("(%p, %u, %x, %x)\n", iface, dwBandID, dwMask, dwState);
-
- band = get_band(This, dwBandID);
- if (!band)
- return E_FAIL;
-
- FIXME("Stub\n");
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI BandSite_RemoveBand(IBandSite *iface, DWORD dwBandID)
+ struct BandObject *Band;
+
+ TRACE("(%p, %u)\n", iface, dwBandID);
+
+ Band = GetBandByID(This, dwBandID);
+ if (Band == NULL)
+ return E_FAIL;
+
+ FreeBand(This, Band);
+ return S_OK;
+}
+
+static HRESULT WINAPI BandSite_GetBandObject(IBandSite *iface, DWORD dwBandID, REFIID
riid, VOID **ppv)
{
BandSite *This = (BandSite *)iface;
- struct SubBand *band;
-
- TRACE("(%p, %u)\n", iface, dwBandID);
-
- band = get_band(This, dwBandID);
- if (!band)
- return E_FAIL;
-
- This->nObjs--;
- MoveMemory(band, band + 1, (This->objs - band - 1) * sizeof(struct SubBand));
- return S_OK;
-}
-
-static HRESULT WINAPI BandSite_GetBandObject(IBandSite *iface, DWORD dwBandID, REFIID
riid, VOID **ppv)
-{
- BandSite *This = (BandSite *)iface;
- struct SubBand *band;
+ struct BandObject *Band;
TRACE("(%p, %u, %s, %p)\n", iface, dwBandID, debugstr_guid(riid), ppv);
- band = get_band(This, dwBandID);
- if (!band)
- return E_FAIL;
-
- return IUnknown_QueryInterface(band->punk, riid, ppv);
+ Band = GetBandByID(This, dwBandID);
+ if (Band == NULL)
+ {
+ *ppv = NULL;
+ return E_FAIL;
+ }
+
+ return Band->DeskBand->lpVtbl->QueryInterface(Band->DeskBand, riid,
ppv);
}
static HRESULT WINAPI BandSite_SetBandSiteInfo(IBandSite *iface, const BANDSITEINFO
*pbsinfo)
@@ -382,8 +597,15 @@
static HRESULT WINAPI BandSite_IDeskBarClient_GetWindow(IDeskBarClient *iface, HWND
*phWnd)
{
- FIXME("(%p, %p)\n", iface, phWnd);
- return E_NOTIMPL;
+ BandSite *This = impl_from_IDeskBarClient(iface);
+
+ 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)
@@ -394,20 +616,97 @@
static HRESULT WINAPI BandSite_IDeskBarClient_SetDeskBarSite(IDeskBarClient *iface,
IUnknown *pUnk)
{
- FIXME("(%p, %p)\n", iface, pUnk);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI BandSite_IDeskBarClient_SetModeDBC(IDeskBarClient *iface, DWORD
unknown)
-{
- FIXME("(%p, %x)\n", iface, unknown);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI BandSite_IDeskBarClient_UIActivateDBC(IDeskBarClient *iface, DWORD
unknown)
-{
- FIXME("(%p, %x)\n", iface, unknown);
- return E_NOTIMPL;
+ BandSite *This = impl_from_IDeskBarClient(iface);
+ 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
dwMode)
+{
+ BandSite *This = impl_from_IDeskBarClient(iface);
+ 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
dwState)
+{
+ BandSite *This = impl_from_IDeskBarClient(iface);
+
+ 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)
@@ -460,7 +759,44 @@
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;
}