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.

1030 lines
29 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. void SetMYLBAcc(HWND hListWin);
  4. void DrawMYLBFocus(HWND hListWin, LPDRAWITEMSTRUCT lpdis, MYLBFOCUS enCurFocus, INT nCurFocusId);
  5. void DrawItem(LPDRAWITEMSTRUCT lpdis, BOOL fSelectionDisabled);
  6. void DrawTitle(HDC hDC, LBITEM * plbi, RECT rc);
  7. void DrawRTF(HDC hDC, LBITEM * plbi, const RECT & rc /*, BOOL bHit*/);
  8. void DrawDescription(HDC hDC, LBITEM * plbi, RECT & rc);
  9. void DrawBitmap(HDC hDC, LBITEM * plbi, const RECT & rc, BOOL fSel, BOOL fSelectionDisabled);
  10. void CalcTitleFocusRect(const RECT &rcIn, RECT & rcOut);
  11. void CalcRTFFocusRect(const RECT &rcIn, RECT & rcOut);
  12. int CalcDescHeight(HDC hDC, LBITEM * plbi, int cx);
  13. int CalcRTFHeight(HDC hDC, LBITEM * plbi);
  14. int CalcRTFWidth(HDC hDC, LBITEM * plbi);
  15. int CalcTitleHeight(HDC hDC, LBITEM * plbi, int cx);
  16. void CalcItemLocation(HDC hDC, LBITEM * plbi, const RECT & rc);
  17. void ToggleSelection(HWND hDlg, HWND hListWin, LBITEM *pItem);
  18. void AddItem(LPTSTR tszTitle, LPTSTR tszDesc, LPTSTR tszRTF, int index, BOOL fSelected, BOOL fRTF);
  19. BOOL CurItemHasRTF(HWND hListWin);
  20. void RedrawMYLB(HWND hwndLB);
  21. void LaunchRTF(HWND hListWin);
  22. HBITMAP ghBmpGrayOut; //=NULL;
  23. HBITMAP ghBmpCheck; // = NULL;
  24. HBITMAP ghBmpClear; // = NULL;
  25. HFONT ghFontUnderline; // = NULL;
  26. HFONT ghFontBold; // = NULL;
  27. HFONT ghFontNormal; // = NULL;
  28. HWND ghWndList; //=NULL;
  29. MYLBFOCUS gFocus;
  30. INT gFocusItemId;
  31. TCHAR gtszRTFShortcut[MAX_RTFSHORTCUTDESC_LENGTH];
  32. void LaunchRTF(HWND hListWin)
  33. {
  34. HWND hDlg = GetParent(hListWin);
  35. int i = (LONG)SendMessage(ghWndList, LB_GETCURSEL, 0, 0);
  36. if(i != LB_ERR)
  37. {
  38. LBITEM* pItem = (LBITEM*)SendMessage(hListWin, LB_GETITEMDATA, i, 0);
  39. if (pItem && pItem->bRTF)
  40. {
  41. DEBUGMSG("MYLB show RTF for item %S", pItem->szTitle);
  42. PostMessage(GetParent(hDlg), AUMSG_SHOW_RTF, LOWORD(pItem->m_index), 0);
  43. }
  44. }
  45. }
  46. ////////////////////////////////////////////////////////////////////////////////
  47. // Overwrite hListWin's accessibility behavior using dynamic annotation server
  48. ////////////////////////////////////////////////////////////////////////////////
  49. void SetMYLBAcc(HWND hListWin)
  50. {
  51. IAccPropServices * pAccPropSvc = NULL;
  52. HRESULT hr = CoCreateInstance(CLSID_AccPropServices,
  53. NULL,
  54. CLSCTX_INPROC_SERVER,
  55. IID_IAccPropServices,
  56. (void **) &pAccPropSvc);
  57. if( hr == S_OK && pAccPropSvc )
  58. {
  59. MYLBAccPropServer* pMYLBPropSrv = new MYLBAccPropServer( pAccPropSvc );
  60. if( pMYLBPropSrv )
  61. {
  62. MSAAPROPID propids[4];
  63. propids[0] = PROPID_ACC_NAME;
  64. propids[1] = PROPID_ACC_STATE;
  65. propids[2] = PROPID_ACC_ROLE;
  66. propids[3] = PROPID_ACC_DESCRIPTION;
  67. pAccPropSvc->SetHwndPropServer( hListWin, OBJID_CLIENT, 0, propids, 4, pMYLBPropSrv, ANNO_CONTAINER);
  68. pMYLBPropSrv->Release();
  69. }
  70. pAccPropSvc->Release();
  71. }
  72. else
  73. {
  74. DEBUGMSG("WANRING: WUAUCLT Fail to create object AccPropServices with error %#lx", hr);
  75. }
  76. // Mark the listbox so that the server can tell if it alive
  77. SetProp(hListWin, MYLBALIVEPROP, (HANDLE)TRUE);
  78. }
  79. /*void DumpRect(LPCTSTR tszName, RECT rc)
  80. {
  81. DEBUGMSG("DumpRect %S at (%d, %d, %d, %d)", tszName, rc.left, rc.top, rc.right, rc.bottom);
  82. }
  83. */
  84. void DrawItem(LPDRAWITEMSTRUCT lpdis, BOOL fSelectionDisabled)
  85. {
  86. LRESULT lResult = SendMessage(lpdis->hwndItem, LB_GETITEMDATA, lpdis->itemID, 0);
  87. if (LB_ERR == lResult)
  88. {
  89. return;
  90. }
  91. LBITEM * plbi = (LBITEM*) lResult;
  92. CalcItemLocation(lpdis->hDC, plbi, lpdis->rcItem);
  93. // Draw the title of the item
  94. DrawTitle(lpdis->hDC, plbi, plbi->rcTitle);
  95. // Draw the text of the item
  96. DrawDescription(lpdis->hDC, plbi, plbi->rcText);
  97. // Draw the bitmap
  98. DrawBitmap(lpdis->hDC, plbi, plbi->rcBitmap, plbi->bSelect, fSelectionDisabled);
  99. // draw the Read this First
  100. DrawRTF(lpdis->hDC, plbi, plbi->rcRTF);
  101. }
  102. BOOL CurItemHasRTF(HWND hListWin)
  103. {
  104. int i = (LONG)SendMessage(hListWin, LB_GETCURSEL, 0, 0);
  105. if (LB_ERR == i)
  106. {
  107. return FALSE;
  108. }
  109. LBITEM *pItem = (LBITEM*)SendMessage(hListWin, LB_GETITEMDATA, (WPARAM)i, 0);
  110. return pItem->bRTF;
  111. }
  112. BOOL fDisableSelection(void)
  113. {
  114. AUOPTION auopt;
  115. if (SUCCEEDED(gInternals->m_getServiceOption(&auopt))
  116. && auopt.fDomainPolicy && AUOPTION_SCHEDULED == auopt.dwOption)
  117. {
  118. return TRUE;
  119. }
  120. return FALSE;
  121. }
  122. void ToggleSelection(HWND hDlg, HWND hListWin, LBITEM *pItem)
  123. {
  124. //DEBUGMSG("ToggleSelection()");
  125. if (NULL == hDlg || NULL == hListWin || NULL == pItem || pItem->m_index >= gInternals->m_ItemList.Count())
  126. {
  127. AUASSERT(FALSE); //should never reach here.
  128. return;
  129. }
  130. HDC hDC = GetDC(hListWin);
  131. if (NULL == hDC)
  132. {
  133. return;
  134. }
  135. pItem->bSelect = !pItem->bSelect;
  136. DrawBitmap(hDC, pItem, pItem->rcBitmap, pItem->bSelect, FALSE); //obviously selection is allowed
  137. #ifndef TESTUI
  138. gInternals->m_ItemList[pItem->m_index].SetStatus(pItem->bSelect ? AUCATITEM_SELECTED : AUCATITEM_UNSELECTED);
  139. #endif
  140. PostMessage(GetParent(hDlg), AUMSG_SELECTION_CHANGED, 0, 0);
  141. ReleaseDC(hListWin, hDC);
  142. }
  143. void RedrawMYLB(HWND hwndLB)
  144. {
  145. //DEBUGMSG("REDRAW MYLB ");
  146. InvalidateRect(ghWndList, NULL, TRUE);
  147. UpdateWindow(ghWndList);
  148. }
  149. void CalcTitleFocusRect(const RECT &rcIn, RECT & rcOut)
  150. {
  151. rcOut = rcIn;
  152. rcOut.right -= TITLE_MARGIN * 2/3;
  153. rcOut.top += SECTION_SPACING * 2/3;
  154. rcOut.bottom -= SECTION_SPACING*2/3 ;
  155. }
  156. void CalcRTFFocusRect(const RECT &rcIn, RECT & rcOut)
  157. {
  158. rcOut = rcIn;
  159. rcOut.left -=3;
  160. rcOut.right +=3;
  161. rcOut.top -= 2;
  162. rcOut.bottom += 2;
  163. }
  164. void DrawMYLBFocus(HWND hListWin, LPDRAWITEMSTRUCT lpdis, MYLBFOCUS enCurFocus, INT nCurFocusId)
  165. {
  166. LBITEM * pItem;
  167. LRESULT lResult;
  168. //DEBUGMSG("DrawMYLBFocus for current focus %d with Item %d", enCurFocus, nCurFocusId);
  169. RECT rcNew;
  170. if (nCurFocusId != lpdis->itemID)
  171. {
  172. return;
  173. }
  174. if (GetFocus() != ghWndList )
  175. {
  176. // DEBUGMSG("CustomLB doesn't have focus");
  177. return;
  178. }
  179. lResult = SendMessage(hListWin, LB_GETITEMDATA, lpdis->itemID, 0);
  180. if (LB_ERR == lResult)
  181. {
  182. DEBUGMSG("DrawMYLBFocus() fail to get item data");
  183. goto done;
  184. }
  185. pItem = (LBITEM*) lResult;
  186. if (!EqualRect(&lpdis->rcItem, &pItem->rcItem))
  187. {
  188. CalcItemLocation(lpdis->hDC, pItem, lpdis->rcItem);
  189. }
  190. if (enCurFocus == MYLB_FOCUS_RTF)
  191. {
  192. CalcRTFFocusRect(pItem->rcRTF, rcNew);
  193. }
  194. if (enCurFocus == MYLB_FOCUS_TITLE)
  195. {
  196. CalcTitleFocusRect(pItem->rcTitle, rcNew);
  197. }
  198. DrawFocusRect(lpdis->hDC, &rcNew); //set new focus rect
  199. done:
  200. return;
  201. }
  202. LRESULT CallDefLBWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  203. {
  204. static WNDPROC s_defLBWndProc = NULL;
  205. if (NULL == s_defLBWndProc)
  206. {
  207. s_defLBWndProc = (WNDPROC) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  208. }
  209. return CallWindowProc(s_defLBWndProc, hWnd, message, wParam, lParam);
  210. }
  211. LRESULT CALLBACK newLBWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  212. {
  213. switch (message)
  214. {
  215. case WM_GETDLGCODE:
  216. return DLGC_WANTALLKEYS;
  217. case WM_KEYDOWN:
  218. switch(wParam)
  219. {
  220. case VK_RIGHT:
  221. case VK_LEFT:
  222. if (MYLB_FOCUS_RTF == gFocus)
  223. {
  224. DEBUGMSG("LB change focus to Title");
  225. gFocus = MYLB_FOCUS_TITLE;
  226. RedrawMYLB(ghWndList);
  227. }
  228. else if (MYLB_FOCUS_TITLE == gFocus && CurItemHasRTF(hWnd))
  229. {
  230. DEBUGMSG("LB change focus to RTF");
  231. gFocus = MYLB_FOCUS_RTF;
  232. RedrawMYLB(ghWndList);
  233. }
  234. break;
  235. case VK_F1:
  236. if (GetKeyState(VK_SHIFT)<0)
  237. {//SHIFT down
  238. LaunchRTF(hWnd);
  239. return 0;
  240. }
  241. break;
  242. case VK_RETURN:
  243. if (MYLB_FOCUS_RTF == gFocus)
  244. {
  245. DEBUGMSG("MYLB show RTF ");
  246. LaunchRTF(hWnd);
  247. }
  248. break;
  249. case VK_TAB:
  250. PostMessage(GetParent(hWnd), WM_NEXTDLGCTL, 0, 0L);
  251. break;
  252. default:
  253. return CallDefLBWndProc(hWnd, message, wParam, lParam);
  254. }
  255. return 0;
  256. case WM_KEYUP:
  257. switch(wParam)
  258. {
  259. case VK_RIGHT:
  260. case VK_LEFT:
  261. break;
  262. case VK_RETURN:
  263. break;
  264. default:
  265. return CallDefLBWndProc(hWnd, message, wParam, lParam);
  266. }
  267. return 0;
  268. default:
  269. break;
  270. }
  271. return CallDefLBWndProc(hWnd, message, wParam, lParam);
  272. }
  273. // Message handler for Custom List box.
  274. LRESULT CALLBACK CustomLBWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  275. {
  276. static int lenx;
  277. int clb;
  278. LBITEM *item;
  279. static BOOL s_fSelectionDisabled;
  280. switch (message)
  281. {
  282. case WM_CREATE:
  283. {
  284. RECT rcLst, rcDlg;
  285. LOGFONT lf;
  286. HFONT parentFont;
  287. TCHAR tszRTF[MAX_RTF_LENGTH] = _T("");
  288. GetClientRect(hDlg, &rcDlg);
  289. rcDlg.top += 2;
  290. rcDlg.bottom -= 3;
  291. rcDlg.left += 2;
  292. rcDlg.right -= 2;
  293. s_fSelectionDisabled = fDisableSelection();
  294. ghWndList = CreateWindow(_T("listbox"), NULL,
  295. WS_CHILD | WS_VISIBLE | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE |
  296. LBS_NOINTEGRALHEIGHT | LBS_HASSTRINGS | LBS_WANTKEYBOARDINPUT |
  297. WS_VSCROLL | WS_HSCROLL | WS_TABSTOP,
  298. rcDlg.left, rcDlg.top, rcDlg.right - rcDlg.left, rcDlg.bottom - rcDlg.top,
  299. hDlg, NULL, ghInstance, NULL);
  300. if (NULL == ghWndList)
  301. {
  302. return -1;
  303. }
  304. WNDPROC defLBWndProc = (WNDPROC) GetWindowLongPtr(ghWndList, GWLP_WNDPROC);
  305. SetWindowLongPtr(ghWndList, GWLP_USERDATA, (LONG_PTR) defLBWndProc);
  306. SetWindowLongPtr(ghWndList, GWLP_WNDPROC, (LONG_PTR) newLBWndProc);
  307. HDC hDC = GetDC(ghWndList);
  308. GetWindowRect(hDlg, &rcDlg);
  309. GetWindowRect(ghWndList, &rcLst);
  310. lenx = rcLst.right - rcLst.left;
  311. // Load read this first text from resource file
  312. LoadString(ghInstance, IDS_READTHISFIRST, tszRTF, MAX_RTF_LENGTH);
  313. // load keyboard shortcut description for Read this First
  314. LoadString(ghInstance, IDS_RTFSHORTCUT, gtszRTFShortcut, MAX_RTFSHORTCUTDESC_LENGTH);
  315. // Load the bitmaps
  316. ghBmpClear = (HBITMAP)LoadImage(ghInstance, MAKEINTRESOURCE(IDB_CLEAR), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS | LR_CREATEDIBSECTION);
  317. ghBmpCheck = (HBITMAP)LoadImage(ghInstance, MAKEINTRESOURCE(IDB_CHECK), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS | LR_CREATEDIBSECTION);
  318. ghBmpGrayOut = (HBITMAP)LoadImage(ghInstance, MAKEINTRESOURCE(IDB_GRAYOUT), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS | LR_CREATEDIBSECTION);
  319. // Create BOLD and Italic fonts
  320. ZeroMemory(&lf, sizeof(lf));
  321. //fixcode: check return value of GetCurrentObject()
  322. GetObject(GetCurrentObject(hDC, OBJ_FONT), sizeof(lf), &lf);
  323. //fixcode: check return value of GetParent()
  324. parentFont = (HFONT)SendMessage(GetParent(hDlg), WM_GETFONT, 0, 0);
  325. SendMessage(hDlg, WM_SETFONT, (WPARAM)parentFont, FALSE);
  326. SelectObject(hDC, parentFont);
  327. //fixcode: check return value of GetCurrentObject()
  328. GetObject(GetCurrentObject(hDC, OBJ_FONT), sizeof(lf), &lf);
  329. lf.lfUnderline = TRUE;
  330. lf.lfWeight = FW_NORMAL;
  331. //fixcode: check return value of CreateFontIndirect()
  332. ghFontUnderline = CreateFontIndirect(&lf);
  333. lf.lfUnderline = FALSE;
  334. lf.lfWeight = FW_NORMAL;
  335. //fixcode: check return value of CreateFontIndirect()
  336. ghFontNormal = CreateFontIndirect(&lf);
  337. lf.lfUnderline = FALSE;
  338. lf.lfWeight = FW_HEAVY;
  339. //fixcode: check return value of CreateFontIndirect()
  340. ghFontBold = CreateFontIndirect(&lf);
  341. ReleaseDC(ghWndList, hDC);
  342. #ifdef TESTUI
  343. {
  344. AddItem(_T("Test 1 Very long title Test 1 Very long title Test 1 Very long title Test 1 Very long title "),
  345. _T("Description"), tszRTF, 0, TRUE, TRUE);
  346. AddItem(_T("Test 2"), _T("Another description. No RTF"), tszRTF,0, TRUE, FALSE);
  347. }
  348. #else
  349. {
  350. for (UINT i = 0; i < gInternals->m_ItemList.Count(); i++)
  351. {
  352. DEBUGMSG("selected[%d] = %lu", i, gInternals->m_ItemList[i].dwStatus());
  353. if ( !gInternals->m_ItemList[i].fHidden() )
  354. {
  355. AddItem(gInternals->m_ItemList[i].bstrTitle(),
  356. gInternals->m_ItemList[i].bstrDescription(),
  357. tszRTF,
  358. i,
  359. gInternals->m_ItemList[i].fSelected(),
  360. IsRTFDownloaded(gInternals->m_ItemList[i].bstrRTFPath(), GetSystemDefaultLangID()));
  361. }
  362. }
  363. }
  364. #endif
  365. SendMessage(ghWndList, LB_SETCURSEL, 0, 0);
  366. gFocus = MYLB_FOCUS_TITLE;
  367. gFocusItemId = 0;
  368. SetMYLBAcc(ghWndList);
  369. return 0;
  370. }
  371. case WM_MOVE:
  372. {
  373. RECT rcList;
  374. GetWindowRect(ghWndList, &rcList); // need this to force LB to realize it got moved
  375. return(TRUE);
  376. }
  377. case WM_SETCURSOR:
  378. {
  379. if (ghWndList == (HWND)wParam && LOWORD(lParam) == HTCLIENT && HIWORD(lParam) == WM_MOUSEMOVE)
  380. {
  381. POINT pt;
  382. RECT rc;
  383. GetCursorPos(&pt);
  384. if (0 == MapWindowPoints(NULL, ghWndList, &pt, 1))
  385. {
  386. DEBUGMSG("MYLBWndProc MapWindowPoints failed");
  387. return FALSE;
  388. }
  389. DWORD dwPos;
  390. dwPos = MAKELONG( pt.x, pt.y);
  391. DWORD dwItem = (LONG)SendMessage(ghWndList, LB_ITEMFROMPOINT, 0, dwPos);
  392. if (LOWORD(dwItem) == -1)
  393. return(FALSE);
  394. item = (LBITEM*)SendMessage(ghWndList, LB_GETITEMDATA, LOWORD(dwItem), 0);
  395. SendMessage(ghWndList, LB_GETITEMRECT, LOWORD(dwItem), (LPARAM)&rc);
  396. if (!EqualRect(&rc, &item->rcItem))
  397. {
  398. HDC hDC = GetDC(ghWndList);
  399. CalcItemLocation(hDC, item, rc);
  400. ReleaseDC(ghWndList, hDC);
  401. }
  402. if (item->bRTF && PtInRect(&item->rcRTF, pt))
  403. {
  404. // DEBUGMSG("Change Cursor to hand in MOUSEMOVE");
  405. SetCursor(ghCursorHand);
  406. return TRUE;
  407. }
  408. return FALSE;
  409. }
  410. else
  411. if (ghWndList == (HWND)wParam && LOWORD(lParam) == HTCLIENT && HIWORD(lParam) == WM_LBUTTONDOWN)
  412. {
  413. POINT pt;
  414. RECT rc;
  415. GetCursorPos(&pt);
  416. if (0 == MapWindowPoints(NULL, ghWndList, &pt, 1))
  417. {
  418. DEBUGMSG("MYLBWndProc MapWindowPoints failed");
  419. return FALSE;
  420. }
  421. DWORD dwPos;
  422. dwPos = MAKELONG( pt.x, pt.y);
  423. DWORD dwItem = (LONG)SendMessage(ghWndList, LB_ITEMFROMPOINT, 0, dwPos);
  424. if (LOWORD(dwItem) == -1)
  425. return(FALSE);
  426. item = (LBITEM*)SendMessage(ghWndList, LB_GETITEMDATA, LOWORD(dwItem), 0);
  427. SendMessage(ghWndList, LB_GETITEMRECT, LOWORD(dwItem), (LPARAM)&rc);
  428. if (!EqualRect(&rc, &item->rcItem))
  429. {
  430. HDC hDC = GetDC(ghWndList);
  431. CalcItemLocation(hDC, item, rc);
  432. ReleaseDC(ghWndList, hDC);
  433. }
  434. // Are we clicking on the Title?
  435. if (PtInRect(&item->rcBitmap, pt))
  436. {
  437. if (!s_fSelectionDisabled)
  438. {
  439. ToggleSelection(hDlg, ghWndList, item);
  440. }
  441. // DEBUGMSG("WM_SETCURSOR change gFocus to TITLE");
  442. gFocus = MYLB_FOCUS_TITLE;
  443. gFocusItemId = dwItem;
  444. RedrawMYLB(ghWndList);
  445. return TRUE;
  446. }
  447. // or are we clicking on the RTF?
  448. if (item->bRTF && PtInRect(&item->rcRTF, pt))
  449. {
  450. PostMessage(GetParent(hDlg), AUMSG_SHOW_RTF, LOWORD(item->m_index), 0);
  451. SetCursor(ghCursorHand);
  452. //DEBUGMSG("WM_SETCURSOR change gFocus to RTF");
  453. gFocus = MYLB_FOCUS_RTF;
  454. gFocusItemId = dwItem;
  455. RedrawMYLB(ghWndList);
  456. return TRUE;
  457. }
  458. return FALSE;
  459. }
  460. return FALSE;
  461. }
  462. case WM_MEASUREITEM:
  463. {
  464. LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam ;
  465. HDC hdc = GetDC(ghWndList);
  466. LBITEM * plbi = (LBITEM*)lpmis->itemData;
  467. lpmis->itemHeight = CalcTitleHeight(hdc, plbi, lenx - XBITMAP - 2* TITLE_MARGIN)
  468. + CalcDescHeight(hdc, plbi, lenx - XBITMAP )
  469. + CalcRTFHeight(hdc, plbi) + 4 * SECTION_SPACING;
  470. ReleaseDC(ghWndList, hdc);
  471. return TRUE;
  472. }
  473. case WM_PAINT:
  474. PAINTSTRUCT ps;
  475. RECT borderRect;
  476. BeginPaint(hDlg, &ps);
  477. GetClientRect(hDlg, &borderRect);
  478. DrawEdge(ps.hdc, &borderRect, EDGE_ETCHED, BF_RECT);
  479. EndPaint(hDlg, &ps);
  480. break;
  481. case WM_NEXTDLGCTL:
  482. PostMessage(GetParent(hDlg), WM_NEXTDLGCTL, 0, 0L);
  483. return 0;
  484. case WM_KEYUP:
  485. //DEBUGMSG("MYLB got KEYUP key %d", wParam);
  486. switch(wParam)
  487. {
  488. case VK_TAB:
  489. case VK_DOWN:
  490. case VK_UP:
  491. SetFocus(ghWndList);
  492. return 0;
  493. default:
  494. break;
  495. }
  496. break;
  497. case WM_VKEYTOITEM:
  498. {
  499. //DEBUGMSG("WM_VKEYTOITEM got char %d", LOWORD(wParam));
  500. if (LOWORD(wParam) != VK_SPACE)
  501. {
  502. return -1;
  503. }
  504. if (MYLB_FOCUS_TITLE == gFocus)
  505. {
  506. int i = (LONG)SendMessage(ghWndList, LB_GETCURSEL, 0, 0);
  507. if (LB_ERR == i)
  508. {
  509. return -2;
  510. }
  511. item = (LBITEM*)SendMessage(ghWndList, LB_GETITEMDATA, i, 0);
  512. if (!s_fSelectionDisabled)
  513. {
  514. ToggleSelection(hDlg, ghWndList, item);
  515. }
  516. return -2;
  517. }
  518. if (MYLB_FOCUS_RTF == gFocus)
  519. {
  520. LaunchRTF(ghWndList);
  521. }
  522. return -2;
  523. }
  524. case WM_DRAWITEM:
  525. {
  526. LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
  527. // If there are no list box items, skip this message.
  528. if (lpdis->itemID == -1)
  529. {
  530. break;
  531. }
  532. // Draw the bitmap and text for the list box item. Draw a
  533. // rectangle around the bitmap if it is selected.
  534. switch (lpdis->itemAction)
  535. {
  536. case ODA_SELECT:
  537. case ODA_DRAWENTIRE:
  538. //DEBUGMSG("MYLB WM_DRAWITEM ODA_DRAWENTIRE for %d", lpdis->itemID);
  539. DrawItem(lpdis, s_fSelectionDisabled);
  540. DrawMYLBFocus(ghWndList, lpdis, gFocus, gFocusItemId);
  541. break;
  542. case ODA_FOCUS:
  543. if (lpdis->itemID != gFocusItemId)
  544. {
  545. gFocusItemId = lpdis->itemID;
  546. gFocus = MYLB_FOCUS_TITLE;
  547. }
  548. //DEBUGMSG("MYLB ODA_FOCUS change focus to %d", gFocusItemId);
  549. DrawItem(lpdis, s_fSelectionDisabled);
  550. DrawMYLBFocus(ghWndList, lpdis, gFocus, gFocusItemId);
  551. break;
  552. }
  553. return TRUE;
  554. }
  555. case WM_DESTROY:
  556. // need to cleanup the fonts
  557. if (ghFontBold)
  558. DeleteObject(ghFontBold);
  559. if (ghFontUnderline)
  560. DeleteObject(ghFontUnderline);
  561. if (ghFontNormal)
  562. DeleteObject(ghFontNormal);
  563. if (ghBmpCheck)
  564. DeleteObject(ghBmpCheck);
  565. if (ghBmpGrayOut)
  566. DeleteObject(ghBmpGrayOut);
  567. if (ghBmpClear)
  568. DeleteObject(ghBmpClear);
  569. ghFontNormal = NULL;
  570. ghFontBold = NULL;
  571. ghFontUnderline = NULL;
  572. ghBmpCheck = NULL;
  573. ghBmpGrayOut = NULL;
  574. ghBmpClear = NULL;
  575. EnterCriticalSection(&gcsClient);
  576. RemoveProp( ghWndList, MYLBALIVEPROP );
  577. clb = (LONG)SendMessage(ghWndList, LB_GETCOUNT, 0, 0);
  578. for(int i = 0; i < clb; i++)
  579. {
  580. item = (LBITEM*)SendMessage(ghWndList, LB_GETITEMDATA, i, 0);
  581. delete(item);
  582. }
  583. LeaveCriticalSection(&gcsClient);
  584. return 0;
  585. }
  586. return DefWindowProc(hDlg, message, wParam, lParam);
  587. }
  588. void DrawTitle(HDC hDC, LBITEM * plbi, RECT rc)
  589. {
  590. // we want the bitmap to be on the same background as the title, let's do this here since we
  591. // already have all the measures.
  592. RECT rcTop = rc;
  593. rcTop.left = 0;
  594. // draw menu background rectangle for the title and bitmap
  595. HBRUSH hBrush;
  596. if (! (hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU))))
  597. {
  598. DEBUGMSG("WUAUCLT CreateSolidBrush failure in DrawTitle, GetLastError=%lu", GetLastError());
  599. return;
  600. }
  601. FillRect(hDC, (LPRECT)&rcTop, hBrush);
  602. if (NULL != hBrush)
  603. {
  604. DeleteObject(hBrush);
  605. }
  606. // draw 3d look
  607. DrawEdge(hDC, &rcTop, EDGE_ETCHED, BF_RECT);
  608. // change text and back ground color of list box's selection
  609. DWORD dwOldTextColor = SetTextColor(hDC, GetSysColor(COLOR_MENUTEXT)); // black text color
  610. DWORD dwOldBkColor = SetBkColor(hDC, GetSysColor(COLOR_MENU)); // text cell light gray background
  611. HFONT hFontPrev = (HFONT)SelectObject(hDC, ghFontBold);
  612. rc.left += TITLE_MARGIN;
  613. rc.top += SECTION_SPACING;
  614. rc.right -= TITLE_MARGIN;
  615. rc.bottom -= SECTION_SPACING;
  616. DrawText(hDC, (LPTSTR)plbi->szTitle, -1,
  617. &rc, DT_WORDBREAK);
  618. // restore text and back ground color of list box's selection
  619. SetTextColor(hDC, dwOldTextColor);
  620. SetBkColor(hDC, dwOldBkColor);
  621. SelectObject(hDC, hFontPrev);
  622. return;
  623. }
  624. void DrawRTF(HDC hDC, LBITEM * plbi, const RECT & rc /*,BOOL fHit*/)
  625. {
  626. if (!plbi->bRTF)
  627. return;
  628. //draw RTF background
  629. RECT rcBackGround;
  630. CalcRTFFocusRect(rc, rcBackGround);
  631. HBRUSH hBrush;
  632. if (!(hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW))))
  633. {
  634. DEBUGMSG("WUAUCLT CreateSolidBrush failure in DrawRTF, GetLastError=%lu", GetLastError());
  635. return;
  636. }
  637. if (!FillRect(hDC, (LPRECT)&rcBackGround, hBrush))
  638. {
  639. DEBUGMSG("Fail to erase RTF background");
  640. }
  641. if (NULL != hBrush)
  642. {
  643. DeleteObject(hBrush);
  644. }
  645. HFONT hFontPrev = (HFONT) SelectObject(hDC, ghFontUnderline);
  646. DWORD dwOldTextColor = SetTextColor(hDC, GetSysColor(ATTENTION_COLOR));
  647. SetBkMode(hDC, TRANSPARENT);
  648. // add the read this first
  649. TextOut(hDC, (int)(rc.left), (int)(rc.top),
  650. (LPTSTR)plbi->szRTF, lstrlen(plbi->szRTF));
  651. // restore text and back ground color of list box's selection
  652. SetTextColor(hDC, dwOldTextColor);
  653. SelectObject(hDC, hFontPrev);
  654. return;
  655. }
  656. void DrawDescription(HDC hDC, LBITEM * plbi, RECT & rc)
  657. {
  658. HFONT hFontPrev = (HFONT)SelectObject(hDC, ghFontNormal);
  659. DrawText(hDC, (LPTSTR)plbi->pszDescription, -1,
  660. &rc, DT_BOTTOM | DT_EXPANDTABS | DT_WORDBREAK | DT_EDITCONTROL);
  661. SelectObject(hDC, hFontPrev);
  662. return;
  663. }
  664. void DrawBitmap(HDC hDC, LBITEM * plbi, const RECT & rc, BOOL fSel, BOOL fSelectionDisabled)
  665. {
  666. HDC hdcMem;
  667. plbi->bSelect = fSel;
  668. if (hdcMem = CreateCompatibleDC(hDC))
  669. {
  670. HGDIOBJ hBmp;
  671. if (fSelectionDisabled)
  672. {
  673. hBmp = ghBmpGrayOut;
  674. // DEBUGMSG("Set bitmap to grayout");
  675. }
  676. else
  677. {
  678. // DEBUGMSG("Set bitmap to selectable");
  679. hBmp = (plbi->bSelect ? ghBmpCheck : ghBmpClear);
  680. }
  681. HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, hBmp);
  682. BitBlt(hDC,
  683. rc.left + 3, rc.top + SECTION_SPACING,
  684. rc.right - rc.left,
  685. rc.bottom - rc.top,
  686. hdcMem, 0, 0, SRCCOPY);
  687. SelectObject(hdcMem, hbmpOld);
  688. DeleteDC(hdcMem);
  689. }
  690. }
  691. BOOL GetBmpSize(HANDLE hBmp, SIZE *psz)
  692. {
  693. if (NULL == hBmp || NULL == psz)
  694. {
  695. DEBUGMSG("Error: GetBmpSize() invalid parameter");
  696. return FALSE;
  697. }
  698. BITMAP bm;
  699. ZeroMemory(&bm, sizeof(bm));
  700. if (0 == GetObject(hBmp, sizeof(bm), &bm))
  701. {
  702. return FALSE;
  703. }
  704. psz->cx = bm.bmWidth;
  705. psz->cy = bm.bmHeight;
  706. return TRUE;
  707. }
  708. //fixcode: should return error code
  709. void AddItem(LPTSTR tszTitle, LPTSTR tszDesc, LPTSTR tszRTF, int index, BOOL fSelected, BOOL fRTF)
  710. {
  711. LBITEM *newItem = new(LBITEM);
  712. if (! newItem)
  713. {
  714. DEBUGMSG("WUAUCLT new() failed in AddItem, GetLastError=%lu", GetLastError());
  715. goto Failed;
  716. }
  717. DWORD dwDescLen = max(lstrlen(tszDesc), MAX_DESC_LENGTH);
  718. newItem->pszDescription = (LPTSTR) malloc((dwDescLen+1) * sizeof(TCHAR));
  719. if (NULL == newItem->pszDescription)
  720. {
  721. DEBUGMSG("AddItem() fail to alloc memory for description");
  722. goto Failed;
  723. }
  724. (void)StringCchCopyEx(newItem->szTitle, ARRAYSIZE(newItem->szTitle), tszTitle, NULL, NULL, MISTSAFE_STRING_FLAGS);
  725. (void)StringCchCopyEx(newItem->pszDescription, dwDescLen+1, tszDesc, NULL, NULL, MISTSAFE_STRING_FLAGS);
  726. (void)StringCchCopyEx(newItem->szRTF, ARRAYSIZE(newItem->szRTF), tszRTF, NULL, NULL, MISTSAFE_STRING_FLAGS);
  727. newItem->m_index = index;
  728. newItem->bSelect = fSelected;
  729. newItem->bRTF = fRTF;
  730. LRESULT i = SendMessage(ghWndList, LB_GETCOUNT, 0, 0);
  731. if (LB_ERR == i ||
  732. LB_ERR == (i = SendMessage(ghWndList, LB_INSERTSTRING, (WPARAM) i, (LPARAM) newItem->szTitle)) ||
  733. LB_ERRSPACE == i ||
  734. LB_ERR == SendMessage(ghWndList, LB_SETITEMDATA, (WPARAM) i, (LPARAM) newItem))
  735. {
  736. DEBUGMSG("WUAUCLT AddItem() fail to add item to listbox");
  737. goto Failed;
  738. }
  739. return;
  740. Failed:
  741. SafeDelete(newItem);
  742. QuitNRemind(TIMEOUT_INX_TOMORROW);
  743. }
  744. ////////////////////////////////////////////////////
  745. // utility function
  746. // calculate the height of a paragraph in current
  747. // device context
  748. ////////////////////////////////////////////////////
  749. UINT GetParagraphHeight(HDC hDC, LPTSTR tszPara, UINT uLineWidth)
  750. {
  751. UINT y = 0;
  752. TCHAR* pEOL;
  753. SIZE sz;
  754. if (0 == uLineWidth)
  755. {
  756. return 0;
  757. }
  758. TCHAR* pLast = tszPara;
  759. while(pEOL = _tcschr(pLast, _T('\n')))
  760. {
  761. *pEOL = _T('\0');
  762. //fixcode: check return value of GetTextExtentPoint32()
  763. GetTextExtentPoint32(hDC, pLast, lstrlen(pLast), &sz);
  764. *pEOL = _T('\n');
  765. pLast = _tcsinc(pEOL);
  766. y += sz.cy * ((sz.cx / (uLineWidth)) + 1);
  767. }
  768. //fixcode: check return value of GetTextExtentPoint32()
  769. GetTextExtentPoint32(hDC, pLast, lstrlen(pLast), &sz);
  770. y += sz.cy * ((sz.cx / (uLineWidth)) + 1);
  771. return y;
  772. }
  773. int CalcDescHeight(HDC hDC, LBITEM * plbi, int cx)
  774. {
  775. TCHAR* pEOL = NULL;
  776. TCHAR* pLast = NULL;
  777. int y = 0;
  778. HFONT hPrevFont = NULL;
  779. if (NULL == plbi)
  780. {
  781. DEBUGMSG("CalcDescHeight() invalid parameter");
  782. return 0;
  783. }
  784. hPrevFont = (HFONT) SelectObject(hDC, ghFontNormal);
  785. y = GetParagraphHeight(hDC, plbi->pszDescription, cx);
  786. SelectObject(hDC, hPrevFont);
  787. return y;
  788. }
  789. int CalcRTFHeight(HDC hDC, LBITEM * plbi)
  790. {
  791. SIZE sz ;
  792. if (NULL == plbi)
  793. {
  794. DEBUGMSG("CalcRTFHeight() invalid parameter");
  795. return 0;
  796. }
  797. ZeroMemory(&sz, sizeof(sz));
  798. HFONT hPrevFont = (HFONT) SelectObject(hDC, ghFontUnderline);
  799. //fixcode: check return value of GetTextExtentPoint32()
  800. GetTextExtentPoint32(hDC, plbi->szRTF, lstrlen(plbi->szRTF), &sz);
  801. SelectObject(hDC, hPrevFont);
  802. return sz.cy;
  803. }
  804. int CalcRTFWidth(HDC hDC, LBITEM * plbi)
  805. {
  806. if (NULL == plbi)
  807. {
  808. DEBUGMSG("CalcRTFWidth() invalid parameter");
  809. return 0;
  810. }
  811. SIZE sz;
  812. HFONT hPrevFont = (HFONT) SelectObject(hDC, ghFontUnderline);
  813. //fixcode: check return value of GetTextExtentPoint32()
  814. GetTextExtentPoint32(hDC, plbi->szRTF, lstrlen(plbi->szRTF), &sz);
  815. SelectObject(hDC, hPrevFont);
  816. return sz.cx;
  817. }
  818. int CalcTitleHeight(HDC hDC, LBITEM *plbi, int cx)
  819. {
  820. INT y = 0;
  821. INT iBmpHeight = 0;
  822. if (NULL == plbi)
  823. {
  824. DEBUGMSG("CalcTitleHeight() invalid parameter");
  825. goto done;
  826. }
  827. HFONT hPrevFont = (HFONT) SelectObject(hDC, ghFontBold);
  828. y = GetParagraphHeight(hDC, plbi->szTitle, cx);
  829. SelectObject(hDC, hPrevFont);
  830. // get checkbox size
  831. if (NULL != ghBmpCheck && NULL != ghBmpClear && NULL != ghBmpGrayOut)
  832. {
  833. SIZE sz1 ;
  834. SIZE sz2 ;
  835. SIZE sz3 ;
  836. sz1.cy = sz2.cy = sz3.cy = DEF_CHECK_HEIGHT;
  837. GetBmpSize(ghBmpCheck, &sz1);
  838. GetBmpSize(ghBmpClear, &sz2);
  839. GetBmpSize(ghBmpGrayOut, &sz3);
  840. iBmpHeight = max(sz1.cy, sz2.cy);
  841. iBmpHeight = max(iBmpHeight, sz3.cy);
  842. }
  843. done:
  844. return max(y, iBmpHeight); //make title height a little bigger for clearer focus rect
  845. }
  846. ////////////////////////////////////////////////////////////
  847. /// Layout of listbox item:
  848. /// spacing
  849. /// bitmap margin TITLE margin
  850. /// spacing
  851. /// DESCRIPTION
  852. /// spacing
  853. /// RTF rtf_margin
  854. /// spacing
  855. ///////////////////////////////////////////////////////////
  856. void CalcItemLocation(HDC hDC, LBITEM * plbi, const RECT & rc)
  857. {
  858. // Calculate the positon of each element
  859. plbi->rcItem = rc;
  860. plbi->rcTitle = rc;
  861. plbi->rcTitle.left += XBITMAP ;
  862. plbi->rcTitle.bottom = plbi->rcTitle.top + CalcTitleHeight(hDC, plbi, plbi->rcTitle.right - plbi->rcTitle.left - 2* TITLE_MARGIN)
  863. + 2 * SECTION_SPACING;
  864. plbi->rcText = rc;
  865. plbi->rcText.left = plbi->rcTitle.left;
  866. plbi->rcText.right = plbi->rcTitle.right;
  867. plbi->rcText.top = plbi->rcTitle.bottom;
  868. plbi->rcText.bottom -= CalcRTFHeight(hDC, plbi) + SECTION_SPACING; //
  869. plbi->rcRTF = plbi->rcText;
  870. plbi->rcRTF.top = plbi->rcText.bottom;
  871. plbi->rcRTF.bottom = plbi->rcRTF.top + CalcRTFHeight(hDC, plbi);
  872. plbi->rcRTF.right = plbi->rcText.right - RTF_MARGIN;
  873. plbi->rcRTF.left = plbi->rcRTF.right - CalcRTFWidth(hDC, plbi);
  874. plbi->rcBitmap = rc;
  875. plbi->rcBitmap.bottom = plbi->rcTitle.bottom;
  876. return;
  877. }