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.

854 lines
22 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1993-1999 Microsoft Corporation. All Rights Reserved.
  3. //
  4. // MODULE: StatBar.cpp
  5. //
  6. // PURPOSE: Implements the CStatusBar class which manipulates the apps
  7. // status bar.
  8. //
  9. #include "pch.hxx"
  10. #include "statbar.h"
  11. #include "menures.h"
  12. #include <oerules.h>
  13. #include <demand.h>
  14. /////////////////////////////////////////////////////////////////////////////
  15. // The order here needs to match the DELIVERYNOTIFYTYPE enumeration from
  16. // mailnews\spooler\spoolapi.h. If there is a zero in the below array, then
  17. // the status area should be cleared out.
  18. const int c_rgidsSpoolerNotify[DELIVERY_NOTIFY_ALLDONE + 1][2] = {
  19. /* DELIVERY_NOTIFY_STARTING */ { 0, 0 },
  20. /* DELIVERY_NOTIFY_CONNECTING */ { idsSBConnecting, STATUS_IMAGE_CONNECTED },
  21. /* DELIVERY_NOTIFY_SECURE */ { 0, 0 },
  22. /* DELIVERY_NOTIFY_UNSECURE */ { 0, 0 },
  23. /* DELIVERY_NOTIFY_AUTHORIZING */ { idsAuthorizing, STATUS_IMAGE_AUTHORIZING },
  24. /* DELIVERY_NOTIFY_CHECKING */ { idsSBChecking, STATUS_IMAGE_CHECKING },
  25. /* DELIVERY_NOTIFY_CHECKING_NEWS */ { idsSBCheckingNews, STATUS_IMAGE_CHECKING_NEWS },
  26. /* DELIVERY_NOTIFY_SENDING */ { idsSBSending, STATUS_IMAGE_SENDING },
  27. /* DELIVERY_NOTIFY_SENDING_NEWS */ { idsSBSendingNews, STATUS_IMAGE_SENDING },
  28. /* DELIVERY_NOTIFY_RECEIVING */ { idsSBReceiving, STATUS_IMAGE_RECEIVING },
  29. /* DELIVERY_NOTIFY_RECEIVING_NEWS */ { idsSBReceivingNews, STATUS_IMAGE_RECEIVING },
  30. /* DELIVERY_NOTIFY_COMPLETE */ { 0, 0 },
  31. /* DELIVERY_NOTIFY_RESULT */ { 0, 0 },
  32. /* DELIVERY_NOTIFY_ALLDONE */ { idsSBNewMsgsControl, STATUS_IMAGE_NEWMSGS }
  33. };
  34. const int c_rgidsConnected[][2] = {
  35. { idsWorkingOffline, STATUS_IMAGE_OFFLINE },
  36. { idsWorkingOnline, STATUS_IMAGE_ONLINE },
  37. { idsNotConnected, STATUS_IMAGE_DISCONNECTED }
  38. };
  39. /////////////////////////////////////////////////////////////////////////////
  40. // Constructors etc.
  41. CStatusBar::CStatusBar()
  42. {
  43. m_cRef = 1;
  44. m_hwnd = 0;
  45. m_hwndProg = 0;
  46. m_tidOwner = 0;
  47. m_dwFlags = 0;
  48. m_himl = 0;
  49. ZeroMemory(m_rgIcons, sizeof(HICON) * STATUS_IMAGE_MAX);
  50. m_cxFiltered = 0;
  51. m_cxSpooler = 0;
  52. m_cxConnected = 0;
  53. m_cxProgress = 0;
  54. m_fInSimple = FALSE;
  55. m_ridFilter = RULEID_VIEW_ALL;
  56. m_statusConn = CONN_STATUS_WORKOFFLINE;
  57. m_typeDelivery = DELIVERY_NOTIFY_STARTING;
  58. m_cMsgsDelivery = 0;
  59. }
  60. CStatusBar::~CStatusBar()
  61. {
  62. // Free the image list
  63. if (m_himl)
  64. ImageList_Destroy(m_himl);
  65. // Free our icons
  66. for (UINT i = 0; i < STATUS_IMAGE_MAX; i++)
  67. {
  68. if (m_rgIcons[i])
  69. DestroyIcon(m_rgIcons[i]);
  70. }
  71. }
  72. /////////////////////////////////////////////////////////////////////////////
  73. // IUnknown
  74. //
  75. HRESULT CStatusBar::QueryInterface(REFIID riid, LPVOID *ppvObj)
  76. {
  77. *ppvObj = NULL;
  78. if (IsEqualIID(riid, IID_IUnknown))
  79. *ppvObj = (LPVOID) (IUnknown *) this;
  80. else if (IsEqualIID(riid, IID_IStatusBar))
  81. *ppvObj = (LPVOID) (IStatusBar *) this;
  82. if (NULL == *ppvObj)
  83. return (E_NOINTERFACE);
  84. AddRef();
  85. return S_OK;
  86. }
  87. ULONG CStatusBar::AddRef(void)
  88. {
  89. return InterlockedIncrement((LONG *) &m_cRef);
  90. }
  91. ULONG CStatusBar::Release(void)
  92. {
  93. InterlockedDecrement((LONG *) &m_cRef);
  94. if (0 == m_cRef)
  95. {
  96. delete this;
  97. return (0);
  98. }
  99. return (m_cRef);
  100. }
  101. //
  102. // FUNCTION: CStatusBar::Initialize()
  103. //
  104. // PURPOSE: Creates and initializes the status bar window.
  105. //
  106. // PARAMETERS:
  107. // [in] hwndParent - Handle of the window that will be this control's parent
  108. // [in] dwFlags - Determine which parts will be displayed
  109. //
  110. // RETURN VALUE:
  111. // E_OUTOFMEMORY, S_OK
  112. //
  113. HRESULT CStatusBar::Initialize(HWND hwndParent, DWORD dwFlags)
  114. {
  115. TraceCall("CStatusBar::Initialize");
  116. // This is now the thread that owns the class
  117. m_tidOwner = GetCurrentThreadId();
  118. // Keep these around
  119. m_dwFlags = dwFlags;
  120. // Create the status window
  121. m_hwnd = CreateStatusWindow(WS_CHILD | SBARS_SIZEGRIP | WS_CLIPSIBLINGS | SBT_TOOLTIPS,
  122. NULL, hwndParent, IDC_STATUS_BAR);
  123. if (!m_hwnd)
  124. return (E_OUTOFMEMORY);
  125. // Calculate the widths of the various areas we support
  126. _UpdateWidths();
  127. // Load the image list too
  128. m_himl = ImageList_LoadImage(g_hLocRes, MAKEINTRESOURCE(idbStatus), 16,
  129. 0, RGB(255, 0, 255), IMAGE_BITMAP, 0);
  130. // Note - We don't need to add any parts here since we do that in the
  131. // OnSize() call.
  132. return (S_OK);
  133. }
  134. //
  135. // FUNCTION: CStatusBar::ShowStatus()
  136. //
  137. // PURPOSE: Shows or hides the status bar.
  138. //
  139. // PARAMETERS:
  140. // [in] fShow - TRUE to show the bar, FALSE to hide it.
  141. //
  142. // RETURN VALUE:
  143. // S_OK
  144. //
  145. HRESULT CStatusBar::ShowStatus(BOOL fShow)
  146. {
  147. TraceCall("CStatusBar::ShowStatus");
  148. Assert(GetCurrentThreadId() == m_tidOwner);
  149. if (IsWindow(m_hwnd))
  150. ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
  151. return (S_OK);
  152. }
  153. //
  154. // FUNCTION: CStatusBar::OnSize()
  155. //
  156. // PURPOSE: Tells the status bar that the parent window resized. In return
  157. // the status bar updates it's own width to match.
  158. //
  159. // PARAMETERS:
  160. // [in] cx - New width of the paret
  161. //
  162. // RETURN VALUE:
  163. // HRESULT
  164. //
  165. HRESULT CStatusBar::OnSize(int cx, int cy)
  166. {
  167. int rgcx[SBP_MAX];
  168. int * prgcx = rgcx;
  169. DWORD cVisible = 1;
  170. DWORD cPart = SBP_MAX - 1;
  171. BOOL dwNoProgress = 0;
  172. int cxProgress = 0;
  173. int cxFiltered = 0;
  174. int cxConnected = 0;
  175. int cxSpooler = 0;
  176. TraceCall("CStatusBar::OnSize");
  177. Assert(GetCurrentThreadId() == m_tidOwner);
  178. // Forward a WM_SIZE message off to the status bar
  179. SendMessage(m_hwnd, WM_SIZE, SIZE_RESTORED, MAKELPARAM(cx, cy));
  180. // Check to see if the progress bar is visible
  181. dwNoProgress = !IsWindow(m_hwndProg);
  182. // Figure out our widths
  183. if (IsWindow(m_hwndProg))
  184. {
  185. cxProgress = m_cxProgress;
  186. cVisible++;
  187. }
  188. if ((0 == (m_dwFlags & SBI_HIDE_FILTERED)) && (RULEID_VIEW_ALL != m_ridFilter))
  189. {
  190. cxFiltered = m_cxFiltered;
  191. cVisible++;
  192. }
  193. if (0 == (m_dwFlags & SBI_HIDE_CONNECTED))
  194. {
  195. cxConnected = m_cxConnected;
  196. cVisible++;
  197. }
  198. if (0 == (m_dwFlags & SBI_HIDE_SPOOLER))
  199. {
  200. cxSpooler = m_cxSpooler;
  201. cVisible++;
  202. }
  203. // If we have a filter turned on
  204. if ((0 == (m_dwFlags & SBI_HIDE_FILTERED)) && (RULEID_VIEW_ALL != m_ridFilter))
  205. {
  206. *prgcx = cxFiltered;
  207. prgcx++;
  208. }
  209. // For general area
  210. *prgcx = cx - cxProgress - cxConnected - cxSpooler;
  211. prgcx++;
  212. // If we have progress
  213. if (0 != cxProgress)
  214. {
  215. *prgcx = cx - cxConnected - cxSpooler;
  216. prgcx++;
  217. }
  218. // For connected state
  219. *prgcx = cx - cxSpooler;
  220. prgcx++;
  221. // For spooler state
  222. *prgcx = cx;
  223. prgcx++;
  224. // Tell the status bar to update
  225. SendMessage(m_hwnd, SB_SETPARTS, cVisible, (LPARAM) rgcx);
  226. return (S_OK);
  227. }
  228. //
  229. // FUNCTION: CStatusBar::GetHeight()
  230. //
  231. // PURPOSE: Allows the caller to find out how tall the status bar is.
  232. //
  233. // PARAMETERS:
  234. // [out] pcy - Returns the height.
  235. //
  236. // RETURN VALUE:
  237. // HRESULT
  238. //
  239. HRESULT CStatusBar::GetHeight(int *pcy)
  240. {
  241. RECT rc;
  242. TraceCall("CStatusBar::GetHeight");
  243. if (!pcy)
  244. return (E_INVALIDARG);
  245. if (IsWindowVisible(m_hwnd))
  246. {
  247. GetClientRect(m_hwnd, &rc);
  248. *pcy = rc.bottom;
  249. }
  250. else
  251. *pcy = 0;
  252. return (S_OK);
  253. }
  254. //
  255. // FUNCTION: CStatusBar::ShowSimpleText()
  256. //
  257. // PURPOSE: Puts the status bar into simple mode and displays the
  258. // specified string.
  259. //
  260. // PARAMETERS:
  261. // [in] pszText - String or resource ID of the string to display
  262. //
  263. // RETURN VALUE:
  264. // S_OK
  265. //
  266. HRESULT CStatusBar::ShowSimpleText(LPTSTR pszText)
  267. {
  268. TCHAR szBuf[CCHMAX_STRINGRES] = "";
  269. TraceCall("CStatusBar::ShowSimpleText");
  270. Assert(GetCurrentThreadId() == m_tidOwner);
  271. // If we have a progress bar visible, hide it first
  272. if (IsWindow(m_hwndProg))
  273. ShowWindow(m_hwndProg, SW_HIDE);
  274. // Check to see if we need to load the string
  275. if (IS_INTRESOURCE(pszText) && pszText != 0)
  276. {
  277. LoadString(g_hLocRes, PtrToUlong(pszText), szBuf, ARRAYSIZE(szBuf));
  278. pszText = szBuf;
  279. }
  280. // Tell the status bar to go into simple mode
  281. SendMessage(m_hwnd, SB_SIMPLE, (WPARAM) TRUE, 0);
  282. m_fInSimple = TRUE;
  283. // Set the status text
  284. SendMessage(m_hwnd, SB_SETTEXT, SBT_NOBORDERS | 255, (LPARAM) pszText);
  285. return (S_OK);
  286. }
  287. //
  288. // FUNCTION: CStatusBar::HideSimpleText()
  289. //
  290. // PURPOSE: Tells the status bar to stop displaying simple mode.
  291. //
  292. // RETURN VALUE:
  293. // S_OK
  294. //
  295. HRESULT CStatusBar::HideSimpleText(void)
  296. {
  297. TraceCall("CStatusBar::HideSimpleText");
  298. Assert(GetCurrentThreadId() == m_tidOwner);
  299. // Tell the status bar to leave simple mode
  300. SendMessage(m_hwnd, SB_SIMPLE, (WPARAM) FALSE, 0);
  301. m_fInSimple = FALSE;
  302. // If we had a progress bar before, show it again
  303. if (IsWindow(m_hwndProg))
  304. ShowWindow(m_hwndProg, SW_SHOW);
  305. return (S_OK);
  306. }
  307. //
  308. // FUNCTION: CStatusBar::SetStatusText()
  309. //
  310. // PURPOSE: Sets the text for the SBP_GENERAL area
  311. //
  312. // PARAMETERS:
  313. // [in] pszText - String or resource ID of the string to display
  314. //
  315. // RETURN VALUE:
  316. // S_OK
  317. //
  318. HRESULT CStatusBar::SetStatusText(LPTSTR pszText)
  319. {
  320. TCHAR szBuf[CCHMAX_STRINGRES];
  321. TraceCall("CStatusBar::SetStatusText");
  322. Assert(GetCurrentThreadId() == m_tidOwner);
  323. DWORD dwPos = SBP_GENERAL;
  324. if ((m_dwFlags & SBI_HIDE_FILTERED) || (RULEID_VIEW_ALL == m_ridFilter))
  325. {
  326. dwPos--;
  327. }
  328. // Check to see if we need to load the string
  329. if (IS_INTRESOURCE(pszText))
  330. {
  331. AthLoadString(PtrToUlong(pszText), szBuf, ARRAYSIZE(szBuf));
  332. pszText = szBuf;
  333. }
  334. // Set the status text
  335. SendMessage(m_hwnd, SB_SETTEXT, dwPos, (LPARAM) pszText);
  336. return (S_OK);
  337. }
  338. //
  339. // FUNCTION: CStatusBar::ShowProgress()
  340. //
  341. // PURPOSE: Adds the progress bar area to the status bar.
  342. //
  343. // PARAMETERS:
  344. // [in] dwRange - Maximum range for the progress bar control
  345. //
  346. // RETURN VALUE:
  347. // E_OUTOFMEMORY, S_OK
  348. //
  349. HRESULT CStatusBar::ShowProgress(DWORD dwRange)
  350. {
  351. TraceCall("CStatusBar::ShowProgress");
  352. Assert(GetCurrentThreadId() == m_tidOwner);
  353. // Create the progress bar control
  354. m_hwndProg = CreateWindow(PROGRESS_CLASS, 0, WS_CHILD | PBS_SMOOTH,
  355. 0, 0, 10, 10, m_hwnd, (HMENU) IDC_STATUS_PROGRESS,
  356. g_hInst, NULL);
  357. if (!m_hwndProg)
  358. return (E_OUTOFMEMORY);
  359. DWORD dwPos = SBP_PROGRESS;
  360. if ((m_dwFlags & SBI_HIDE_FILTERED) || (RULEID_VIEW_ALL == m_ridFilter))
  361. {
  362. dwPos--;
  363. }
  364. // Hit the status bar with a size to force it to add the progress bar area
  365. RECT rc;
  366. GetClientRect(m_hwnd, &rc);
  367. OnSize(rc.right, rc.bottom);
  368. SendMessage(m_hwndProg, PBM_SETRANGE32, 0, dwRange);
  369. // Now size the progress bar to sit inside the status bar
  370. SendMessage(m_hwnd, SB_GETRECT, dwPos, (LPARAM) &rc);
  371. SetWindowPos(m_hwndProg, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
  372. SWP_NOZORDER | SWP_NOACTIVATE);
  373. // If we're not in simple mode, show it
  374. if (!m_fInSimple)
  375. ShowWindow(m_hwndProg, SW_SHOW);
  376. return (S_OK);
  377. }
  378. //
  379. // FUNCTION: CStatusBar::SetProgress()
  380. //
  381. // PURPOSE: Set's the progress bar position.
  382. //
  383. // PARAMETERS:
  384. // [in] dwPos - New progress bar position
  385. //
  386. // RETURN VALUE:
  387. // S_OK
  388. //
  389. HRESULT CStatusBar::SetProgress(DWORD dwPos)
  390. {
  391. TraceCall("CStatusBar::SetProgress");
  392. Assert(GetCurrentThreadId() == m_tidOwner);
  393. // Update the progress bar
  394. if (IsWindow(m_hwndProg))
  395. {
  396. SendMessage(m_hwndProg, PBM_SETPOS, dwPos, 0);
  397. }
  398. return (S_OK);
  399. }
  400. //
  401. // FUNCTION: CStatusBar::HideProgress()
  402. //
  403. // PURPOSE: Hides the progress bar.
  404. //
  405. // RETURN VALUE:
  406. // S_OK
  407. //
  408. HRESULT CStatusBar::HideProgress(void)
  409. {
  410. TraceCall("CStatusBar::HideProgress");
  411. Assert(GetCurrentThreadId() == m_tidOwner);
  412. if (IsWindow(m_hwndProg))
  413. {
  414. // Destroy the progress bar
  415. DestroyWindow(m_hwndProg);
  416. m_hwndProg = 0;
  417. // Hit the status bar with a size to have it remove the well
  418. RECT rc;
  419. GetClientRect(m_hwnd, &rc);
  420. OnSize(rc.right, rc.bottom);
  421. }
  422. return (S_OK);
  423. }
  424. //
  425. // FUNCTION: CStatusBar::SetConnectedStatus()
  426. //
  427. // PURPOSE: Updates the status in the SBP_CONNECTED area
  428. //
  429. // PARAMETERS:
  430. // [in] status - New status
  431. //
  432. // RETURN VALUE:
  433. // S_OK
  434. //
  435. HRESULT CStatusBar::SetConnectedStatus(CONN_STATUS status)
  436. {
  437. TraceCall("SetConnectedStatus");
  438. Assert(GetCurrentThreadId() == m_tidOwner);
  439. // First job is to figure out the position
  440. DWORD dwPos = SBP_CONNECTED - (!IsWindow(m_hwndProg));
  441. if ((m_dwFlags & SBI_HIDE_FILTERED) || (RULEID_VIEW_ALL == m_ridFilter))
  442. {
  443. dwPos--;
  444. }
  445. // Next, load the appropriate string for this new status
  446. TCHAR szRes[CCHMAX_STRINGRES];
  447. Assert(status < CONN_STATUS_MAX);
  448. AthLoadString(c_rgidsConnected[status][0], szRes, ARRAYSIZE(szRes));
  449. // Also need to load the right picture
  450. HICON hIcon = _GetIcon(c_rgidsConnected[status][1]);
  451. // Tell the status bar to update
  452. SendMessage(m_hwnd, SB_SETTEXT, dwPos, (LPARAM) szRes);
  453. SendMessage(m_hwnd, SB_SETICON, dwPos, (LPARAM) hIcon);
  454. // Cache the connection status
  455. m_statusConn = status;
  456. return (S_OK);
  457. }
  458. //
  459. // FUNCTION: CStatusBar::SetSpoolerStatus()
  460. //
  461. // PURPOSE: Updates the spooler area.
  462. //
  463. // PARAMETERS:
  464. // [in] type - New status
  465. //
  466. // RETURN VALUE:
  467. // HRESULT
  468. //
  469. HRESULT CStatusBar::SetSpoolerStatus(DELIVERYNOTIFYTYPE type, DWORD cMsgs)
  470. {
  471. TCHAR szRes[CCHMAX_STRINGRES] = "";
  472. HICON hIcon;
  473. DWORD dwPos;
  474. TraceCall("CStatusBar::SetSpoolerStatus");
  475. Assert(GetCurrentThreadId() == m_tidOwner);
  476. Assert(type <= DELIVERY_NOTIFY_ALLDONE);
  477. // First job is to figure out the position
  478. dwPos = SBP_SPOOLER - (0 != (m_dwFlags & SBI_HIDE_CONNECTED)) - (!IsWindow(m_hwndProg));
  479. if ((m_dwFlags & SBI_HIDE_FILTERED) || (RULEID_VIEW_ALL == m_ridFilter))
  480. {
  481. dwPos--;
  482. }
  483. // If we are at the ALLDONE state, we do some extra work
  484. if (type == DELIVERY_NOTIFY_ALLDONE)
  485. {
  486. if (-1 == cMsgs)
  487. {
  488. // Some error occured
  489. hIcon = _GetIcon(STATUS_IMAGE_ERROR);
  490. AthLoadString(idsErrorText, szRes, ARRAYSIZE(szRes));
  491. }
  492. else if (0 == cMsgs)
  493. {
  494. hIcon = _GetIcon(STATUS_IMAGE_NOMSGS);
  495. AthLoadString(idsSBNoNewMsgs, szRes, ARRAYSIZE(szRes));
  496. }
  497. else
  498. {
  499. TCHAR szBuf[CCHMAX_STRINGRES];
  500. hIcon = _GetIcon(STATUS_IMAGE_NEWMSGS);
  501. AthLoadString(idsSBNewMsgsControl, szBuf, ARRAYSIZE(szBuf));
  502. wnsprintf(szRes, ARRAYSIZE(szRes), szBuf, cMsgs);
  503. }
  504. }
  505. else
  506. {
  507. hIcon = _GetIcon(c_rgidsSpoolerNotify[type][1]);
  508. if (c_rgidsSpoolerNotify[type][0])
  509. AthLoadString(c_rgidsSpoolerNotify[type][0], szRes, ARRAYSIZE(szRes));
  510. }
  511. // Tell the status bar to update
  512. if (*szRes != 0)
  513. {
  514. SendMessage(m_hwnd, SB_SETTEXT, dwPos, (LPARAM) szRes);
  515. SendMessage(m_hwnd, SB_SETICON, dwPos, (LPARAM) hIcon);
  516. }
  517. else
  518. {
  519. SendMessage(m_hwnd, SB_SETTEXT, dwPos, (LPARAM) szRes);
  520. SendMessage(m_hwnd, SB_SETICON, dwPos, 0);
  521. }
  522. // Cache the delivery info
  523. m_typeDelivery = type;
  524. m_cMsgsDelivery = cMsgs;
  525. return (S_OK);
  526. }
  527. //
  528. // FUNCTION: CStatusBar::OnNotify()
  529. //
  530. // PURPOSE: Sends notifications to the status bar
  531. //
  532. // PARAMETERS:
  533. // NMHDR *pnmhdr
  534. //
  535. // RETURN VALUE:
  536. // HRESULT
  537. //
  538. HRESULT CStatusBar::OnNotify(NMHDR *pNotify)
  539. {
  540. DWORD dwPoints;
  541. POINT pt;
  542. RECT rc;
  543. DWORD dwSpoolerPos;
  544. DWORD dwConnectPos;
  545. TraceCall("CStatusBar::OnNotify");
  546. Assert(GetCurrentThreadId() == m_tidOwner);
  547. if (m_dwFlags & SBI_HIDE_SPOOLER)
  548. {
  549. dwSpoolerPos = -1;
  550. }
  551. else
  552. {
  553. dwSpoolerPos = SBP_SPOOLER - (!IsWindow(m_hwndProg));
  554. if ((m_dwFlags & SBI_HIDE_FILTERED) || (RULEID_VIEW_ALL == m_ridFilter))
  555. {
  556. dwSpoolerPos--;
  557. }
  558. }
  559. dwConnectPos = (m_dwFlags & SBI_HIDE_CONNECTED) ? -1 : dwSpoolerPos - 1;
  560. if (pNotify->idFrom == IDC_STATUS_BAR)
  561. {
  562. if (NM_DBLCLK == pNotify->code)
  563. {
  564. dwPoints = GetMessagePos();
  565. pt.x = LOWORD(dwPoints);
  566. pt.y = HIWORD(dwPoints);
  567. ScreenToClient(m_hwnd, &pt);
  568. SendMessage(m_hwnd, SB_GETRECT, dwSpoolerPos, (LPARAM)&rc);
  569. if (PtInRect(&rc, pt))
  570. {
  571. g_pSpooler->StartDelivery(GetParent(m_hwnd), NULL, FOLDERID_INVALID, DELIVER_SHOW);
  572. }
  573. else
  574. {
  575. SendMessage(m_hwnd, SB_GETRECT, dwConnectPos, (LPARAM)&rc);
  576. if (PtInRect(&rc, pt))
  577. {
  578. PostMessage(GetParent(m_hwnd), WM_COMMAND, ID_WORK_OFFLINE, 0);
  579. }
  580. }
  581. }
  582. }
  583. return (S_OK);
  584. }
  585. //
  586. // FUNCTION: CStatusBar::SetFilter()
  587. //
  588. // PURPOSE: Sets the filter for the SBP_FILTERED area
  589. //
  590. // PARAMETERS:
  591. // [in] ridFilter - ID for the current filter
  592. //
  593. // RETURN VALUE:
  594. // S_OK
  595. //
  596. HRESULT CStatusBar::SetFilter(RULEID ridFilter)
  597. {
  598. RECT rc;
  599. TCHAR szBuf[CCHMAX_STRINGRES];
  600. DWORD dwPos;
  601. TraceCall("CStatusBar::SetFilter");
  602. Assert(GetCurrentThreadId() == m_tidOwner);
  603. // Get the data
  604. dwPos = SBP_GENERAL;
  605. if ((m_dwFlags & SBI_HIDE_FILTERED) || (RULEID_VIEW_ALL == m_ridFilter))
  606. {
  607. dwPos--;
  608. }
  609. // Get the status text
  610. SendMessage(m_hwnd, SB_GETTEXT, dwPos, (LPARAM) szBuf);
  611. // Cache the rule
  612. m_ridFilter = ridFilter;
  613. // Resize the status bar
  614. GetClientRect(m_hwnd, &rc);
  615. OnSize(rc.right, rc.bottom);
  616. dwPos = SBP_GENERAL;
  617. if ((m_dwFlags & SBI_HIDE_FILTERED) || (RULEID_VIEW_ALL == m_ridFilter))
  618. {
  619. dwPos--;
  620. }
  621. // Set the status text
  622. SendMessage(m_hwnd, SB_SETTEXT, dwPos, (LPARAM) szBuf);
  623. SendMessage(m_hwnd, SB_SETICON, dwPos, (LPARAM) NULL);
  624. AthLoadString(idsViewFiltered, szBuf, ARRAYSIZE(szBuf));
  625. // Set the data into the status bar
  626. if ((0 == (m_dwFlags & SBI_HIDE_FILTERED)) && (RULEID_VIEW_ALL != m_ridFilter))
  627. {
  628. SendMessage(m_hwnd, SB_SETTEXT, SBP_FILTERED, (LPARAM) szBuf);
  629. }
  630. if (0 == (m_dwFlags & SBI_HIDE_SPOOLER))
  631. {
  632. SetConnectedStatus(m_statusConn);
  633. }
  634. if (0 == (m_dwFlags & SBI_HIDE_CONNECTED))
  635. {
  636. SetSpoolerStatus(m_typeDelivery, m_cMsgsDelivery);
  637. }
  638. return (S_OK);
  639. }
  640. //
  641. // FUNCTION: CStatusBar::_UpdateWidths()
  642. //
  643. // PURPOSE: Calculates the widths of each of the different areas of the
  644. // status bar.
  645. //
  646. void CStatusBar::_UpdateWidths(void)
  647. {
  648. HDC hdc;
  649. TCHAR szBuf[CCHMAX_STRINGRES];
  650. SIZE size;
  651. int i;
  652. TraceCall("CStatusBar::_UpdateWidths");
  653. // Get the DC from the status bar
  654. hdc = GetDC(m_hwnd);
  655. // Now we need to figure out how big our parts are going to be.
  656. // Figure out the space needed for the filtered state
  657. AthLoadString(idsViewFiltered, szBuf, ARRAYSIZE(szBuf));
  658. GetTextExtentPoint32(hdc, szBuf, lstrlen(szBuf), &size);
  659. m_cxFiltered = size.cx;
  660. // Add some padding and space for the icon
  661. m_cxFiltered += (2 * GetSystemMetrics(SM_CXEDGE));
  662. // Figure out the space needed for the spooler state
  663. for (i = 0; i < ARRAYSIZE(c_rgidsSpoolerNotify); i++)
  664. {
  665. if (c_rgidsSpoolerNotify[i][0])
  666. {
  667. AthLoadString(c_rgidsSpoolerNotify[i][0], szBuf, ARRAYSIZE(szBuf));
  668. GetTextExtentPoint32(hdc, szBuf, lstrlen(szBuf), &size);
  669. if (size.cx > m_cxSpooler)
  670. m_cxSpooler = size.cx;
  671. }
  672. }
  673. // Add some padding and space for the icon and the grippy thing
  674. m_cxSpooler += (2 * GetSystemMetrics(SM_CXEDGE)) + 24 + 16;
  675. // Do the same for the connected part
  676. for (i = 0; i < ARRAYSIZE(c_rgidsConnected); i++)
  677. {
  678. if (c_rgidsConnected[i][0])
  679. {
  680. LoadString(g_hLocRes, c_rgidsConnected[i][0], szBuf, ARRAYSIZE(szBuf));
  681. GetTextExtentPoint32(hdc, szBuf, lstrlen(szBuf), &size);
  682. if (size.cx > m_cxConnected)
  683. m_cxConnected = size.cx;
  684. }
  685. }
  686. // Add some padding and space for the icon
  687. m_cxConnected += (2 * GetSystemMetrics(SM_CXEDGE)) + 24;
  688. // Let's say that the progress is always equal to
  689. // the space for the connected area
  690. m_cxProgress = m_cxConnected;
  691. ReleaseDC(m_hwnd, hdc);
  692. return;
  693. }
  694. HICON CStatusBar::_GetIcon(DWORD iIndex)
  695. {
  696. // Make sure the index is valid
  697. if (iIndex > STATUS_IMAGE_MAX)
  698. return 0;
  699. // Check to see if we've already created this one
  700. if (m_rgIcons[iIndex])
  701. return (m_rgIcons[iIndex]);
  702. // Otherwise, create it.
  703. m_rgIcons[iIndex] = ImageList_GetIcon(m_himl, iIndex, ILD_TRANSPARENT);
  704. return (m_rgIcons[iIndex]);
  705. }