811 lines
22 KiB
C++
811 lines
22 KiB
C++
#include "priv.h"
|
|
#include "sccls.h"
|
|
#include "resource.h"
|
|
#include "mshtmhst.h"
|
|
#include "deskbar.h"
|
|
#include "bands.h"
|
|
#define WANT_CBANDSITE_CLASS
|
|
#include "bandsite.h"
|
|
|
|
#include <trayp.h> // TM_*
|
|
#include <desktray.h> // IDeskTray
|
|
|
|
#include "dbapp.h"
|
|
|
|
#include "mluisupp.h"
|
|
|
|
/*
|
|
this virtual app implments DeskBars that you have on the desktop.
|
|
it has the glue that combines CDeskBar with CBandSite and populates the
|
|
bands (as well as persistance and such)
|
|
|
|
-Chee
|
|
*/
|
|
|
|
#define DM_INIT 0
|
|
#define DM_PERSIST 0 // trace IPS::Load, ::Save, etc.
|
|
#define DM_MENU 0 // menu code
|
|
#define DM_DRAG 0 // drag&drop
|
|
#define DM_TRAY 0 // tray: marshal, side, etc.
|
|
|
|
#ifdef DEBUG
|
|
extern unsigned long DbStreamTell(IStream *pstm);
|
|
#else
|
|
#define DbStreamTell(pstm) ((ULONG) 0)
|
|
#endif
|
|
|
|
|
|
#define SUPERCLASS CDeskBar
|
|
|
|
/*
|
|
Instead of just 4 Deskbars on the whole desktop, we now have 4 deskbars for
|
|
each monitor, however, this brings problem whenever a monitor goes away, we
|
|
need to clean up the following datastructure.
|
|
- dli
|
|
*/
|
|
|
|
// FEATURE: (dli) maybe this should be moved into multimon.h
|
|
// however, people should not get into the habbit of depending on this.
|
|
// and it's really not used anywhere else, so, keep it here for now.
|
|
#define DSA_MONITORSGROW 1
|
|
|
|
typedef struct DeskBarsPerMonitor {
|
|
HMONITOR hMon;
|
|
IDeskBar* Deskbars[4];
|
|
} DESKBARSPERMONITOR, *LPDESKBARSPERMONITOR;
|
|
|
|
HDSA g_hdsaDeskBars = NULL;
|
|
|
|
enum ips_e {
|
|
IPS_FALSE, // reserved, must be 0 (FALSE)
|
|
IPS_LOAD,
|
|
IPS_INITNEW
|
|
};
|
|
|
|
CASSERT(IPS_FALSE == 0);
|
|
|
|
CDeskBarApp::~CDeskBarApp()
|
|
{
|
|
_LeaveSide();
|
|
|
|
if (_pbs)
|
|
_pbs->Release();
|
|
|
|
if (_pcm)
|
|
_pcm->Release();
|
|
|
|
}
|
|
|
|
LRESULT CDeskBarApp::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LRESULT lres = SUPERCLASS::v_WndProc(hwnd, uMsg, wParam, lParam);
|
|
|
|
if (!_hwnd) {
|
|
return lres; // destroyed by superclass
|
|
}
|
|
|
|
if (_eMode == WBM_BFLOATING) {
|
|
switch (uMsg) {
|
|
case WM_NOTIFY:
|
|
{
|
|
//
|
|
// override the hittest value to be HTCAPTION if we're docked browser based
|
|
//
|
|
NMHDR* pnm = (NMHDR*)lParam;
|
|
|
|
if (pnm->code == NM_NCHITTEST &&
|
|
pnm->hwndFrom == _hwndChild) {
|
|
//
|
|
// in the floating bug docked int he browser, we don't do
|
|
// mdi child stuff, so we make the gripper work as the caption
|
|
//
|
|
NMMOUSE* pnmm = (NMMOUSE*)pnm;
|
|
if (pnmm->dwHitInfo == RBHT_CAPTION ||
|
|
pnmm->dwHitInfo == RBHT_GRABBER)
|
|
lres = HTTRANSPARENT;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_NCHITTEST:
|
|
// all "client" areas are captions in this mode
|
|
if (lres == HTCLIENT)
|
|
lres = HTCAPTION;
|
|
break;
|
|
|
|
case WM_SETCURSOR:
|
|
DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return lres;
|
|
}
|
|
|
|
BOOL CDeskBarApp::_OnCloseBar(BOOL fConfirm)
|
|
{
|
|
// if we are closing a bar with no bands in it, don't pop up the dialog
|
|
if ((_pbs && (_pbs->EnumBands(-1,NULL)==0)) ||
|
|
(!fConfirm || ConfirmRemoveBand(_hwnd, IDS_CONFIRMCLOSEBAR, TEXT(""))) )
|
|
return SUPERCLASS::_OnCloseBar(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
// Gets the Deskbars on a specific monitor
|
|
// DBPM -- DeskBars Per Monitor
|
|
LPDESKBARSPERMONITOR GetDBPMWithMonitor(HMONITOR hMon, BOOL fCreate)
|
|
{
|
|
int ihdsa;
|
|
LPDESKBARSPERMONITOR pdbpm;
|
|
|
|
if (!g_hdsaDeskBars) {
|
|
if (fCreate)
|
|
g_hdsaDeskBars = DSA_Create(SIZEOF(DESKBARSPERMONITOR), DSA_MONITORSGROW);
|
|
}
|
|
|
|
if (!g_hdsaDeskBars)
|
|
return NULL;
|
|
|
|
// If we find the DBPM with this HMONITOR, return it.
|
|
for (ihdsa = 0; ihdsa < DSA_GetItemCount(g_hdsaDeskBars); ihdsa++) {
|
|
pdbpm = (LPDESKBARSPERMONITOR)DSA_GetItemPtr(g_hdsaDeskBars, ihdsa);
|
|
if (pdbpm->hMon == hMon)
|
|
return pdbpm;
|
|
}
|
|
|
|
if (fCreate) {
|
|
DESKBARSPERMONITOR dbpm = {0};
|
|
// This monitor is not setup, so set it, and set us the
|
|
// the ownder of _uSide
|
|
dbpm.hMon = hMon;
|
|
ihdsa = DSA_AppendItem(g_hdsaDeskBars, &dbpm);
|
|
pdbpm = (LPDESKBARSPERMONITOR)DSA_GetItemPtr(g_hdsaDeskBars, ihdsa);
|
|
return pdbpm;
|
|
}
|
|
|
|
// When all else fails, return NULL
|
|
return NULL;
|
|
}
|
|
|
|
void CDeskBarApp::_LeaveSide()
|
|
{
|
|
if (ISABE_DOCK(_uSide) && !ISWBM_FLOAT(_eMode)) {
|
|
// remove ourselves from the array list of where we were
|
|
LPDESKBARSPERMONITOR pdbpm = GetDBPMWithMonitor(_hMon, FALSE);
|
|
if (pdbpm && (pdbpm->Deskbars[_uSide] == this)) {
|
|
ASSERT(pdbpm->hMon);
|
|
ASSERT(pdbpm->hMon == _hMon);
|
|
pdbpm->Deskbars[_uSide] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//***
|
|
// NOTES
|
|
// FEATURE: should we create/use IDeskTray::AppBarGetState?
|
|
UINT GetTraySide(HMONITOR * phMon)
|
|
{
|
|
LRESULT lTmp;
|
|
APPBARDATA abd;
|
|
|
|
abd.cbSize = sizeof(APPBARDATA);
|
|
abd.hWnd = GetTrayWindow();
|
|
if (phMon)
|
|
Tray_GetHMonitor(abd.hWnd, phMon);
|
|
|
|
abd.uEdge = (UINT)-1;
|
|
//lTmp = g_pdtray->AppBarGetTaskBarPos(&abd);
|
|
lTmp = SHAppBarMessage(ABM_GETTASKBARPOS, &abd);
|
|
ASSERT(lTmp);
|
|
TraceMsg(DM_TRAY, "gts: ret=ABE_%d", abd.uEdge);
|
|
return abd.uEdge;
|
|
}
|
|
|
|
//***
|
|
// ENTRY/EXIT
|
|
// fNoMerge is for the IPS::Load case
|
|
// NOTES
|
|
// warning: be careful of reentrancy! fNoMove is how we guard against it.
|
|
void CDeskBarApp::_SetModeSide(UINT eMode, UINT uSide, HMONITOR hMonNew, BOOL fNoMerge)
|
|
{
|
|
BOOL fNoMove;
|
|
|
|
// make sure we don't merge etc. on NOOP moves.
|
|
// we do such moves to force refresh (e.g. for autohide and IPS::Load);
|
|
// also happens w/ drags which end up back where they started
|
|
fNoMove = (eMode == _eMode && uSide == _uSide && hMonNew == _hMon);
|
|
|
|
if (!fNoMove)
|
|
_LeaveSide();
|
|
|
|
// warning: this may call (e.g.) AppBarRegister, which causes a
|
|
// resize, which calls back to us. careful of reentrancy!!!
|
|
// if we do reenter we end up w/ nt5:155043, where entry #1 has
|
|
// fNoMove==0, then we get a recalc, entry #2 has fNoMove==1,
|
|
// and we set our side array to us, then return back to entry
|
|
// #1 which merges into itself!
|
|
SUPERCLASS::_SetModeSide(eMode, uSide, hMonNew, fNoMerge);
|
|
|
|
if (!fNoMove) {
|
|
if (ISABE_DOCK(_uSide) && !ISWBM_FLOAT(_eMode)) {
|
|
LPDESKBARSPERMONITOR pdbpm = GetDBPMWithMonitor(hMonNew, TRUE);
|
|
HMONITOR hMonTray = NULL;
|
|
if (pdbpm) {
|
|
if (fNoMerge) {
|
|
if (!pdbpm->Deskbars[_uSide]) {
|
|
// 1st guy on an edge owns it
|
|
// if we don't do this, when we load persisted state on logon
|
|
// we end up w/ *no* edge owner (since fNoMerge), so we don't
|
|
// merge on subsequent moves.
|
|
goto Lsetowner;
|
|
}
|
|
}
|
|
else if (pdbpm->Deskbars[_uSide]) {
|
|
// if someone already there, try merging into them
|
|
#ifdef DEBUG
|
|
// alt+drag suppresses merge
|
|
// DEBUG only since don't track >1 per side, but useful
|
|
// for testing appbars and toolbars anyway
|
|
if (!(GetKeyState(VK_MENU) < 0))
|
|
#endif
|
|
{
|
|
extern IBandSite* _GetBandSite(IDeskBar * pdb);
|
|
IBandSite *pbs;
|
|
|
|
pbs = _GetBandSite(pdbpm->Deskbars[_uSide]);
|
|
// nt5:215952: should 'never' have pbs==0 but somehow
|
|
// it does happen (during deskbar automation tests).
|
|
// call andyp or tjgreen if you hit this assert so
|
|
// we can figure out why.
|
|
if (TPTR(pbs)) {
|
|
_MergeSide(pbs); // dst=pbs, src=this
|
|
pbs->Release();
|
|
}
|
|
}
|
|
}
|
|
else if ((GetTraySide(&hMonTray) == _uSide) && (hMonTray == _hMon) && !(GetKeyState(VK_SHIFT) < 0)) {
|
|
// ditto for tray (but need to marshal/unmarshal)
|
|
#ifdef DEBUG
|
|
// alt+drag suppresses merge
|
|
// DEBUG only since don't track >1 per side, but useful
|
|
// for testing appbars and toolbars anyway
|
|
if (!(GetKeyState(VK_MENU) < 0))
|
|
#endif
|
|
{
|
|
_MergeSide((IBandSite *)1); // dst=pbs, src=this
|
|
}
|
|
}
|
|
else {
|
|
// o.w. nobody there yet, set ourselves as owner
|
|
ASSERT(pdbpm->hMon);
|
|
ASSERT(pdbpm->hMon == hMonNew);
|
|
Lsetowner:
|
|
TraceMsg(DM_TRAY, "cdba._sms: 1st side owner this=0x%x", this);
|
|
pdbpm->Deskbars[_uSide] = this;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CDeskBarApp::_UpdateCaptionTitle()
|
|
{
|
|
if (ISWBM_FLOAT(_eMode)) {
|
|
int iCount = (int)_pbs->EnumBands((UINT)-1, NULL);
|
|
if (iCount == 1) {
|
|
DWORD dwBandID;
|
|
if (SUCCEEDED(_pbs->EnumBands(0, &dwBandID))) {
|
|
WCHAR wszTitle[80];
|
|
if (SUCCEEDED(_pbs->QueryBand(dwBandID, NULL, NULL, wszTitle, ARRAYSIZE(wszTitle)))) {
|
|
USES_CONVERSION;
|
|
SetWindowText(_hwnd, W2T(wszTitle));
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
TCHAR szTitle[80];
|
|
szTitle[0] = 0;
|
|
MLLoadString(IDS_WEBBARSTITLE,szTitle,ARRAYSIZE(szTitle));
|
|
SetWindowText(_hwnd, szTitle);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CDeskBarApp::_NotifyModeChange(DWORD dwMode)
|
|
{
|
|
SUPERCLASS::_NotifyModeChange(dwMode);
|
|
_UpdateCaptionTitle();
|
|
}
|
|
|
|
//*** GetTrayIface -- get iface from tray (w/ marshal/unmarshal)
|
|
//
|
|
HRESULT GetTrayIface(REFIID riid, void **ppvObj)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
HWND hwndTray;
|
|
IStream *pstm;
|
|
|
|
TraceMsg(DM_TRAY, "gtif: marshal!");
|
|
|
|
*ppvObj = NULL;
|
|
|
|
hwndTray = GetTrayWindow();
|
|
if (hwndTray) {
|
|
pstm = (IStream *) SendMessage(hwndTray, TM_MARSHALBS, (WPARAM)(GUID *)&riid, 0);
|
|
|
|
if (EVAL(pstm)) {
|
|
// paired w/ matching Marshal in explorer (TM_MARSHALBS)
|
|
hr = CoGetInterfaceAndReleaseStream(pstm, riid, ppvObj);
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//*** _MergeSide -- merge two deskbars into one
|
|
// ENTRY/EXIT
|
|
// this [INOUT] destination deskbar (ptr:1 if tray)
|
|
// pdbSrc [INOUT] source deskbar; deleted if all bands moved successfully
|
|
// ret S_OK if all bands moved; S_FALSE if some moved; E_* o.w.
|
|
HRESULT CDeskBarApp::_MergeSide(IBandSite *pbsDst)
|
|
{
|
|
extern HRESULT _MergeBS(IDropTarget *pdtDst, IBandSite *pbsSrc);
|
|
HRESULT hr;
|
|
IDropTarget *pdtDst;
|
|
|
|
AddRef(); // make sure we don't disappear partway thru operation
|
|
|
|
if (pbsDst == (IBandSite *)1) {
|
|
// get (marshal'ed) iface from tray
|
|
hr = GetTrayIface(IID_IDropTarget, (void **)&pdtDst);
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
else {
|
|
// don't merge into ourself!
|
|
ASSERT(pbsDst != _pbs);
|
|
ASSERT(!SHIsSameObject(pbsDst, SAFECAST(_pbs, IBandSite*)));
|
|
|
|
hr = pbsDst->QueryInterface(IID_IDropTarget, (void **)&pdtDst);
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
ASSERT(SUCCEEDED(hr) || pdtDst == NULL);
|
|
|
|
if (pdtDst) {
|
|
hr = _MergeBS(pdtDst, _pbs);
|
|
pdtDst->Release();
|
|
}
|
|
|
|
Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
void CDeskBarApp::_CreateBandSiteMenu()
|
|
{
|
|
CoCreateInstance(CLSID_BandSiteMenu, NULL,CLSCTX_INPROC_SERVER,
|
|
IID_PPV_ARG(IContextMenu3, &_pcm));
|
|
if (_pcm)
|
|
{
|
|
IShellService* pss;
|
|
|
|
_pcm->QueryInterface(IID_IShellService, (LPVOID*)&pss);
|
|
if (pss)
|
|
{
|
|
pss->SetOwner((IBandSite*)_pbs);
|
|
pss->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
HRESULT CDeskBarApp::QueryInterface(REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
if (IsEqualIID(riid, IID_IContextMenu) ||
|
|
IsEqualIID(riid, IID_IContextMenu2) ||
|
|
IsEqualIID(riid, IID_IContextMenu3))
|
|
{
|
|
if (!_pcm)
|
|
{
|
|
_CreateBandSiteMenu();
|
|
}
|
|
|
|
// only return out our pointer if we got the one we're going
|
|
// to delegate to
|
|
if (_pcm)
|
|
{
|
|
*ppvObj = SAFECAST(this, IContextMenu3*);
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
}
|
|
return SUPERCLASS::QueryInterface(riid, ppvObj);
|
|
}
|
|
|
|
HRESULT CDeskBarApp::QueryService(REFGUID guidService,
|
|
REFIID riid, void **ppvObj)
|
|
{
|
|
if (IsEqualGUID(guidService,SID_SBandSite)) {
|
|
return QueryInterface(riid, ppvObj);
|
|
}
|
|
|
|
return SUPERCLASS::QueryService(guidService, riid, ppvObj);
|
|
}
|
|
|
|
|
|
HRESULT CDeskBarApp::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
|
|
{
|
|
int idCmd = -1;
|
|
|
|
if (!HIWORD(pici->lpVerb))
|
|
idCmd = LOWORD(pici->lpVerb);
|
|
|
|
if (idCmd >= _idCmdDeskBarFirst)
|
|
{
|
|
_AppBarOnCommand(idCmd - _idCmdDeskBarFirst);
|
|
return S_OK;
|
|
}
|
|
|
|
return _pcm->InvokeCommand(pici);
|
|
|
|
}
|
|
|
|
HRESULT CDeskBarApp::GetCommandString( UINT_PTR idCmd,
|
|
UINT uType,
|
|
UINT *pwReserved,
|
|
LPSTR pszName,
|
|
UINT cchMax)
|
|
{
|
|
return _pcm->GetCommandString(idCmd, uType, pwReserved, pszName, cchMax);
|
|
}
|
|
|
|
HRESULT CDeskBarApp::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return _pcm->HandleMenuMsg(uMsg, wParam, lParam);
|
|
}
|
|
|
|
HRESULT CDeskBarApp::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres)
|
|
{
|
|
return _pcm->HandleMenuMsg2(uMsg, wParam, lParam, plres);
|
|
}
|
|
|
|
HRESULT CDeskBarApp::QueryContextMenu(HMENU hmenu,
|
|
UINT indexMenu,
|
|
UINT idCmdFirst,
|
|
UINT idCmdLast,
|
|
UINT uFlags)
|
|
{
|
|
HRESULT hr = _pcm->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
int i = hr;
|
|
HMENU hmenuSrc;
|
|
|
|
_idCmdDeskBarFirst = i;
|
|
hmenuSrc = _GetContextMenu();
|
|
|
|
// off-by-1 and by idCmdFirst+i, i think...
|
|
i += Shell_MergeMenus(hmenu, hmenuSrc, (UINT)-1, idCmdFirst + i, idCmdLast, MM_ADDSEPARATOR) - (idCmdFirst + i);
|
|
DestroyMenu(hmenuSrc);
|
|
|
|
return ResultFromShort(i); // potentially off-by-1, but who cares...
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//***
|
|
// NOTES
|
|
// FEATURE: nuke this, fold it into CDeskBarApp_CreateInstance
|
|
HRESULT DeskBarApp_Create(IUnknown** ppunk)
|
|
{
|
|
HRESULT hres;
|
|
|
|
*ppunk = NULL;
|
|
|
|
CDeskBarApp *pdb = new CDeskBarApp();
|
|
if (!pdb)
|
|
return E_OUTOFMEMORY;
|
|
|
|
CBandSite *pcbs = new CBandSite(NULL);
|
|
if (pcbs)
|
|
{
|
|
IDeskBarClient *pdbc = SAFECAST(pcbs, IDeskBarClient*);
|
|
hres = pdb->SetClient(pdbc);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
pdb->_pbs = pcbs;
|
|
pcbs->AddRef();
|
|
*ppunk = SAFECAST(pdb, IDeskBar*);
|
|
}
|
|
|
|
pdbc->Release();
|
|
}
|
|
else
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (FAILED(hres))
|
|
pdb->Release();
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
STDAPI CDeskBarApp_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
|
|
{
|
|
HRESULT hres;
|
|
IUnknown *punk;
|
|
|
|
// aggregation checking is handled in class factory
|
|
|
|
hres = DeskBarApp_Create(&punk);
|
|
if (SUCCEEDED(hres)) {
|
|
*ppunk = SAFECAST(punk, IDockingWindow*);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//*** CDeskBarApp::IInputObject*::* {
|
|
//
|
|
|
|
HRESULT CDeskBarApp::TranslateAcceleratorIO(LPMSG lpMsg)
|
|
{
|
|
if (lpMsg->message == WM_SYSKEYDOWN) {
|
|
if (lpMsg->wParam == VK_F4) {
|
|
// ie4:28819: need to trap VK_F4 here, o.w. CBaseBrowser::TA
|
|
// does a last-chance (winsdk)::TA (to IDM_CLOSE) and doing a
|
|
// shutdown!
|
|
PostMessage(_hwnd, WM_CLOSE, 0, 0);
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return SUPERCLASS::TranslateAcceleratorIO(lpMsg);
|
|
}
|
|
|
|
// }
|
|
|
|
//*** CDeskBarApp::IPersistStream*::* {
|
|
//
|
|
|
|
HRESULT CDeskBarApp::GetClassID(CLSID *pClassID)
|
|
{
|
|
*pClassID = CLSID_DeskBarApp;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CDeskBarApp::IsDirty(void)
|
|
{
|
|
return S_FALSE; // Never be dirty
|
|
}
|
|
|
|
|
|
//
|
|
// Persisted CDeskBarApp
|
|
//
|
|
#define STC_VERSION 1
|
|
|
|
struct SThisClass
|
|
{
|
|
DWORD cbSize;
|
|
DWORD cbVersion;
|
|
};
|
|
|
|
HRESULT CDeskBarApp::Load(IStream *pstm)
|
|
{
|
|
SThisClass stc;
|
|
ULONG cbRead;
|
|
HRESULT hres;
|
|
|
|
TraceMsg(DM_PERSIST, "cdba.l enter(this=%x pstm=%x) tell()=%x", this, pstm, DbStreamTell(pstm));
|
|
|
|
ASSERT(!_eInitLoaded);
|
|
_eInitLoaded = IPS_LOAD;
|
|
|
|
hres = pstm->Read(&stc, SIZEOF(stc), &cbRead);
|
|
#ifdef DEBUG
|
|
// just in case we toast ourselves (offscreen or something)...
|
|
static BOOL fNoPersist = FALSE;
|
|
if (fNoPersist)
|
|
hres = E_FAIL;
|
|
#endif
|
|
if (hres==S_OK && cbRead==SIZEOF(stc)) {
|
|
if (stc.cbSize==SIZEOF(SThisClass) && stc.cbVersion==STC_VERSION) {
|
|
_eInitLoaded = IPS_LOAD; // FEATURE: what if OLFS of bands fails?
|
|
|
|
hres = SUPERCLASS::Load(pstm);
|
|
|
|
TraceMsg(DM_INIT, "cdba::Load succeeded");
|
|
} else {
|
|
TraceMsg(DM_ERROR, "cdba::Load failed stc.cbSize==SIZEOF(SThisClass) && stc.cbVersion==SWB_VERSION");
|
|
hres = E_FAIL;
|
|
}
|
|
} else {
|
|
TraceMsg(DM_ERROR, "cdba::Load failed (hres==S_OK && cbRead==SIZEOF(_adEdge)");
|
|
hres = E_FAIL;
|
|
}
|
|
TraceMsg(DM_PERSIST, "cdba.l leave tell()=%x", DbStreamTell(pstm));
|
|
|
|
// after loading this, if we find that we're supposed to be browser docked,
|
|
// make our bandsite always have a gripper
|
|
if (_eMode == WBM_BFLOATING)
|
|
{
|
|
BANDSITEINFO bsinfo;
|
|
|
|
bsinfo.dwMask = BSIM_STYLE;
|
|
bsinfo.dwStyle = BSIS_ALWAYSGRIPPER;
|
|
|
|
_pbs->SetBandSiteInfo(&bsinfo);
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
HRESULT CDeskBarApp::Save(IStream *pstm, BOOL fClearDirty)
|
|
{
|
|
HRESULT hres;
|
|
SThisClass stc;
|
|
|
|
TraceMsg(DM_PERSIST, "cdba.s enter(this=%x pstm=%x) tell()=%x", this, pstm, DbStreamTell(pstm));
|
|
stc.cbSize = SIZEOF(SThisClass);
|
|
stc.cbVersion = STC_VERSION;
|
|
|
|
hres = pstm->Write(&stc, SIZEOF(stc), NULL);
|
|
if (SUCCEEDED(hres)) {
|
|
SUPERCLASS::Save(pstm, fClearDirty);
|
|
}
|
|
|
|
TraceMsg(DM_PERSIST, "cdba.s leave tell()=%x", DbStreamTell(pstm));
|
|
return hres;
|
|
}
|
|
|
|
HRESULT CDeskBarApp::GetSizeMax(ULARGE_INTEGER *pcbSize)
|
|
{
|
|
ULARGE_INTEGER cbMax = { SIZEOF(SThisClass), 0 };
|
|
*pcbSize = cbMax;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CDeskBarApp::InitNew(void)
|
|
{
|
|
HRESULT hres;
|
|
|
|
ASSERT(!_eInitLoaded);
|
|
_eInitLoaded = IPS_INITNEW;
|
|
TraceMsg(DM_INIT, "CDeskBarApp::InitNew called");
|
|
|
|
hres = SUPERCLASS::InitNew();
|
|
if (FAILED(hres))
|
|
return hres;
|
|
|
|
// can't call _InitPos4 until set site in SetSite
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT CDeskBarApp::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
|
|
VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
|
|
{
|
|
if (pguidCmdGroup == NULL) {
|
|
/*NOTHING*/
|
|
}
|
|
else if (IsEqualGUID(CGID_DeskBarClient, *pguidCmdGroup)) {
|
|
switch (nCmdID) {
|
|
case DBCID_EMPTY:
|
|
if (_pbs) {
|
|
// if we have no bands left, close
|
|
PostMessage(_hwnd, WM_CLOSE, 0, 0);
|
|
}
|
|
return S_OK;
|
|
}
|
|
}
|
|
else if (IsEqualIID(*pguidCmdGroup, CGID_DeskBand)) {
|
|
switch (nCmdID) {
|
|
case DBID_BANDINFOCHANGED:
|
|
_UpdateCaptionTitle();
|
|
return S_OK;
|
|
}
|
|
}
|
|
else if (IsEqualIID(*pguidCmdGroup, CGID_BandSite)) {
|
|
switch (nCmdID) {
|
|
case BSID_BANDADDED:
|
|
case BSID_BANDREMOVED:
|
|
_UpdateCaptionTitle();
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return SUPERCLASS::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
|
|
}
|
|
|
|
HRESULT CDeskBarApp::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
|
|
{
|
|
HRESULT hres;
|
|
|
|
ASSERT(!_eInitLoaded);
|
|
_eInitLoaded = IPS_LOAD;
|
|
TraceMsg(DM_INIT, "CDeskBarApp::Load(bag) called");
|
|
|
|
hres = SUPERCLASS::Load(pPropBag, pErrorLog);
|
|
|
|
// after loading this, if we find that we're supposed to be browser docked,
|
|
// make our bandsite always have a gripper
|
|
if (_eMode == WBM_BFLOATING)
|
|
{
|
|
BANDSITEINFO bsinfo;
|
|
|
|
bsinfo.dwMask = BSIM_STYLE;
|
|
bsinfo.dwStyle = BSIS_ALWAYSGRIPPER;
|
|
|
|
_pbs->SetBandSiteInfo(&bsinfo);
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
IBandSite * _GetBandSite(IDeskBar * pdb)
|
|
{
|
|
IBandSite* pbs = NULL;
|
|
|
|
if (pdb) {
|
|
IUnknown* punkClient;
|
|
|
|
pdb->GetClient(&punkClient);
|
|
if (punkClient) {
|
|
punkClient->QueryInterface(IID_IBandSite, (LPVOID*)&pbs);
|
|
punkClient->Release();
|
|
}
|
|
}
|
|
|
|
return pbs;
|
|
}
|
|
|
|
|
|
IBandSite* DeskBarApp_GetBandSiteOnEdge(UINT uEdge)
|
|
{
|
|
// APPCOMPAT: (dli) if no HMONITOR is passed in, use the primary monitor
|
|
// should make sure that there is always a valid HMONITOR passed in
|
|
HMONITOR hMon = GetPrimaryMonitor();
|
|
// --------------------------------------------------------------
|
|
|
|
LPDESKBARSPERMONITOR pdbpm = GetDBPMWithMonitor(hMon, FALSE);
|
|
if (pdbpm) {
|
|
ASSERT(pdbpm->hMon);
|
|
ASSERT(pdbpm->hMon == hMon);
|
|
return _GetBandSite(pdbpm->Deskbars[uEdge]);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
IBandSite* DeskBarApp_GetBandSiteAtPoint(LPPOINT ppt)
|
|
{
|
|
HWND hwnd = WindowFromPoint(*ppt);
|
|
HMONITOR hMon = MonitorFromPoint(*ppt, MONITOR_DEFAULTTONULL);
|
|
if (hwnd && hMon) {
|
|
LPDESKBARSPERMONITOR pdbpm = GetDBPMWithMonitor(hMon, FALSE);
|
|
if (pdbpm) {
|
|
ASSERT(pdbpm->hMon);
|
|
ASSERT(pdbpm->hMon == hMon);
|
|
int i;
|
|
for (i = 0; i < 4; i++) {
|
|
if (pdbpm->Deskbars[i]) {
|
|
HWND hwndDeskbar;
|
|
pdbpm->Deskbars[i]->GetWindow(&hwndDeskbar);
|
|
|
|
if (hwndDeskbar == hwnd) {
|
|
return _GetBandSite(pdbpm->Deskbars[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// }
|