Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

809 lines
23 KiB

  1. #include "priv.h"
  2. #include "sccls.h"
  3. #include "resource.h"
  4. #include "mshtmhst.h"
  5. #include "deskbar.h"
  6. #include "bands.h"
  7. #define WANT_CBANDSITE_CLASS
  8. #include "bandsite.h"
  9. #include <trayp.h> // TM_*
  10. #include <desktray.h> // IDeskTray
  11. #include "dbapp.h"
  12. #include "mluisupp.h"
  13. /*
  14. this virtual app implments DeskBars that you have on the desktop.
  15. it has the glue that combines CDeskBar with CBandSite and populates the
  16. bands (as well as persistance and such)
  17. -Chee
  18. */
  19. #define DM_INIT 0
  20. #define DM_PERSIST 0 // trace IPS::Load, ::Save, etc.
  21. #define DM_MENU 0 // menu code
  22. #define DM_DRAG 0 // drag&drop
  23. #define DM_TRAY 0 // tray: marshal, side, etc.
  24. #ifdef DEBUG
  25. extern unsigned long DbStreamTell(IStream *pstm);
  26. #else
  27. #define DbStreamTell(pstm) ((ULONG) 0)
  28. #endif
  29. #define SUPERCLASS CDeskBar
  30. /*
  31. Instead of just 4 Deskbars on the whole desktop, we now have 4 deskbars for
  32. each monitor, however, this brings problem whenever a monitor goes away, we
  33. need to clean up the following datastructure.
  34. - dli
  35. */
  36. // FEATURE: (dli) maybe this should be moved into multimon.h
  37. // however, people should not get into the habbit of depending on this.
  38. // and it's really not used anywhere else, so, keep it here for now.
  39. #define DSA_MONITORSGROW 1
  40. typedef struct DeskBarsPerMonitor {
  41. HMONITOR hMon;
  42. IDeskBar* Deskbars[4];
  43. } DESKBARSPERMONITOR, *LPDESKBARSPERMONITOR;
  44. HDSA g_hdsaDeskBars = NULL;
  45. enum ips_e {
  46. IPS_FALSE, // reserved, must be 0 (FALSE)
  47. IPS_LOAD,
  48. IPS_INITNEW
  49. };
  50. CASSERT(IPS_FALSE == 0);
  51. CDeskBarApp::~CDeskBarApp()
  52. {
  53. _LeaveSide();
  54. if (_pbs)
  55. _pbs->Release();
  56. if (_pcm)
  57. _pcm->Release();
  58. }
  59. LRESULT CDeskBarApp::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  60. {
  61. LRESULT lres = SUPERCLASS::v_WndProc(hwnd, uMsg, wParam, lParam);
  62. if (!_hwnd) {
  63. return lres; // destroyed by superclass
  64. }
  65. if (_eMode == WBM_BFLOATING) {
  66. switch (uMsg) {
  67. case WM_NOTIFY:
  68. {
  69. //
  70. // override the hittest value to be HTCAPTION if we're docked browser based
  71. //
  72. NMHDR* pnm = (NMHDR*)lParam;
  73. if (pnm->code == NM_NCHITTEST &&
  74. pnm->hwndFrom == _hwndChild) {
  75. //
  76. // in the floating bug docked int he browser, we don't do
  77. // mdi child stuff, so we make the gripper work as the caption
  78. //
  79. NMMOUSE* pnmm = (NMMOUSE*)pnm;
  80. if (pnmm->dwHitInfo == RBHT_CAPTION ||
  81. pnmm->dwHitInfo == RBHT_GRABBER)
  82. lres = HTTRANSPARENT;
  83. }
  84. }
  85. break;
  86. case WM_NCHITTEST:
  87. // all "client" areas are captions in this mode
  88. if (lres == HTCLIENT)
  89. lres = HTCAPTION;
  90. break;
  91. case WM_SETCURSOR:
  92. DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
  93. return TRUE;
  94. }
  95. }
  96. return lres;
  97. }
  98. BOOL CDeskBarApp::_OnCloseBar(BOOL fConfirm)
  99. {
  100. // if we are closing a bar with no bands in it, don't pop up the dialog
  101. if ((_pbs && (_pbs->EnumBands(-1,NULL)==0)) ||
  102. (!fConfirm || ConfirmRemoveBand(_hwnd, IDS_CONFIRMCLOSEBAR, TEXT(""))) )
  103. return SUPERCLASS::_OnCloseBar(FALSE);
  104. return FALSE;
  105. }
  106. // Gets the Deskbars on a specific monitor
  107. // DBPM -- DeskBars Per Monitor
  108. LPDESKBARSPERMONITOR GetDBPMWithMonitor(HMONITOR hMon, BOOL fCreate)
  109. {
  110. int ihdsa;
  111. LPDESKBARSPERMONITOR pdbpm;
  112. if (!g_hdsaDeskBars) {
  113. if (fCreate)
  114. g_hdsaDeskBars = DSA_Create(SIZEOF(DESKBARSPERMONITOR), DSA_MONITORSGROW);
  115. }
  116. if (!g_hdsaDeskBars)
  117. return NULL;
  118. // If we find the DBPM with this HMONITOR, return it.
  119. for (ihdsa = 0; ihdsa < DSA_GetItemCount(g_hdsaDeskBars); ihdsa++) {
  120. pdbpm = (LPDESKBARSPERMONITOR)DSA_GetItemPtr(g_hdsaDeskBars, ihdsa);
  121. if (pdbpm->hMon == hMon)
  122. return pdbpm;
  123. }
  124. if (fCreate) {
  125. DESKBARSPERMONITOR dbpm = {0};
  126. // This monitor is not setup, so set it, and set us the
  127. // the ownder of _uSide
  128. dbpm.hMon = hMon;
  129. ihdsa = DSA_AppendItem(g_hdsaDeskBars, &dbpm);
  130. pdbpm = (LPDESKBARSPERMONITOR)DSA_GetItemPtr(g_hdsaDeskBars, ihdsa);
  131. return pdbpm;
  132. }
  133. // When all else fails, return NULL
  134. return NULL;
  135. }
  136. void CDeskBarApp::_LeaveSide()
  137. {
  138. if (ISABE_DOCK(_uSide) && !ISWBM_FLOAT(_eMode)) {
  139. // remove ourselves from the array list of where we were
  140. LPDESKBARSPERMONITOR pdbpm = GetDBPMWithMonitor(_hMon, FALSE);
  141. if (pdbpm && (pdbpm->Deskbars[_uSide] == this)) {
  142. ASSERT(pdbpm->hMon);
  143. ASSERT(pdbpm->hMon == _hMon);
  144. pdbpm->Deskbars[_uSide] = NULL;
  145. }
  146. }
  147. }
  148. //***
  149. // NOTES
  150. // FEATURE: should we create/use IDeskTray::AppBarGetState?
  151. UINT GetTraySide(HMONITOR * phMon)
  152. {
  153. LRESULT lTmp;
  154. APPBARDATA abd;
  155. abd.cbSize = sizeof(APPBARDATA);
  156. abd.hWnd = GetTrayWindow();
  157. if (phMon)
  158. Tray_GetHMonitor(abd.hWnd, phMon);
  159. abd.uEdge = (UINT)-1;
  160. //lTmp = g_pdtray->AppBarGetTaskBarPos(&abd);
  161. lTmp = SHAppBarMessage(ABM_GETTASKBARPOS, &abd);
  162. ASSERT(lTmp);
  163. TraceMsg(DM_TRAY, "gts: ret=ABE_%d", abd.uEdge);
  164. return abd.uEdge;
  165. }
  166. //***
  167. // ENTRY/EXIT
  168. // fNoMerge is for the IPS::Load case
  169. // NOTES
  170. // warning: be careful of reentrancy! fNoMove is how we guard against it.
  171. void CDeskBarApp::_SetModeSide(UINT eMode, UINT uSide, HMONITOR hMonNew, BOOL fNoMerge)
  172. {
  173. BOOL fNoMove;
  174. // make sure we don't merge etc. on NOOP moves.
  175. // we do such moves to force refresh (e.g. for autohide and IPS::Load);
  176. // also happens w/ drags which end up back where they started
  177. fNoMove = (eMode == _eMode && uSide == _uSide && hMonNew == _hMon);
  178. if (!fNoMove)
  179. _LeaveSide();
  180. // warning: this may call (e.g.) AppBarRegister, which causes a
  181. // resize, which calls back to us. careful of reentrancy!!!
  182. // if we do reenter we end up w/ nt5:155043, where entry #1 has
  183. // fNoMove==0, then we get a recalc, entry #2 has fNoMove==1,
  184. // and we set our side array to us, then return back to entry
  185. // #1 which merges into itself!
  186. SUPERCLASS::_SetModeSide(eMode, uSide, hMonNew, fNoMerge);
  187. if (!fNoMove) {
  188. if (ISABE_DOCK(_uSide) && !ISWBM_FLOAT(_eMode)) {
  189. LPDESKBARSPERMONITOR pdbpm = GetDBPMWithMonitor(hMonNew, TRUE);
  190. HMONITOR hMonTray = NULL;
  191. if (pdbpm) {
  192. if (fNoMerge) {
  193. if (!pdbpm->Deskbars[_uSide]) {
  194. // 1st guy on an edge owns it
  195. // if we don't do this, when we load persisted state on logon
  196. // we end up w/ *no* edge owner (since fNoMerge), so we don't
  197. // merge on subsequent moves.
  198. goto Lsetowner;
  199. }
  200. }
  201. else if (pdbpm->Deskbars[_uSide]) {
  202. // if someone already there, try merging into them
  203. #ifdef DEBUG
  204. // alt+drag suppresses merge
  205. // DEBUG only since don't track >1 per side, but useful
  206. // for testing appbars and toolbars anyway
  207. if (!(GetKeyState(VK_MENU) < 0))
  208. #endif
  209. {
  210. extern IBandSite* _GetBandSite(IDeskBar * pdb);
  211. IBandSite *pbs;
  212. pbs = _GetBandSite(pdbpm->Deskbars[_uSide]);
  213. // nt5:215952: should 'never' have pbs==0 but somehow
  214. // it does happen (during deskbar automation tests).
  215. // call andyp or tjgreen if you hit this assert so
  216. // we can figure out why.
  217. if (TPTR(pbs)) {
  218. _MergeSide(pbs); // dst=pbs, src=this
  219. pbs->Release();
  220. }
  221. }
  222. }
  223. else if ((GetTraySide(&hMonTray) == _uSide) && (hMonTray == _hMon) && !(GetKeyState(VK_SHIFT) < 0)) {
  224. // ditto for tray (but need to marshal/unmarshal)
  225. #ifdef DEBUG
  226. // alt+drag suppresses merge
  227. // DEBUG only since don't track >1 per side, but useful
  228. // for testing appbars and toolbars anyway
  229. if (!(GetKeyState(VK_MENU) < 0))
  230. #endif
  231. {
  232. _MergeSide((IBandSite *)1); // dst=pbs, src=this
  233. }
  234. }
  235. else {
  236. // o.w. nobody there yet, set ourselves as owner
  237. ASSERT(pdbpm->hMon);
  238. ASSERT(pdbpm->hMon == hMonNew);
  239. Lsetowner:
  240. TraceMsg(DM_TRAY, "cdba._sms: 1st side owner this=0x%x", this);
  241. pdbpm->Deskbars[_uSide] = this;
  242. }
  243. }
  244. }
  245. }
  246. }
  247. void CDeskBarApp::_UpdateCaptionTitle()
  248. {
  249. if (ISWBM_FLOAT(_eMode)) {
  250. int iCount = (int)_pbs->EnumBands((UINT)-1, NULL);
  251. if (iCount == 1) {
  252. DWORD dwBandID;
  253. if (SUCCEEDED(_pbs->EnumBands(0, &dwBandID))) {
  254. WCHAR wszTitle[80];
  255. if (SUCCEEDED(_pbs->QueryBand(dwBandID, NULL, NULL, wszTitle, ARRAYSIZE(wszTitle)))) {
  256. SetWindowText(_hwnd, wszTitle);
  257. }
  258. }
  259. }
  260. else {
  261. TCHAR szTitle[80];
  262. szTitle[0] = 0;
  263. MLLoadString(IDS_WEBBARSTITLE,szTitle,ARRAYSIZE(szTitle));
  264. SetWindowText(_hwnd, szTitle);
  265. }
  266. }
  267. }
  268. void CDeskBarApp::_NotifyModeChange(DWORD dwMode)
  269. {
  270. SUPERCLASS::_NotifyModeChange(dwMode);
  271. _UpdateCaptionTitle();
  272. }
  273. //*** GetTrayIface -- get iface from tray (w/ marshal/unmarshal)
  274. //
  275. HRESULT GetTrayIface(REFIID riid, void **ppvObj)
  276. {
  277. HRESULT hr = E_FAIL;
  278. HWND hwndTray;
  279. IStream *pstm;
  280. TraceMsg(DM_TRAY, "gtif: marshal!");
  281. *ppvObj = NULL;
  282. hwndTray = GetTrayWindow();
  283. if (hwndTray) {
  284. pstm = (IStream *) SendMessage(hwndTray, TM_MARSHALBS, (WPARAM)(GUID *)&riid, 0);
  285. if (EVAL(pstm)) {
  286. // paired w/ matching Marshal in explorer (TM_MARSHALBS)
  287. hr = CoGetInterfaceAndReleaseStream(pstm, riid, ppvObj);
  288. ASSERT(SUCCEEDED(hr));
  289. }
  290. }
  291. return hr;
  292. }
  293. //*** _MergeSide -- merge two deskbars into one
  294. // ENTRY/EXIT
  295. // this [INOUT] destination deskbar (ptr:1 if tray)
  296. // pdbSrc [INOUT] source deskbar; deleted if all bands moved successfully
  297. // ret S_OK if all bands moved; S_FALSE if some moved; E_* o.w.
  298. HRESULT CDeskBarApp::_MergeSide(IBandSite *pbsDst)
  299. {
  300. extern HRESULT _MergeBS(IDropTarget *pdtDst, IBandSite *pbsSrc);
  301. HRESULT hr;
  302. IDropTarget *pdtDst;
  303. AddRef(); // make sure we don't disappear partway thru operation
  304. if (pbsDst == (IBandSite *)1) {
  305. // get (marshal'ed) iface from tray
  306. hr = GetTrayIface(IID_IDropTarget, (void **)&pdtDst);
  307. ASSERT(SUCCEEDED(hr));
  308. }
  309. else {
  310. // don't merge into ourself!
  311. ASSERT(pbsDst != _pbs);
  312. ASSERT(!SHIsSameObject(pbsDst, SAFECAST(_pbs, IBandSite*)));
  313. hr = pbsDst->QueryInterface(IID_IDropTarget, (void **)&pdtDst);
  314. ASSERT(SUCCEEDED(hr));
  315. }
  316. ASSERT(SUCCEEDED(hr) || pdtDst == NULL);
  317. if (pdtDst) {
  318. hr = _MergeBS(pdtDst, _pbs);
  319. pdtDst->Release();
  320. }
  321. Release();
  322. return hr;
  323. }
  324. void CDeskBarApp::_CreateBandSiteMenu()
  325. {
  326. CoCreateInstance(CLSID_BandSiteMenu, NULL,CLSCTX_INPROC_SERVER,
  327. IID_PPV_ARG(IContextMenu3, &_pcm));
  328. if (_pcm)
  329. {
  330. IShellService* pss;
  331. _pcm->QueryInterface(IID_IShellService, (LPVOID*)&pss);
  332. if (pss)
  333. {
  334. pss->SetOwner((IBandSite*)_pbs);
  335. pss->Release();
  336. }
  337. }
  338. }
  339. HRESULT CDeskBarApp::QueryInterface(REFIID riid, LPVOID * ppvObj)
  340. {
  341. if (IsEqualIID(riid, IID_IContextMenu) ||
  342. IsEqualIID(riid, IID_IContextMenu2) ||
  343. IsEqualIID(riid, IID_IContextMenu3))
  344. {
  345. if (!_pcm)
  346. {
  347. _CreateBandSiteMenu();
  348. }
  349. // only return out our pointer if we got the one we're going
  350. // to delegate to
  351. if (_pcm)
  352. {
  353. *ppvObj = SAFECAST(this, IContextMenu3*);
  354. AddRef();
  355. return S_OK;
  356. }
  357. }
  358. return SUPERCLASS::QueryInterface(riid, ppvObj);
  359. }
  360. HRESULT CDeskBarApp::QueryService(REFGUID guidService,
  361. REFIID riid, void **ppvObj)
  362. {
  363. if (IsEqualGUID(guidService,SID_SBandSite)) {
  364. return QueryInterface(riid, ppvObj);
  365. }
  366. return SUPERCLASS::QueryService(guidService, riid, ppvObj);
  367. }
  368. HRESULT CDeskBarApp::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
  369. {
  370. int idCmd = -1;
  371. if (!HIWORD(pici->lpVerb))
  372. idCmd = LOWORD(pici->lpVerb);
  373. if (idCmd >= _idCmdDeskBarFirst)
  374. {
  375. _AppBarOnCommand(idCmd - _idCmdDeskBarFirst);
  376. return S_OK;
  377. }
  378. return _pcm->InvokeCommand(pici);
  379. }
  380. HRESULT CDeskBarApp::GetCommandString( UINT_PTR idCmd,
  381. UINT uType,
  382. UINT *pwReserved,
  383. LPSTR pszName,
  384. UINT cchMax)
  385. {
  386. return _pcm->GetCommandString(idCmd, uType, pwReserved, pszName, cchMax);
  387. }
  388. HRESULT CDeskBarApp::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  389. {
  390. return _pcm->HandleMenuMsg(uMsg, wParam, lParam);
  391. }
  392. HRESULT CDeskBarApp::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres)
  393. {
  394. return _pcm->HandleMenuMsg2(uMsg, wParam, lParam, plres);
  395. }
  396. HRESULT CDeskBarApp::QueryContextMenu(HMENU hmenu,
  397. UINT indexMenu,
  398. UINT idCmdFirst,
  399. UINT idCmdLast,
  400. UINT uFlags)
  401. {
  402. HRESULT hr = _pcm->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
  403. if (SUCCEEDED(hr))
  404. {
  405. int i = hr;
  406. HMENU hmenuSrc;
  407. _idCmdDeskBarFirst = i;
  408. hmenuSrc = _GetContextMenu();
  409. // off-by-1 and by idCmdFirst+i, i think...
  410. i += Shell_MergeMenus(hmenu, hmenuSrc, (UINT)-1, idCmdFirst + i, idCmdLast, MM_ADDSEPARATOR) - (idCmdFirst + i);
  411. DestroyMenu(hmenuSrc);
  412. return ResultFromShort(i); // potentially off-by-1, but who cares...
  413. }
  414. return hr;
  415. }
  416. //***
  417. // NOTES
  418. // FEATURE: nuke this, fold it into CDeskBarApp_CreateInstance
  419. HRESULT DeskBarApp_Create(IUnknown** ppunk)
  420. {
  421. HRESULT hres;
  422. *ppunk = NULL;
  423. CDeskBarApp *pdb = new CDeskBarApp();
  424. if (!pdb)
  425. return E_OUTOFMEMORY;
  426. CBandSite *pcbs = new CBandSite(NULL);
  427. if (pcbs)
  428. {
  429. IDeskBarClient *pdbc = SAFECAST(pcbs, IDeskBarClient*);
  430. hres = pdb->SetClient(pdbc);
  431. if (SUCCEEDED(hres))
  432. {
  433. pdb->_pbs = pcbs;
  434. pcbs->AddRef();
  435. *ppunk = SAFECAST(pdb, IDeskBar*);
  436. }
  437. pdbc->Release();
  438. }
  439. else
  440. {
  441. hres = E_OUTOFMEMORY;
  442. }
  443. if (FAILED(hres))
  444. pdb->Release();
  445. return hres;
  446. }
  447. STDAPI CDeskBarApp_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  448. {
  449. HRESULT hres;
  450. IUnknown *punk;
  451. // aggregation checking is handled in class factory
  452. hres = DeskBarApp_Create(&punk);
  453. if (SUCCEEDED(hres)) {
  454. *ppunk = SAFECAST(punk, IDockingWindow*);
  455. return S_OK;
  456. }
  457. return E_OUTOFMEMORY;
  458. }
  459. //*** CDeskBarApp::IInputObject*::* {
  460. //
  461. HRESULT CDeskBarApp::TranslateAcceleratorIO(LPMSG lpMsg)
  462. {
  463. if (lpMsg->message == WM_SYSKEYDOWN) {
  464. if (lpMsg->wParam == VK_F4) {
  465. // ie4:28819: need to trap VK_F4 here, o.w. CBaseBrowser::TA
  466. // does a last-chance (winsdk)::TA (to IDM_CLOSE) and doing a
  467. // shutdown!
  468. PostMessage(_hwnd, WM_CLOSE, 0, 0);
  469. return S_OK;
  470. }
  471. }
  472. return SUPERCLASS::TranslateAcceleratorIO(lpMsg);
  473. }
  474. // }
  475. //*** CDeskBarApp::IPersistStream*::* {
  476. //
  477. HRESULT CDeskBarApp::GetClassID(CLSID *pClassID)
  478. {
  479. *pClassID = CLSID_DeskBarApp;
  480. return S_OK;
  481. }
  482. HRESULT CDeskBarApp::IsDirty(void)
  483. {
  484. return S_FALSE; // Never be dirty
  485. }
  486. //
  487. // Persisted CDeskBarApp
  488. //
  489. #define STC_VERSION 1
  490. struct SThisClass
  491. {
  492. DWORD cbSize;
  493. DWORD cbVersion;
  494. };
  495. HRESULT CDeskBarApp::Load(IStream *pstm)
  496. {
  497. SThisClass stc;
  498. ULONG cbRead;
  499. HRESULT hres;
  500. TraceMsg(DM_PERSIST, "cdba.l enter(this=%x pstm=%x) tell()=%x", this, pstm, DbStreamTell(pstm));
  501. ASSERT(!_eInitLoaded);
  502. _eInitLoaded = IPS_LOAD;
  503. hres = pstm->Read(&stc, SIZEOF(stc), &cbRead);
  504. #ifdef DEBUG
  505. // just in case we toast ourselves (offscreen or something)...
  506. static BOOL fNoPersist = FALSE;
  507. if (fNoPersist)
  508. hres = E_FAIL;
  509. #endif
  510. if (hres==S_OK && cbRead==SIZEOF(stc)) {
  511. if (stc.cbSize==SIZEOF(SThisClass) && stc.cbVersion==STC_VERSION) {
  512. _eInitLoaded = IPS_LOAD; // FEATURE: what if OLFS of bands fails?
  513. hres = SUPERCLASS::Load(pstm);
  514. TraceMsg(DM_INIT, "cdba::Load succeeded");
  515. } else {
  516. TraceMsg(DM_ERROR, "cdba::Load failed stc.cbSize==SIZEOF(SThisClass) && stc.cbVersion==SWB_VERSION");
  517. hres = E_FAIL;
  518. }
  519. } else {
  520. TraceMsg(DM_ERROR, "cdba::Load failed (hres==S_OK && cbRead==SIZEOF(_adEdge)");
  521. hres = E_FAIL;
  522. }
  523. TraceMsg(DM_PERSIST, "cdba.l leave tell()=%x", DbStreamTell(pstm));
  524. // after loading this, if we find that we're supposed to be browser docked,
  525. // make our bandsite always have a gripper
  526. if (_eMode == WBM_BFLOATING)
  527. {
  528. BANDSITEINFO bsinfo;
  529. bsinfo.dwMask = BSIM_STYLE;
  530. bsinfo.dwStyle = BSIS_ALWAYSGRIPPER;
  531. _pbs->SetBandSiteInfo(&bsinfo);
  532. }
  533. return hres;
  534. }
  535. HRESULT CDeskBarApp::Save(IStream *pstm, BOOL fClearDirty)
  536. {
  537. HRESULT hres;
  538. SThisClass stc;
  539. TraceMsg(DM_PERSIST, "cdba.s enter(this=%x pstm=%x) tell()=%x", this, pstm, DbStreamTell(pstm));
  540. stc.cbSize = SIZEOF(SThisClass);
  541. stc.cbVersion = STC_VERSION;
  542. hres = pstm->Write(&stc, SIZEOF(stc), NULL);
  543. if (SUCCEEDED(hres)) {
  544. SUPERCLASS::Save(pstm, fClearDirty);
  545. }
  546. TraceMsg(DM_PERSIST, "cdba.s leave tell()=%x", DbStreamTell(pstm));
  547. return hres;
  548. }
  549. HRESULT CDeskBarApp::GetSizeMax(ULARGE_INTEGER *pcbSize)
  550. {
  551. ULARGE_INTEGER cbMax = { SIZEOF(SThisClass), 0 };
  552. *pcbSize = cbMax;
  553. return S_OK;
  554. }
  555. HRESULT CDeskBarApp::InitNew(void)
  556. {
  557. HRESULT hres;
  558. ASSERT(!_eInitLoaded);
  559. _eInitLoaded = IPS_INITNEW;
  560. TraceMsg(DM_INIT, "CDeskBarApp::InitNew called");
  561. hres = SUPERCLASS::InitNew();
  562. if (FAILED(hres))
  563. return hres;
  564. // can't call _InitPos4 until set site in SetSite
  565. return hres;
  566. }
  567. HRESULT CDeskBarApp::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
  568. VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  569. {
  570. if (pguidCmdGroup == NULL) {
  571. /*NOTHING*/
  572. }
  573. else if (IsEqualGUID(CGID_DeskBarClient, *pguidCmdGroup)) {
  574. switch (nCmdID) {
  575. case DBCID_EMPTY:
  576. if (_pbs) {
  577. // if we have no bands left, close
  578. PostMessage(_hwnd, WM_CLOSE, 0, 0);
  579. }
  580. return S_OK;
  581. }
  582. }
  583. else if (IsEqualIID(*pguidCmdGroup, CGID_DeskBand)) {
  584. switch (nCmdID) {
  585. case DBID_BANDINFOCHANGED:
  586. _UpdateCaptionTitle();
  587. return S_OK;
  588. }
  589. }
  590. else if (IsEqualIID(*pguidCmdGroup, CGID_BandSite)) {
  591. switch (nCmdID) {
  592. case BSID_BANDADDED:
  593. case BSID_BANDREMOVED:
  594. _UpdateCaptionTitle();
  595. return S_OK;
  596. }
  597. }
  598. return SUPERCLASS::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  599. }
  600. HRESULT CDeskBarApp::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
  601. {
  602. HRESULT hres;
  603. ASSERT(!_eInitLoaded);
  604. _eInitLoaded = IPS_LOAD;
  605. TraceMsg(DM_INIT, "CDeskBarApp::Load(bag) called");
  606. hres = SUPERCLASS::Load(pPropBag, pErrorLog);
  607. // after loading this, if we find that we're supposed to be browser docked,
  608. // make our bandsite always have a gripper
  609. if (_eMode == WBM_BFLOATING)
  610. {
  611. BANDSITEINFO bsinfo;
  612. bsinfo.dwMask = BSIM_STYLE;
  613. bsinfo.dwStyle = BSIS_ALWAYSGRIPPER;
  614. _pbs->SetBandSiteInfo(&bsinfo);
  615. }
  616. return hres;
  617. }
  618. IBandSite * _GetBandSite(IDeskBar * pdb)
  619. {
  620. IBandSite* pbs = NULL;
  621. if (pdb) {
  622. IUnknown* punkClient;
  623. pdb->GetClient(&punkClient);
  624. if (punkClient) {
  625. punkClient->QueryInterface(IID_IBandSite, (LPVOID*)&pbs);
  626. punkClient->Release();
  627. }
  628. }
  629. return pbs;
  630. }
  631. IBandSite* DeskBarApp_GetBandSiteOnEdge(UINT uEdge)
  632. {
  633. // APPCOMPAT: (dli) if no HMONITOR is passed in, use the primary monitor
  634. // should make sure that there is always a valid HMONITOR passed in
  635. HMONITOR hMon = GetPrimaryMonitor();
  636. // --------------------------------------------------------------
  637. LPDESKBARSPERMONITOR pdbpm = GetDBPMWithMonitor(hMon, FALSE);
  638. if (pdbpm) {
  639. ASSERT(pdbpm->hMon);
  640. ASSERT(pdbpm->hMon == hMon);
  641. return _GetBandSite(pdbpm->Deskbars[uEdge]);
  642. }
  643. return NULL;
  644. }
  645. IBandSite* DeskBarApp_GetBandSiteAtPoint(LPPOINT ppt)
  646. {
  647. HWND hwnd = WindowFromPoint(*ppt);
  648. HMONITOR hMon = MonitorFromPoint(*ppt, MONITOR_DEFAULTTONULL);
  649. if (hwnd && hMon) {
  650. LPDESKBARSPERMONITOR pdbpm = GetDBPMWithMonitor(hMon, FALSE);
  651. if (pdbpm) {
  652. ASSERT(pdbpm->hMon);
  653. ASSERT(pdbpm->hMon == hMon);
  654. int i;
  655. for (i = 0; i < 4; i++) {
  656. if (pdbpm->Deskbars[i]) {
  657. HWND hwndDeskbar;
  658. pdbpm->Deskbars[i]->GetWindow(&hwndDeskbar);
  659. if (hwndDeskbar == hwnd) {
  660. return _GetBandSite(pdbpm->Deskbars[i]);
  661. }
  662. }
  663. }
  664. }
  665. }
  666. return NULL;
  667. }
  668. // }