Source code of Windows XP (NT5)
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.

585 lines
15 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: Progtab.cpp
  7. //
  8. // Contents: Progress tab
  9. //
  10. // Classes:
  11. //
  12. // Notes: Handle the custom results pane.
  13. //
  14. // History: 05-Nov-97 Susia Created.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "precomp.h"
  18. extern HINSTANCE g_hInst; // current instance
  19. extern BOOL CALLBACK ProgressWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam);
  20. BOOL CALLBACK ResultsProgressWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam);
  21. //--------------------------------------------------------------------------------
  22. //
  23. // FUNCTION: ListBox_HitTest(HWND hwnd, LONG xPos, LONG yPos)
  24. //
  25. // PURPOSE: HitTest for a ListBox, since Windows was nice enough to not provide one
  26. // This is really a function to see if the hittest falls in the range
  27. // of the More Info Jump text.
  28. //
  29. // COMMENTS: Implemented on main thread.
  30. //
  31. //--------------------------------------------------------------------------------
  32. INT ListBox_HitTest(HWND hwnd, LONG xPos, LONG yPos)
  33. {
  34. int begin = ListBox_GetTopIndex(hwnd);
  35. int end = ListBox_GetCount(hwnd);
  36. int i;
  37. RECT rcRect;
  38. for (i=begin;i<end;i++)
  39. {
  40. LBDATA *pData = NULL;
  41. if (ListBox_GetItemRect(hwnd, i, &rcRect))
  42. {
  43. pData = (LBDATA *) ListBox_GetItemData(hwnd,i);
  44. if (pData == NULL)
  45. {
  46. // if no data then try the next one
  47. continue;
  48. }
  49. // if textRect not calculated then this isn't visible.
  50. if (pData->fTextRectValid)
  51. {
  52. // only use left and right vars for hit test. top and bottom
  53. // can change.
  54. // compare y values first since they are the ones
  55. // most likely to be different.
  56. if ( (yPos >= rcRect.top) &&
  57. (yPos <= rcRect.bottom) &&
  58. (xPos >= pData->rcTextHitTestRect.left) &&
  59. (xPos <= pData->rcTextHitTestRect.right) )
  60. {
  61. return i;
  62. }
  63. }
  64. }
  65. }
  66. return -1;
  67. }
  68. //--------------------------------------------------------------------------------
  69. //
  70. // FUNCTION: OnProgressResultsDrawItem(HWND hwnd, UINT idCtl, LPDRAWITEMSTRUCT lpdis)
  71. //
  72. // PURPOSE: Handle DrawItem events for Progress Dialog Results Tab
  73. //
  74. // COMMENTS: Implemented on main thread.
  75. //
  76. //--------------------------------------------------------------------------------
  77. BOOL OnProgressResultsDrawItem(HWND hwnd,CProgressDlg *pProgress,UINT idCtl, const DRAWITEMSTRUCT* lpDrawItem)
  78. {
  79. HDC hdc = lpDrawItem->hDC;
  80. COLORREF clrText, clrBack;
  81. RECT rcText, rcFocus;
  82. LOGFONT lf;
  83. HGDIOBJ hFont, hFontOld;
  84. HFONT hFontJumpText = NULL;
  85. int nSavedDC;
  86. LBDATA *pData = (LBDATA *) lpDrawItem->itemData;
  87. if (!hdc || !pData)
  88. {
  89. return FALSE;
  90. }
  91. nSavedDC = SaveDC(hdc);
  92. Assert(lpDrawItem->CtlType == ODT_LISTBOX);
  93. if (lpDrawItem->itemID == -1)
  94. goto exit;
  95. clrBack = SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  96. // Clear the item for drawing
  97. // + 1 is just the way you do it for some reason
  98. FillRect(hdc, &(lpDrawItem->rcItem),
  99. (HBRUSH) (COLOR_WINDOW + 1) );
  100. if (pData->IconIndex != -1)
  101. {
  102. ImageList_Draw(pProgress->m_errorimage,
  103. pData->IconIndex,
  104. hdc,
  105. BULLET_INDENT,
  106. lpDrawItem->rcItem.top + BULLET_INDENT,
  107. ILD_TRANSPARENT);
  108. }
  109. // Set up the font, text and background colors
  110. hFont = (HFONT) SendMessage(hwnd, WM_GETFONT, 0, 0);
  111. if (hFont)
  112. {
  113. Assert(NULL == hFontJumpText);
  114. if (pData->fIsJump && GetObject(hFont,sizeof(LOGFONT),&lf))
  115. {
  116. lf.lfUnderline = TRUE;
  117. hFontJumpText = CreateFontIndirect(&lf);
  118. if (hFontJumpText)
  119. {
  120. hFontOld = SelectObject(hdc,hFontJumpText);
  121. }
  122. }
  123. if (!hFontJumpText)
  124. {
  125. hFontOld = SelectObject(hdc,hFont);
  126. }
  127. }
  128. // set up colors
  129. if (pData->fIsJump)
  130. {
  131. // even if don't get font change the attribs;
  132. if (pData->fHasBeenClicked)
  133. {
  134. clrText = SetTextColor(hdc, RGB(128,0,128));
  135. }
  136. else
  137. {
  138. clrText = SetTextColor(hdc, RGB(0,0,255));
  139. }
  140. }
  141. else
  142. {
  143. clrText = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  144. }
  145. // calc what the drawText should be. Need to take our stored
  146. // text value and adjust the top.
  147. {
  148. RECT rpDataRect = pData->rcText;
  149. rcText = lpDrawItem->rcItem;
  150. rcText.top = lpDrawItem->rcItem.top + BULLET_INDENT;
  151. rcText.left += rpDataRect.left;
  152. rcText.right = rcText.left + WIDTH(rpDataRect);
  153. }
  154. /* rcText = lpDrawItem->rcItem;
  155. rcText.left += (pProgress->m_iIconMetricX*3)/2 + BULLET_INDENT; // move over Icon distance
  156. rcText.top += BULLET_INDENT;
  157. */
  158. // draw the text using the TextBox we calc'd in Measure Item
  159. DrawText(hdc,pData->pszText, -1,
  160. &rcText,
  161. DT_NOCLIP | DT_WORDBREAK );
  162. // If we need a focus rect, do that too
  163. if (lpDrawItem->itemState & ODS_FOCUS)
  164. {
  165. rcFocus = lpDrawItem->rcItem;
  166. // rcFocus.left += (pProgress->m_iIconMetricX*3)/2;
  167. rcFocus.top += BULLET_INDENT;
  168. rcFocus.left += BULLET_INDENT;
  169. DrawFocusRect(hdc, &rcFocus);
  170. }
  171. // SetBkColor(hdc, clrBack);
  172. // SetTextColor(hdc, clrText);
  173. if (nSavedDC)
  174. {
  175. RestoreDC(hdc,nSavedDC);
  176. }
  177. if (hFontJumpText)
  178. {
  179. DeleteObject(hFontJumpText);
  180. }
  181. exit:
  182. return TRUE;
  183. }
  184. //--------------------------------------------------------------------------------
  185. //
  186. // FUNCTION: OnProgressResultsMeasureItem(HWND hwnd, CProgressDlg *pProgress, UINT *horizExtent UINT idCtl, MEASUREITEMSTRUCT *pMeasureItem)
  187. //
  188. // PURPOSE: Handle MeasureItem events for Progress Dialog Results Tab
  189. //
  190. // COMMENTS: Implemented on main thread.
  191. //
  192. //--------------------------------------------------------------------------------
  193. BOOL OnProgressResultsMeasureItem(HWND hwnd,CProgressDlg *pProgress, UINT *horizExtent, UINT /* idCtl */, MEASUREITEMSTRUCT *pMeasureItem)
  194. {
  195. LBDATA *pData = NULL;
  196. HWND hwndList = GetDlgItem(hwnd,IDC_LISTBOXERROR);
  197. if (!hwndList)
  198. {
  199. return FALSE;
  200. }
  201. pData = (LBDATA *) ListBox_GetItemData(hwndList, pMeasureItem->itemID);
  202. if (pData == NULL)
  203. {
  204. Assert(pProgress != NULL);
  205. Assert(pProgress->m_CurrentListEntry != NULL);
  206. pData = pProgress->m_CurrentListEntry;
  207. }
  208. if (pData == NULL)
  209. {
  210. return FALSE;
  211. }
  212. HFONT hfont = NULL;
  213. HFONT hFontJumpText = NULL;
  214. HDC hdc;
  215. int iHeight;
  216. int nSavedDC;
  217. hdc = GetDC(hwndList);
  218. if (NULL == hdc)
  219. {
  220. return FALSE;
  221. }
  222. nSavedDC = SaveDC(hdc);
  223. // Get the size of the string
  224. hfont = (HFONT) SendMessage(hwnd, WM_GETFONT, 0, 0);
  225. // if can't get font or jump text font just use the
  226. // current font.
  227. if (hfont)
  228. {
  229. // if this is jump text then change some
  230. // font attributes.
  231. if (pData->fIsJump)
  232. {
  233. LOGFONT lf;
  234. if (GetObject(hfont,sizeof(LOGFONT),&lf))
  235. {
  236. lf.lfUnderline = TRUE;
  237. hFontJumpText = CreateFontIndirect(&lf);
  238. }
  239. }
  240. if (hFontJumpText)
  241. {
  242. SelectFont(hdc, hFontJumpText);
  243. }
  244. else
  245. {
  246. SelectFont(hdc, hfont);
  247. }
  248. }
  249. int cxResultsWidth;
  250. RECT rcRect;
  251. // GetClientRect seems to subtract off the Scroll Bars for us.
  252. GetClientRect(hwndList, &rcRect);
  253. cxResultsWidth = rcRect.right;
  254. SetRect(&rcRect, 0, 0, cxResultsWidth, 0);
  255. // subtract off the length of Icon + 1/2
  256. rcRect.right -= ((pProgress->m_iIconMetricX*3)/2
  257. + BULLET_INDENT );
  258. int tempwidth = rcRect.right;
  259. iHeight = DrawText(hdc, pData->pszText, -1, &rcRect,
  260. DT_NOCLIP | DT_CALCRECT | DT_WORDBREAK) + BULLET_INDENT;
  261. //We have a smegging word in the string wider than the rect.
  262. if (rcRect.right > tempwidth)
  263. {
  264. *horizExtent = cxResultsWidth + (rcRect.right - tempwidth);
  265. // fix up the proper width
  266. rcRect.right = cxResultsWidth + (rcRect.right - tempwidth);
  267. }
  268. else
  269. {
  270. rcRect.right = cxResultsWidth;
  271. }
  272. rcRect.left += ((pProgress->m_iIconMetricX*3)/2
  273. + BULLET_INDENT );
  274. // bottom is either the height of the line or if it has
  275. // an icon the max of these two.
  276. if (-1 != pData->IconIndex)
  277. {
  278. rcRect.bottom = max(iHeight,pProgress->m_iIconMetricY + BULLET_INDENT*2);
  279. }
  280. else
  281. {
  282. rcRect.bottom = iHeight;
  283. }
  284. // if need to add space on the end then do that
  285. if (pData->fAddLineSpacingAtEnd)
  286. {
  287. SIZE Size;
  288. if (!GetTextExtentPoint(hdc,SZ_SYNCMGRNAME,
  289. lstrlen(SZ_SYNCMGRNAME),&Size))
  290. {
  291. // if can't get size make up a number
  292. Size.cy = 13;
  293. }
  294. // lets do 2/3 a line spacing.
  295. rcRect.bottom += (Size.cy*2)/3;
  296. }
  297. // store the TextRect in the pData field.
  298. pMeasureItem->itemHeight = rcRect.bottom;
  299. pMeasureItem->itemWidth = cxResultsWidth;
  300. pData->rcText = rcRect;
  301. pData->fTextRectValid = TRUE;
  302. pData->rcTextHitTestRect = rcRect;
  303. if (pData->fIsJump)
  304. {
  305. SIZE size;
  306. // on jump text want the hit test only over the actual text
  307. // in the horizontal location.
  308. if(GetTextExtentPoint(hdc,pData->pszText,lstrlen(pData->pszText), &size))
  309. {
  310. pData->rcTextHitTestRect.right = size.cx + pData->rcTextHitTestRect.left;
  311. }
  312. }
  313. if (nSavedDC)
  314. {
  315. RestoreDC(hdc,nSavedDC);
  316. }
  317. if (hFontJumpText)
  318. {
  319. DeleteObject(hFontJumpText);
  320. }
  321. ReleaseDC(hwndList, hdc);
  322. return TRUE;
  323. }
  324. //--------------------------------------------------------------------------------
  325. //
  326. // FUNCTION: OnProgressResultsDeleteItem(HWND hwnd, UINT idCtl, const DELETEITEMSTRUCT * lpDeleteItem)
  327. //
  328. // PURPOSE: Handle DeleteItem events for Progress Dialog Results Tab
  329. //
  330. // COMMENTS: Implemented on main thread.
  331. //
  332. //--------------------------------------------------------------------------------
  333. BOOL OnProgressResultsDeleteItem(HWND hwnd,UINT idCtl, const DELETEITEMSTRUCT * lpDeleteItem)
  334. {
  335. // Assert(lpDeleteItem->itemData);
  336. if (lpDeleteItem->itemData)
  337. {
  338. FREE((LPVOID) lpDeleteItem->itemData);
  339. }
  340. return TRUE;
  341. }
  342. void OnProgressResultsSize(HWND hwnd,CProgressDlg *pProgress,UINT uMsg,WPARAM wParam,LPARAM lParam)
  343. {
  344. HWND hwndList = GetDlgItem(hwnd,IDC_LISTBOXERROR);
  345. int iItems = ListBox_GetCount(hwndList);
  346. int iCurItem;
  347. MEASUREITEMSTRUCT measureItem;
  348. RECT rect;
  349. UINT horizExtent = 0;
  350. SendMessage(hwndList,WM_SETREDRAW,FALSE /*fRedraw */,0);
  351. GetClientRect(hwndList,&rect);
  352. for (iCurItem = 0 ; iCurItem < iItems; ++iCurItem)
  353. {
  354. measureItem.itemID = iCurItem;
  355. if (OnProgressResultsMeasureItem(hwnd,pProgress,&horizExtent, -1,&measureItem))
  356. {
  357. ListBox_SetItemHeight(hwndList, iCurItem, measureItem.itemHeight);
  358. }
  359. }
  360. //make sure there is a horizontal scroll bar if needed.
  361. SendMessage(hwndList, LB_SETHORIZONTALEXTENT, horizExtent, 0L);
  362. SendMessage(hwndList,WM_SETREDRAW,TRUE /*fRedraw */,0);
  363. InvalidateRect(hwndList,&rect,FALSE);
  364. }
  365. //--------------------------------------------------------------------------------
  366. //
  367. // FUNCTION: ResultsListBoxWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam)
  368. //
  369. // PURPOSE: Callback for Progress Dialog Update Tab
  370. //
  371. // COMMENTS: Implemented on main thread.
  372. //
  373. //--------------------------------------------------------------------------------
  374. BOOL CALLBACK ResultsListBoxWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam)
  375. {
  376. CProgressDlg *pProgressDlg = (CProgressDlg *) GetWindowLongPtr(GetParent(hwnd), DWLP_USER);
  377. // OUR PARENT HAS A POINTER TO THE progress in dwl_user.
  378. switch (uMsg)
  379. {
  380. case WM_POWERBROADCAST:
  381. {
  382. DWORD dwRet = TRUE;
  383. if (wParam == PBT_APMQUERYSUSPEND)
  384. {
  385. // if just created or syncing don't suspend
  386. if (pProgressDlg)
  387. {
  388. if ( (pProgressDlg->m_dwProgressFlags & PROGRESSFLAG_NEWDIALOG)
  389. || (pProgressDlg->m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS))
  390. {
  391. dwRet = BROADCAST_QUERY_DENY;
  392. }
  393. }
  394. return dwRet;
  395. }
  396. }
  397. break;
  398. case WM_SETCURSOR:
  399. return TRUE; // rely on mousemove to set the cursor.
  400. break;
  401. case WM_MOUSEMOVE:
  402. {
  403. int index = ListBox_HitTest(hwnd, (LONG) LOWORD(lParam),(LONG) HIWORD(lParam));
  404. LBDATA *lbData =(LBDATA *) ListBox_GetItemData(hwnd, index);
  405. if (lbData)
  406. {
  407. if ((index != -1) && (lbData->fIsJump))
  408. {
  409. SetCursor(LoadCursor(g_hInst,MAKEINTRESOURCE(IDC_HARROW)));
  410. }
  411. else
  412. {
  413. SetCursor(LoadCursor(NULL,IDC_ARROW));
  414. }
  415. }
  416. }
  417. break;
  418. case WM_KEYDOWN:
  419. case WM_LBUTTONDBLCLK:
  420. case WM_LBUTTONDOWN:
  421. {
  422. int index = -1;
  423. LBDATA *lbData = NULL;
  424. // get index either through hittest of selection based on
  425. // if keydown or not.
  426. if (uMsg == WM_KEYDOWN)
  427. {
  428. if (VK_SPACE == ((int) wParam) )
  429. {
  430. index = ListBox_GetCurSel(hwnd);
  431. }
  432. else
  433. {
  434. break; // don't mess with any other keys
  435. }
  436. }
  437. else
  438. {
  439. index = ListBox_HitTest(hwnd, (LONG) LOWORD(lParam),(LONG) HIWORD(lParam));
  440. }
  441. if (-1 != index)
  442. {
  443. lbData =(LBDATA *) ListBox_GetItemData(hwnd, index);
  444. }
  445. if ((lbData) && (lbData->fIsJump))
  446. {
  447. if (pProgressDlg)
  448. {
  449. if (NOERROR == pProgressDlg->OnShowError(lbData->pHandlerID,
  450. hwnd,
  451. lbData->ErrorID))
  452. {
  453. lbData->fHasBeenClicked = TRUE;
  454. RedrawWindow(hwnd, NULL,NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  455. }
  456. return 0;
  457. }
  458. }
  459. break;
  460. }
  461. default:
  462. break;
  463. }
  464. if (pProgressDlg && pProgressDlg->m_fnResultsListBox)
  465. {
  466. return (BOOL)CallWindowProc(pProgressDlg->m_fnResultsListBox, hwnd, uMsg, wParam, lParam);
  467. }
  468. return TRUE;
  469. }