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.

549 lines
14 KiB

  1. /*****************************************************************************\
  2. FILE: MBDeskBar.cpp
  3. DESCRIPTION:
  4. This is the Desktop Toolbar code used to host the "MailBox" feature UI.
  5. BryanSt 2/26/2000
  6. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  7. \*****************************************************************************/
  8. #include "priv.h"
  9. #include <atlbase.h> // USES_CONVERSION
  10. #include "util.h"
  11. #include "objctors.h"
  12. #include <comdef.h>
  13. #include "MailBox.h"
  14. #ifdef FEATURE_MAILBOX
  15. /**************************************************************************
  16. CLASS: CMailBoxDeskBand
  17. **************************************************************************/
  18. class CMailBoxDeskBand : public IDeskBand,
  19. public IInputObject,
  20. public IObjectWithSite,
  21. public IPersistStream,
  22. public IContextMenu
  23. {
  24. public:
  25. //IUnknown methods
  26. STDMETHODIMP QueryInterface(REFIID, LPVOID*);
  27. STDMETHODIMP_(DWORD) AddRef();
  28. STDMETHODIMP_(DWORD) Release();
  29. //IOleWindow methods
  30. STDMETHOD (GetWindow)(HWND*);
  31. STDMETHOD (ContextSensitiveHelp)(BOOL);
  32. //IDockingWindow methods
  33. STDMETHOD (ShowDW)(BOOL fShow);
  34. STDMETHOD (CloseDW)(DWORD dwReserved);
  35. STDMETHOD (ResizeBorderDW)(LPCRECT prcBorder, IUnknown* punkToolbarSite, BOOL fReserved);
  36. //IDeskBand methods
  37. STDMETHOD (GetBandInfo)(DWORD, DWORD, DESKBANDINFO*);
  38. //IInputObject methods
  39. STDMETHOD (UIActivateIO)(BOOL, LPMSG);
  40. STDMETHOD (HasFocusIO)(void);
  41. STDMETHOD (TranslateAcceleratorIO)(LPMSG);
  42. //IObjectWithSite methods
  43. STDMETHOD (SetSite)(IUnknown*);
  44. STDMETHOD (GetSite)(REFIID, LPVOID*);
  45. //IPersistStream methods
  46. STDMETHOD (GetClassID)(LPCLSID);
  47. STDMETHOD (IsDirty)(void);
  48. STDMETHOD (Load)(LPSTREAM);
  49. STDMETHOD (Save)(LPSTREAM, BOOL);
  50. STDMETHOD (GetSizeMax)(ULARGE_INTEGER*);
  51. //IContextMenu methods
  52. STDMETHOD (QueryContextMenu)(HMENU, UINT, UINT, UINT, UINT);
  53. STDMETHOD (InvokeCommand)(LPCMINVOKECOMMANDINFO);
  54. STDMETHOD (GetCommandString)(UINT_PTR, UINT, LPUINT, LPSTR, UINT);
  55. private:
  56. CMailBoxDeskBand();
  57. ~CMailBoxDeskBand();
  58. // Private Member Variables
  59. DWORD m_cRef;
  60. HWND m_hwndParent; // The hwnd of the DeskBar (the host with all the bars)
  61. HWND m_hwndMailBox; // The child hwnd that displayed the Label, Editbox, and "Go" button.
  62. IInputObjectSite *m_pSite;
  63. CMailBoxUI * m_pMailBoxUI;
  64. // Private Member Functions
  65. HRESULT _CreateWindow(void);
  66. static LRESULT CALLBACK MailBoxDeskBarWndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
  67. friend HRESULT CMailBoxDeskBand_CreateInstance(IN IUnknown * punkOuter, REFIID riid, void ** ppvObj);
  68. };
  69. //===========================
  70. // *** Class Internals & Helpers ***
  71. //===========================
  72. HRESULT CMailBoxDeskBand::_CreateWindow(void)
  73. {
  74. HRESULT hr = S_OK;
  75. //If the window doesn't exist yet, create it now.
  76. if (!m_hwndMailBox)
  77. {
  78. ATOMICRELEASE(m_pMailBoxUI);
  79. m_pMailBoxUI = new CMailBoxUI();
  80. if (m_pMailBoxUI)
  81. {
  82. hr = m_pMailBoxUI->CreateWindowMB(m_hwndParent, &m_hwndMailBox);
  83. }
  84. else
  85. {
  86. hr = E_OUTOFMEMORY;
  87. }
  88. }
  89. return hr;
  90. }
  91. //===========================
  92. // *** IOleWindow Interface ***
  93. //===========================
  94. STDMETHODIMP CMailBoxDeskBand::GetWindow(HWND *phWnd)
  95. {
  96. *phWnd = m_hwndMailBox;
  97. return S_OK;
  98. }
  99. STDMETHODIMP CMailBoxDeskBand::ContextSensitiveHelp(BOOL fEnterMode)
  100. {
  101. // TODO: Add help here.
  102. return S_OK;
  103. }
  104. //===========================
  105. // *** IDockingWindow Interface ***
  106. //===========================
  107. STDMETHODIMP CMailBoxDeskBand::ShowDW(BOOL fShow)
  108. {
  109. TraceMsg(0, "::ShowDW %x", fShow);
  110. if (m_hwndMailBox)
  111. {
  112. if (fShow)
  113. ShowWindow(m_hwndMailBox, SW_SHOW);
  114. else
  115. ShowWindow(m_hwndMailBox, SW_HIDE);
  116. return S_OK;
  117. }
  118. return E_FAIL;
  119. }
  120. STDMETHODIMP CMailBoxDeskBand::CloseDW(DWORD dwReserved)
  121. {
  122. TraceMsg(0, "::CloseDW", 0);
  123. ShowDW(FALSE);
  124. if (m_pMailBoxUI)
  125. {
  126. m_pMailBoxUI->CloseWindowMB();
  127. ATOMICRELEASE(m_pMailBoxUI);
  128. }
  129. return S_OK;
  130. }
  131. STDMETHODIMP CMailBoxDeskBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown* punkSite, BOOL fReserved)
  132. {
  133. // This method is never called for Band Objects.
  134. return E_NOTIMPL;
  135. }
  136. //===========================
  137. // *** IInputObject Interface ***
  138. //===========================
  139. STDMETHODIMP CMailBoxDeskBand::UIActivateIO(BOOL fActivate, LPMSG pMsg)
  140. {
  141. TraceMsg(0, "::UIActivateIO %x", fActivate);
  142. if (fActivate)
  143. SetFocus(m_hwndMailBox);
  144. return S_OK;
  145. }
  146. STDMETHODIMP CMailBoxDeskBand::HasFocusIO(void)
  147. {
  148. // If this window or one of its decendants has the focus, return S_OK. Return
  149. // S_FALSE if we don't have the focus.
  150. TraceMsg(0, "::HasFocusIO", NULL);
  151. HWND hwnd = GetFocus();
  152. if (hwnd && ((hwnd == m_hwndMailBox) ||
  153. (GetParent(hwnd) == m_hwndMailBox) ||
  154. (GetParent(GetParent(hwnd)) == m_hwndMailBox)))
  155. {
  156. return S_OK;
  157. }
  158. return S_FALSE;
  159. }
  160. STDMETHODIMP CMailBoxDeskBand::TranslateAcceleratorIO(LPMSG pMsg)
  161. {
  162. // If the accelerator is translated, return S_OK or S_FALSE otherwise.
  163. return S_FALSE;
  164. }
  165. //===========================
  166. // *** IObjectWithSite Interface ***
  167. //===========================
  168. STDMETHODIMP CMailBoxDeskBand::SetSite(IUnknown* punkSite)
  169. {
  170. HRESULT hr = S_OK;
  171. //If a site is being held, release it.
  172. ATOMICRELEASE(m_pSite);
  173. //If punkSite is not NULL, a new site is being set.
  174. if (punkSite)
  175. {
  176. // Get the parent window.
  177. m_hwndParent = NULL;
  178. IUnknown_GetWindow(punkSite, &m_hwndParent);
  179. if (m_hwndParent)
  180. {
  181. hr = _CreateWindow();
  182. if (SUCCEEDED(hr))
  183. {
  184. // Get and keep the IInputObjectSite pointer.
  185. hr = punkSite->QueryInterface(IID_PPV_ARG(IInputObjectSite, &m_pSite));
  186. }
  187. }
  188. else
  189. {
  190. hr = E_FAIL;
  191. }
  192. }
  193. return hr;
  194. }
  195. STDMETHODIMP CMailBoxDeskBand::GetSite(REFIID riid, LPVOID *ppvReturn)
  196. {
  197. *ppvReturn = NULL;
  198. if (m_pSite)
  199. return m_pSite->QueryInterface(riid, ppvReturn);
  200. return E_FAIL;
  201. }
  202. //===========================
  203. // *** IDeskBand Interface ***
  204. //===========================
  205. STDMETHODIMP CMailBoxDeskBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
  206. {
  207. if (pdbi)
  208. {
  209. if (pdbi->dwMask & DBIM_MINSIZE)
  210. {
  211. pdbi->ptMinSize.x = 0;
  212. pdbi->ptMinSize.y = 0;
  213. }
  214. if (pdbi->dwMask & DBIM_MODEFLAGS)
  215. {
  216. pdbi->dwModeFlags = DBIMF_FIXEDBMP;
  217. }
  218. bool fVertical = (((dwViewMode & (DBIF_VIEWMODE_VERTICAL | DBIF_VIEWMODE_FLOATING)) != 0) ? true : false);
  219. if (true == fVertical)
  220. {
  221. if (pdbi->dwMask & DBIM_MODEFLAGS)
  222. {
  223. pdbi->dwModeFlags |= DBIMF_VARIABLEHEIGHT;
  224. }
  225. }
  226. else
  227. {
  228. if (m_pMailBoxUI)
  229. {
  230. HWND hwndEdit;
  231. if (SUCCEEDED(m_pMailBoxUI->GetEditboxWindow(&hwndEdit)))
  232. {
  233. RECT rcEditbox;
  234. // TODO: We need to find the real height of the editbox with
  235. // one row of text plus 2 pixels on top and bottom.
  236. GetWindowRect(hwndEdit, &rcEditbox);
  237. pdbi->ptMinSize.y = RECTHEIGHT(rcEditbox);
  238. // TODO: Find out how to calc the appropriate size of the editbox.
  239. pdbi->ptMinSize.y = 0x1A;
  240. }
  241. }
  242. }
  243. if (pdbi->dwMask & DBIM_MAXSIZE)
  244. {
  245. if (true == fVertical)
  246. {
  247. pdbi->ptMaxSize.y = -1;
  248. }
  249. }
  250. if (pdbi->dwMask & DBIM_INTEGRAL)
  251. {
  252. if (true == fVertical)
  253. {
  254. pdbi->ptIntegral.y = 1;
  255. }
  256. }
  257. if (pdbi->dwMask & DBIM_TITLE)
  258. {
  259. LoadStringW(HINST_THISDLL, IDS_MAILBOX_DESKBAR_LABEL, pdbi->wszTitle, ARRAYSIZE(pdbi->wszTitle));
  260. }
  261. if (pdbi->dwMask & DBIM_BKCOLOR)
  262. {
  263. //Use the default background color by removing this flag.
  264. pdbi->dwMask &= ~DBIM_BKCOLOR;
  265. }
  266. return S_OK;
  267. }
  268. return E_INVALIDARG;
  269. }
  270. //===========================
  271. // *** IPersistStream Interface ***
  272. //===========================
  273. #define MAILBOX_PERSIST_SIGNATURE 0xF0AB8915 // Random signature.
  274. #define MAILBOX_PERSIST_VERSION 0x00000000 // This is version 0.
  275. typedef struct {
  276. DWORD cbSize;
  277. DWORD dwSig; // from MAILBOX_PERSIST_SIGNATURE
  278. DWORD dwVer; // from MAILBOX_PERSIST_VERSION
  279. } MAILBOX_PERSISTHEADERSTRUCT;
  280. STDMETHODIMP CMailBoxDeskBand::GetClassID(LPCLSID pClassID)
  281. {
  282. *pClassID = CLSID_MailBoxDeskBar;
  283. return S_OK;
  284. }
  285. STDMETHODIMP CMailBoxDeskBand::IsDirty(void)
  286. {
  287. // We currently never get dirty because we don't have state.
  288. return S_FALSE;
  289. }
  290. STDMETHODIMP CMailBoxDeskBand::Load(IStream* pStream)
  291. {
  292. DWORD cbRead;
  293. MAILBOX_PERSISTHEADERSTRUCT mailboxPersistHeader;
  294. HRESULT hr = pStream->Read(&mailboxPersistHeader, sizeof(mailboxPersistHeader), &cbRead);
  295. if (SUCCEEDED(hr) &&
  296. (sizeof(mailboxPersistHeader) == cbRead) &&
  297. (MAILBOX_PERSIST_SIGNATURE == mailboxPersistHeader.dwSig) &&
  298. (mailboxPersistHeader.cbSize > 0))
  299. {
  300. void * pPersistHeader = (void *) LocalAlloc(NONZEROLPTR, mailboxPersistHeader.cbSize);
  301. if (pPersistHeader)
  302. {
  303. // We read it simply to support future versions.
  304. hr = pStream->Read(pPersistHeader, mailboxPersistHeader.cbSize, NULL);
  305. LocalFree(pPersistHeader);
  306. }
  307. else
  308. {
  309. hr = E_OUTOFMEMORY;
  310. }
  311. }
  312. return hr;
  313. }
  314. STDMETHODIMP CMailBoxDeskBand::Save(IStream* pStream, BOOL fClearDirty)
  315. {
  316. MAILBOX_PERSISTHEADERSTRUCT mailboxPersistHeader = {0, MAILBOX_PERSIST_SIGNATURE, MAILBOX_PERSIST_VERSION};
  317. // if (fClearDirty)
  318. // m_bDirty = FALSE;
  319. return pStream->Write(&mailboxPersistHeader, sizeof(mailboxPersistHeader), NULL);
  320. }
  321. STDMETHODIMP CMailBoxDeskBand::GetSizeMax(ULARGE_INTEGER *pul)
  322. {
  323. HRESULT hr = E_INVALIDARG;
  324. if (pul)
  325. {
  326. pul->QuadPart = sizeof(MAILBOX_PERSISTHEADERSTRUCT);
  327. hr = S_OK;
  328. }
  329. return hr;
  330. }
  331. //===========================
  332. // *** IContextMenu Interface ***
  333. //===========================
  334. STDMETHODIMP CMailBoxDeskBand::QueryContextMenu( HMENU hMenu,
  335. UINT indexMenu,
  336. UINT idCmdFirst,
  337. UINT idCmdLast,
  338. UINT uFlags)
  339. {
  340. if (CMF_DEFAULTONLY & uFlags)
  341. return S_OK;
  342. // We don't currently add any context menu items.
  343. return S_OK;
  344. }
  345. STDMETHODIMP CMailBoxDeskBand::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
  346. {
  347. return E_INVALIDARG;
  348. }
  349. STDMETHODIMP CMailBoxDeskBand::GetCommandString(UINT_PTR idCommand, UINT uFlags, LPUINT lpReserved, LPSTR lpszName, UINT uMaxNameLen)
  350. {
  351. HRESULT hr = E_INVALIDARG;
  352. return hr;
  353. }
  354. //===========================
  355. // *** IUnknown Interface ***
  356. //===========================
  357. STDMETHODIMP CMailBoxDeskBand::QueryInterface(REFIID riid, LPVOID *ppvObj)
  358. {
  359. static const QITAB qit[] = {
  360. QITABENT(CMailBoxDeskBand, IOleWindow),
  361. QITABENT(CMailBoxDeskBand, IDockingWindow),
  362. QITABENT(CMailBoxDeskBand, IInputObject),
  363. QITABENT(CMailBoxDeskBand, IObjectWithSite),
  364. QITABENT(CMailBoxDeskBand, IDeskBand),
  365. QITABENT(CMailBoxDeskBand, IPersist),
  366. QITABENT(CMailBoxDeskBand, IPersistStream),
  367. QITABENT(CMailBoxDeskBand, IContextMenu),
  368. { 0 },
  369. };
  370. return QISearch(this, qit, riid, ppvObj);
  371. }
  372. STDMETHODIMP_(DWORD) CMailBoxDeskBand::AddRef()
  373. {
  374. return ++m_cRef;
  375. }
  376. STDMETHODIMP_(DWORD) CMailBoxDeskBand::Release()
  377. {
  378. if (--m_cRef == 0)
  379. {
  380. delete this;
  381. return 0;
  382. }
  383. return m_cRef;
  384. }
  385. //===========================
  386. // *** Class Methods ***
  387. //===========================
  388. CMailBoxDeskBand::CMailBoxDeskBand()
  389. {
  390. DllAddRef();
  391. m_pSite = NULL;
  392. m_pMailBoxUI = NULL;
  393. m_hwndMailBox = NULL;
  394. m_hwndParent = NULL;
  395. m_cRef = 1;
  396. }
  397. CMailBoxDeskBand::~CMailBoxDeskBand()
  398. {
  399. ATOMICRELEASE(m_pSite);
  400. ATOMICRELEASE(m_pMailBoxUI);
  401. DllRelease();
  402. }
  403. HRESULT CMailBoxDeskBand_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT void ** ppvObj)
  404. {
  405. HRESULT hr = CLASS_E_NOAGGREGATION;
  406. if (ppvObj)
  407. {
  408. *ppvObj = NULL;
  409. if (NULL == punkOuter)
  410. {
  411. CMailBoxDeskBand * pmf = new CMailBoxDeskBand();
  412. if (pmf)
  413. {
  414. hr = pmf->QueryInterface(riid, ppvObj);
  415. pmf->Release();
  416. }
  417. else
  418. {
  419. hr = E_OUTOFMEMORY;
  420. }
  421. }
  422. else
  423. {
  424. hr = E_INVALIDARG;
  425. }
  426. }
  427. return hr;
  428. }
  429. #endif // FEATURE_MAILBOX