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.

924 lines
22 KiB

  1. /**************************************************************************
  2. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. ANY KIND, EITHER EXPRESSED OR TFPLIED, INCLUDING BUT NOT LIMITED TO
  4. THE TFPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. PARTICULAR PURPOSE.
  6. Copyright 1997 Microsoft Corporation. All Rights Reserved.
  7. **************************************************************************/
  8. /**************************************************************************
  9. File: DeskBand.cpp
  10. Description: Implements CDeskBand
  11. **************************************************************************/
  12. /**************************************************************************
  13. include statements
  14. **************************************************************************/
  15. #include "private.h"
  16. #include "DeskBand.h"
  17. #include "tipbar.h"
  18. #include "Guid.h"
  19. #include <shlapip.h>
  20. extern CTipbarWnd *g_pTipbarWnd;
  21. const IID IID_IDeskBandEx = {
  22. 0x5dd6b79a,
  23. 0x3ab7,
  24. 0x49c0,
  25. {0xab,0x82,0x6b,0x2d,0xa7,0xd7,0x8d,0x75}
  26. };
  27. /**************************************************************************
  28. CDeskBand::CDeskBand()
  29. **************************************************************************/
  30. CDeskBand::CDeskBand()
  31. {
  32. m_pSite = NULL;
  33. m_hwndParent = NULL;
  34. m_bFocus = FALSE;
  35. m_dwViewMode = 0;
  36. m_dwBandID = -1;
  37. m_ObjRefCount = 1;
  38. g_DllRefCount++;
  39. }
  40. /**************************************************************************
  41. CDeskBand::~CDeskBand()
  42. **************************************************************************/
  43. CDeskBand::~CDeskBand()
  44. {
  45. // this should have been freed in a call to SetSite(NULL),
  46. // but just to be safe
  47. if(m_pSite)
  48. {
  49. m_pSite->Release();
  50. m_pSite = NULL;
  51. }
  52. g_DllRefCount--;
  53. }
  54. ///////////////////////////////////////////////////////////////////////////
  55. //
  56. // IUnknown Implementation
  57. //
  58. /**************************************************************************
  59. CDeskBand::QueryInterface
  60. **************************************************************************/
  61. STDMETHODIMP CDeskBand::QueryInterface(REFIID riid, LPVOID *ppReturn)
  62. {
  63. *ppReturn = NULL;
  64. //IUnknown
  65. if(IsEqualIID(riid, IID_IUnknown))
  66. {
  67. *ppReturn = this;
  68. }
  69. //IOleWindow
  70. else if(IsEqualIID(riid, IID_IOleWindow))
  71. {
  72. *ppReturn = (IOleWindow*)this;
  73. }
  74. //IDockingWindow
  75. else if(IsEqualIID(riid, IID_IDockingWindow))
  76. {
  77. *ppReturn = (IDockingWindow*)this;
  78. }
  79. //IInputObject
  80. else if(IsEqualIID(riid, IID_IInputObject))
  81. {
  82. *ppReturn = (IInputObject*)this;
  83. }
  84. //IObjectWithSite
  85. else if(IsEqualIID(riid, IID_IObjectWithSite))
  86. {
  87. *ppReturn = (IObjectWithSite*)this;
  88. }
  89. //IDeskBand
  90. else if(IsEqualIID(riid, IID_IDeskBand))
  91. {
  92. *ppReturn = (IDeskBand*)this;
  93. }
  94. //IDeskBandEx
  95. else if(IsEqualIID(riid, IID_IDeskBandEx))
  96. {
  97. *ppReturn = (IDeskBandEx*)this;
  98. }
  99. //IPersist
  100. else if(IsEqualIID(riid, IID_IPersist))
  101. {
  102. *ppReturn = (IPersist*)this;
  103. }
  104. //IPersistStream
  105. else if(IsEqualIID(riid, IID_IPersistStream))
  106. {
  107. *ppReturn = (IPersistStream*)this;
  108. }
  109. //IContextMenu
  110. else if(IsEqualIID(riid, IID_IContextMenu))
  111. {
  112. *ppReturn = (IContextMenu*)this;
  113. }
  114. if(*ppReturn)
  115. {
  116. (*(LPUNKNOWN*)ppReturn)->AddRef();
  117. return S_OK;
  118. }
  119. return E_FAIL;
  120. }
  121. /**************************************************************************
  122. CDeskBand::AddRef
  123. **************************************************************************/
  124. STDMETHODIMP_(DWORD) CDeskBand::AddRef()
  125. {
  126. return ++m_ObjRefCount;
  127. }
  128. /**************************************************************************
  129. CDeskBand::Release
  130. **************************************************************************/
  131. STDMETHODIMP_(DWORD) CDeskBand::Release()
  132. {
  133. if(--m_ObjRefCount == 0)
  134. {
  135. delete this;
  136. return 0;
  137. }
  138. return m_ObjRefCount;
  139. }
  140. ///////////////////////////////////////////////////////////////////////////
  141. //
  142. // IOleWindow Implementation
  143. //
  144. /**************************************************************************
  145. CDeskBand::GetWindow()
  146. **************************************************************************/
  147. STDMETHODIMP CDeskBand::GetWindow(HWND *phWnd)
  148. {
  149. if (!g_pTipbarWnd)
  150. *phWnd = NULL;
  151. else
  152. *phWnd = g_pTipbarWnd->GetWnd();
  153. return S_OK;
  154. }
  155. /**************************************************************************
  156. CDeskBand::ContextSensitiveHelp()
  157. **************************************************************************/
  158. STDMETHODIMP CDeskBand::ContextSensitiveHelp(BOOL fEnterMode)
  159. {
  160. return E_NOTIMPL;
  161. }
  162. ///////////////////////////////////////////////////////////////////////////
  163. //
  164. // IDockingWindow Implementation
  165. //
  166. /**************************************************************************
  167. CDeskBand::ShowDW()
  168. **************************************************************************/
  169. STDMETHODIMP CDeskBand::ShowDW(BOOL fShow)
  170. {
  171. if (!g_pTipbarWnd)
  172. return S_OK;
  173. if (g_pTipbarWnd->GetWnd())
  174. {
  175. g_pTipbarWnd->Show(fShow);
  176. }
  177. return S_OK;
  178. }
  179. /**************************************************************************
  180. CDeskBand::CloseDW()
  181. **************************************************************************/
  182. STDMETHODIMP CDeskBand::CloseDW(DWORD dwReserved)
  183. {
  184. if (m_fInCloseDW)
  185. return S_OK;
  186. AddRef();
  187. m_fInCloseDW = TRUE;
  188. ShowDW(FALSE);
  189. if(g_pTipbarWnd && IsWindow(g_pTipbarWnd->GetWnd()))
  190. {
  191. ClosePopupTipbar();
  192. }
  193. m_fInCloseDW = FALSE;
  194. Release();
  195. return S_OK;
  196. }
  197. /**************************************************************************
  198. CDeskBand::ResizeBorderDW()
  199. **************************************************************************/
  200. STDMETHODIMP CDeskBand::ResizeBorderDW( LPCRECT prcBorder,
  201. IUnknown* punkSite,
  202. BOOL fReserved)
  203. {
  204. // This method is never called for Band Objects.
  205. return E_NOTIMPL;
  206. }
  207. ///////////////////////////////////////////////////////////////////////////
  208. //
  209. // IInputObject Implementation
  210. //
  211. /**************************************************************************
  212. CDeskBand::UIActivateIO()
  213. **************************************************************************/
  214. STDMETHODIMP CDeskBand::UIActivateIO(BOOL fActivate, LPMSG pMsg)
  215. {
  216. #if 1
  217. //
  218. // we don't have keyboard access to the language bar, yet.
  219. // however the accessibility requires it. when it is done, this can be
  220. // implemented.
  221. //
  222. return E_NOTIMPL;
  223. #else
  224. if(g_pTipbarWnd && fActivate)
  225. SetFocus(g_pTipbarWnd->GetWnd());
  226. return S_OK;
  227. #endif
  228. }
  229. /**************************************************************************
  230. CDeskBand::HasFocusIO()
  231. If this window or one of its decendants has the focus, return S_OK. Return
  232. S_FALSE if we don't have the focus.
  233. **************************************************************************/
  234. STDMETHODIMP CDeskBand::HasFocusIO(void)
  235. {
  236. if(m_bFocus)
  237. return S_OK;
  238. return S_FALSE;
  239. }
  240. /**************************************************************************
  241. CDeskBand::TranslateAcceleratorIO()
  242. If the accelerator is translated, return S_OK or S_FALSE otherwise.
  243. **************************************************************************/
  244. STDMETHODIMP CDeskBand::TranslateAcceleratorIO(LPMSG pMsg)
  245. {
  246. return S_FALSE;
  247. }
  248. ///////////////////////////////////////////////////////////////////////////
  249. //
  250. // IObjectWithSite implementations
  251. //
  252. /**************************************************************************
  253. CDeskBand::SetSite()
  254. **************************************************************************/
  255. STDMETHODIMP CDeskBand::SetSite(IUnknown* punkSite)
  256. {
  257. //If a site is being held, release it.
  258. if(m_pSite)
  259. {
  260. m_pSite->Release();
  261. m_pSite = NULL;
  262. }
  263. // If punkSite is not NULL, a new site is being set.
  264. if(punkSite)
  265. {
  266. // Get the parent window.
  267. IOleWindow *pOleWindow;
  268. m_hwndParent = NULL;
  269. if(SUCCEEDED(punkSite->QueryInterface(IID_IOleWindow,
  270. (LPVOID*)&pOleWindow)))
  271. {
  272. pOleWindow->GetWindow(&m_hwndParent);
  273. pOleWindow->Release();
  274. }
  275. if(!m_hwndParent)
  276. return E_FAIL;
  277. if(!RegisterAndCreateWindow())
  278. return E_FAIL;
  279. // Get and keep the IInputObjectSite pointer.
  280. if(SUCCEEDED(punkSite->QueryInterface(IID_IInputObjectSite,
  281. (LPVOID*)&m_pSite)))
  282. {
  283. return S_OK;
  284. }
  285. return E_FAIL;
  286. }
  287. return S_OK;
  288. }
  289. /**************************************************************************
  290. CDeskBand::GetSite()
  291. **************************************************************************/
  292. STDMETHODIMP CDeskBand::GetSite(REFIID riid, LPVOID *ppvReturn)
  293. {
  294. *ppvReturn = NULL;
  295. if(m_pSite)
  296. return m_pSite->QueryInterface(riid, ppvReturn);
  297. return E_FAIL;
  298. }
  299. ///////////////////////////////////////////////////////////////////////////
  300. //
  301. // IDeskBand implementation
  302. //
  303. /**************************************************************************
  304. CDeskBand::GetBandInfo()
  305. **************************************************************************/
  306. STDMETHODIMP CDeskBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
  307. {
  308. if(pdbi)
  309. {
  310. BOOL bVertical = FALSE;
  311. m_dwBandID = dwBandID;
  312. m_dwViewMode = dwViewMode;
  313. if (DBIF_VIEWMODE_VERTICAL & dwViewMode)
  314. {
  315. bVertical = TRUE;
  316. }
  317. UINT cxSmIcon;
  318. UINT cySmIcon;
  319. UINT cxSize;
  320. UINT cySize;
  321. cxSmIcon = GetSystemMetrics(SM_CXSMICON);
  322. cySmIcon = GetSystemMetrics(SM_CYSMICON);
  323. cxSize = cxSmIcon;
  324. if (g_pTipbarWnd)
  325. {
  326. g_pTipbarWnd->InitMetrics();
  327. cySize = g_pTipbarWnd->GetTipbarHeight();
  328. }
  329. else
  330. cySize = cySmIcon + cySmIcon / 3;
  331. if(pdbi->dwMask & DBIM_MINSIZE)
  332. {
  333. if(DBIF_VIEWMODE_FLOATING & dwViewMode)
  334. {
  335. pdbi->ptMinSize.x = 200;
  336. pdbi->ptMinSize.y = 400;
  337. }
  338. else
  339. {
  340. pdbi->ptMinSize.x = cxSize;
  341. pdbi->ptMinSize.y = cySize + 2;
  342. }
  343. }
  344. if(pdbi->dwMask & DBIM_MAXSIZE)
  345. {
  346. pdbi->ptMaxSize.x = -1;
  347. pdbi->ptMaxSize.y = -1;
  348. }
  349. if(pdbi->dwMask & DBIM_INTEGRAL)
  350. {
  351. pdbi->ptIntegral.x = cxSize;
  352. pdbi->ptIntegral.y = cySize;
  353. }
  354. if(pdbi->dwMask & DBIM_ACTUAL)
  355. {
  356. pdbi->ptActual.x = cxSize;
  357. pdbi->ptActual.y = cySize + 2;
  358. }
  359. if(pdbi->dwMask & DBIM_TITLE)
  360. {
  361. pdbi->dwMask &= ~DBIM_TITLE;
  362. StringCchCopyW(pdbi->wszTitle,
  363. ARRAYSIZE(pdbi->wszTitle),
  364. CRStr(IDS_LANGBAR));
  365. }
  366. if(pdbi->dwMask & DBIM_MODEFLAGS)
  367. {
  368. pdbi->dwModeFlags = DBIMF_NORMAL;
  369. pdbi->dwModeFlags |= DBIMF_VARIABLEHEIGHT;
  370. }
  371. if(pdbi->dwMask & DBIM_BKCOLOR)
  372. {
  373. //Use the default background color by removing this flag.
  374. pdbi->dwMask &= ~DBIM_BKCOLOR;
  375. }
  376. //
  377. // Don't pulls language band into desktop window.
  378. //
  379. //pdbi->dwModeFlags |= DBIMF_UNDELETEABLE;
  380. if (g_pTipbarWnd)
  381. {
  382. if (!bVertical)
  383. {
  384. g_pTipbarWnd->SetVertical(FALSE);
  385. }
  386. else
  387. {
  388. g_pTipbarWnd->SetVertical(TRUE);
  389. }
  390. }
  391. return S_OK;
  392. }
  393. return E_INVALIDARG;
  394. }
  395. ///////////////////////////////////////////////////////////////////////////
  396. //
  397. // IDeskBandEx implementation
  398. //
  399. /**************************************************************************
  400. CDeskBand::MoveBand()
  401. **************************************************************************/
  402. STDMETHODIMP CDeskBand::MoveBand(void)
  403. {
  404. if (g_pTipbarWnd)
  405. {
  406. g_pTipbarWnd->GetLangBarMgr()->ShowFloating(TF_SFT_SHOWNORMAL);
  407. //
  408. // Don't need ask remove language deskband since we do it by calling
  409. // ShowFloating().
  410. //
  411. return S_FALSE;
  412. }
  413. else
  414. {
  415. //
  416. // Let's Explorer remove language deskband.
  417. //
  418. return S_OK;
  419. }
  420. }
  421. ///////////////////////////////////////////////////////////////////////////
  422. //
  423. // IPersistStream implementations
  424. //
  425. // This is only supported to allow the desk band to be dropped on the
  426. // desktop and to prevent multiple instances of the desk band from showing
  427. // up in the context menu. This desk band doesn't actually persist any data.
  428. //
  429. /**************************************************************************
  430. CDeskBand::GetClassID()
  431. **************************************************************************/
  432. STDMETHODIMP CDeskBand::GetClassID(LPCLSID pClassID)
  433. {
  434. *pClassID = CLSID_MSUTBDeskBand;
  435. return S_OK;
  436. }
  437. /**************************************************************************
  438. CDeskBand::IsDirty()
  439. **************************************************************************/
  440. STDMETHODIMP CDeskBand::IsDirty(void)
  441. {
  442. return S_FALSE;
  443. }
  444. /**************************************************************************
  445. CDeskBand::Load()
  446. **************************************************************************/
  447. STDMETHODIMP CDeskBand::Load(LPSTREAM pStream)
  448. {
  449. return S_OK;
  450. }
  451. /**************************************************************************
  452. CDeskBand::Save()
  453. **************************************************************************/
  454. STDMETHODIMP CDeskBand::Save(LPSTREAM pStream, BOOL fClearDirty)
  455. {
  456. return S_OK;
  457. }
  458. /**************************************************************************
  459. CDeskBand::GetSizeMax()
  460. **************************************************************************/
  461. STDMETHODIMP CDeskBand::GetSizeMax(ULARGE_INTEGER *pul)
  462. {
  463. return E_NOTIMPL;
  464. }
  465. ///////////////////////////////////////////////////////////////////////////
  466. //
  467. // IContextMenu Implementation
  468. //
  469. /**************************************************************************
  470. CDeskBand::QueryContextMenu()
  471. **************************************************************************/
  472. STDMETHODIMP CDeskBand::QueryContextMenu( HMENU hMenu,
  473. UINT indexMenu,
  474. UINT idCmdFirst,
  475. UINT idCmdLast,
  476. UINT uFlags)
  477. {
  478. if(!(CMF_DEFAULTONLY & uFlags))
  479. {
  480. InsertMenu( hMenu,
  481. indexMenu,
  482. MF_STRING | MF_BYPOSITION,
  483. idCmdFirst + IDM_COMMAND,
  484. CRStr(IDS_RESTORE));
  485. return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_COMMAND + 1));
  486. }
  487. return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
  488. }
  489. /**************************************************************************
  490. CDeskBand::InvokeCommand()
  491. **************************************************************************/
  492. STDMETHODIMP CDeskBand::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
  493. {
  494. switch (LOWORD(lpcmi->lpVerb))
  495. {
  496. case IDM_COMMAND:
  497. //
  498. // Load floating language bar and close language band.
  499. //
  500. if (g_pTipbarWnd)
  501. {
  502. g_pTipbarWnd->GetLangBarMgr()->ShowFloating(TF_SFT_SHOWNORMAL);
  503. }
  504. //
  505. // Need to remove language band here
  506. //
  507. break;
  508. default:
  509. return E_INVALIDARG;
  510. }
  511. return NOERROR;
  512. }
  513. /**************************************************************************
  514. CDeskBand::GetCommandString()
  515. **************************************************************************/
  516. STDMETHODIMP CDeskBand::GetCommandString( UINT_PTR idCommand,
  517. UINT uFlags,
  518. LPUINT lpReserved,
  519. LPSTR lpszName,
  520. UINT uMaxNameLen)
  521. {
  522. HRESULT hr = E_INVALIDARG;
  523. switch(uFlags)
  524. {
  525. case GCS_HELPTEXT:
  526. switch(idCommand)
  527. {
  528. case IDM_COMMAND:
  529. StringCchCopy(lpszName, uMaxNameLen, "Desk Band command help text");
  530. hr = NOERROR;
  531. break;
  532. }
  533. break;
  534. case GCS_VERB:
  535. switch(idCommand)
  536. {
  537. case IDM_COMMAND:
  538. StringCchCopy(lpszName, uMaxNameLen, "command");
  539. hr = NOERROR;
  540. break;
  541. }
  542. break;
  543. case GCS_VALIDATE:
  544. hr = NOERROR;
  545. break;
  546. }
  547. return hr;
  548. }
  549. ///////////////////////////////////////////////////////////////////////////
  550. //
  551. // private method implementations
  552. //
  553. /**************************************************************************
  554. CDeskBand::FocusChange()
  555. **************************************************************************/
  556. void CDeskBand::FocusChange(BOOL bFocus)
  557. {
  558. m_bFocus = bFocus;
  559. //inform the input object site that the focus has changed
  560. if(m_pSite)
  561. {
  562. m_pSite->OnFocusChangeIS((IDockingWindow*)this, bFocus);
  563. }
  564. }
  565. /**************************************************************************
  566. CDeskBand::OnSetFocus(HWND hWnd)
  567. **************************************************************************/
  568. void CDeskBand::OnSetFocus(HWND hWndvoid)
  569. {
  570. FocusChange(TRUE);
  571. return;
  572. }
  573. /**************************************************************************
  574. CDeskBand::OnKillFocus(HWND hWnd)
  575. **************************************************************************/
  576. void CDeskBand::OnKillFocus(HWND hWndvoid)
  577. {
  578. FocusChange(FALSE);
  579. return;
  580. }
  581. /**************************************************************************
  582. CDeskBand::RegisterAndCreateWindow()
  583. **************************************************************************/
  584. BOOL CDeskBand::RegisterAndCreateWindow(void)
  585. {
  586. // If the window doesn't exist yet, create it now.
  587. if (!g_pTipbarWnd)
  588. {
  589. m_fTipbarCreating = TRUE;
  590. GetTipbarInternal(m_hwndParent, 0, this);
  591. m_fTipbarCreating = FALSE;
  592. }
  593. if (!g_pTipbarWnd)
  594. return FALSE;
  595. return (NULL != g_pTipbarWnd->GetWnd());
  596. }
  597. /**************************************************************************
  598. CDeskBand::ResizeRebar()
  599. **************************************************************************/
  600. BOOL CDeskBand::ResizeRebar(HWND hwnd, int nSize, BOOL fFit)
  601. {
  602. RECT rc0;
  603. RECT rc1;
  604. //
  605. // id is not initialized yet.
  606. //
  607. if (m_dwBandID == -1)
  608. {
  609. return FALSE;
  610. }
  611. GetWindowRect(hwnd, &rc0);
  612. GetWindowRect(m_hwndParent, &rc1);
  613. //
  614. // if the current size is nSize, we don't need to do anything.
  615. //
  616. int nCurSize;
  617. if (DBIF_VIEWMODE_VERTICAL & m_dwViewMode)
  618. nCurSize = rc0.bottom - rc0.top;
  619. else
  620. nCurSize = rc0.right - rc0.left;
  621. if (nCurSize == nSize)
  622. return TRUE;
  623. //
  624. // if the current size is bigger than nSize, we don't need to do anything.
  625. //
  626. if (!fFit && (nCurSize > nSize))
  627. return TRUE;
  628. //
  629. // start pos and end pos is offset of Rebar window.
  630. //
  631. LPARAM lStart;
  632. LPARAM lEnd;
  633. if (DBIF_VIEWMODE_VERTICAL & m_dwViewMode)
  634. {
  635. int nStart = rc0.top - rc1.top;
  636. int nEnd = nStart + nCurSize - nSize;
  637. lStart = MAKELPARAM(1, nStart);
  638. lEnd = MAKELPARAM(1, nEnd);
  639. }
  640. else
  641. {
  642. int nStart;
  643. int nEnd;
  644. if (g_dwWndStyle & UIWINDOW_LAYOUTRTL)
  645. {
  646. nStart = rc1.right - rc0.right;
  647. nEnd = nStart + nCurSize - nSize;
  648. }
  649. else
  650. {
  651. nStart = rc0.left - rc1.left;
  652. nEnd = nStart + nCurSize - nSize;
  653. }
  654. lStart = MAKELPARAM(nStart, 1);
  655. lEnd = MAKELPARAM(nEnd, 1);
  656. }
  657. //
  658. // #560192
  659. //
  660. // SendMessage() can yield another message in this thread and
  661. // this could be a request to remove langband. So this pointer
  662. // can be gone while the calls.
  663. // We want to finish the series of SendMessage() so keep the window
  664. // handle in the stack.
  665. //
  666. HWND hwndParent = m_hwndParent;
  667. int nIndex = (int)SendMessage(hwndParent, RB_IDTOINDEX, m_dwBandID, 0);
  668. if (nIndex == -1)
  669. return FALSE;
  670. //
  671. // move the deskband.
  672. //
  673. SendMessage(hwndParent, RB_BEGINDRAG, nIndex, lStart);
  674. SendMessage(hwndParent, RB_DRAGMOVE, 0, lEnd);
  675. SendMessage(hwndParent, RB_ENDDRAG, 0, 0);
  676. return TRUE;
  677. }
  678. /**************************************************************************
  679. CDeskBand::DeleteBand()
  680. **************************************************************************/
  681. void CDeskBand::DeleteBand()
  682. {
  683. HWND hwndParent = m_hwndParent;
  684. int nIndex = (int)SendMessage(hwndParent, RB_IDTOINDEX, m_dwBandID, 0);
  685. if (nIndex == -1)
  686. return;
  687. SendMessage(hwndParent, RB_DELETEBAND, nIndex, 0);
  688. }