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.

591 lines
16 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: tasksym.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "tasks.h"
  12. #include "stgio.h"
  13. #include <commdlg.h>
  14. #include "symbinfo.h"
  15. #include "pickicon.h"
  16. #include "util.h"
  17. const int NUM_SYMBOLS = (sizeof(s_rgEOTSymbol)/sizeof(s_rgEOTSymbol[0]));
  18. static const int s_cxIcon = 32; // size of an icon
  19. static const int s_cxSelectionMargin = 4; // additional border for selection
  20. static const int s_cxIconGutter = 10; // gutter space between icons (keep this even)
  21. //############################################################################
  22. //############################################################################
  23. //
  24. // Implementation of class CEOTSymbol
  25. //
  26. //############################################################################
  27. //############################################################################
  28. CEOTSymbol::~CEOTSymbol()
  29. {
  30. }
  31. bool
  32. CEOTSymbol::operator == (const CEOTSymbol &rhs)
  33. {
  34. return ( (m_iconResource == rhs.m_iconResource) &&
  35. (m_value == rhs.m_value) &&
  36. (m_ID == rhs.m_ID) );
  37. }
  38. void
  39. CEOTSymbol::SetIcon(const CSmartIcon & smartIconSmall, const CSmartIcon & smartIconLarge)
  40. {
  41. m_smartIconSmall = smartIconSmall;
  42. m_smartIconLarge = smartIconLarge;
  43. }
  44. /*+-------------------------------------------------------------------------*
  45. *
  46. * CEOTSymbol::Draw
  47. *
  48. * PURPOSE:
  49. *
  50. * PARAMETERS:
  51. * HDC hdc :
  52. * RECT * lpRect :
  53. * bool bSmall :
  54. *
  55. * RETURNS:
  56. * void
  57. *
  58. *+-------------------------------------------------------------------------*/
  59. void
  60. CEOTSymbol::Draw(HDC hdc, RECT *lpRect, bool bSmall) const
  61. {
  62. // if the icons already exist, Draw has been called before OR this symbol has a custom icon that as been
  63. // assigned the icons directly using SetIcon
  64. if((HICON)m_smartIconSmall == NULL)
  65. {
  66. m_smartIconSmall.Attach((HICON)::LoadImage(_Module.GetResourceInstance(),
  67. MAKEINTRESOURCE(m_iconResource), IMAGE_ICON, 16, 16, 0));
  68. }
  69. if((HICON)m_smartIconLarge == NULL)
  70. {
  71. m_smartIconLarge.Attach((HICON)::LoadImage(_Module.GetResourceInstance(),
  72. MAKEINTRESOURCE(m_iconResource), IMAGE_ICON, 32, 32, 0));
  73. }
  74. /*
  75. * Preserve icon shape when BitBlitting it to a
  76. * mirrored DC.
  77. */
  78. DWORD dwLayout=0L;
  79. if ((dwLayout=GetLayout(hdc)) & LAYOUT_RTL)
  80. {
  81. SetLayout(hdc, dwLayout|LAYOUT_BITMAPORIENTATIONPRESERVED);
  82. }
  83. DrawIconEx(hdc, lpRect->left, lpRect->top, bSmall ? m_smartIconSmall : m_smartIconLarge,
  84. bSmall? 16 : 32, bSmall? 16 : 32, 0, NULL, DI_NORMAL);
  85. /*
  86. * Restore the DC to its previous layout state.
  87. */
  88. if (dwLayout & LAYOUT_RTL)
  89. {
  90. SetLayout(hdc, dwLayout);
  91. }
  92. }
  93. /*+-------------------------------------------------------------------------*
  94. *
  95. * CEOTSymbol::IsMatch
  96. *
  97. * PURPOSE: Checks to see whether str1 is one of the strings contained in the
  98. * comma separated list str2.
  99. *
  100. * PARAMETERS:
  101. * CStr & str1 :
  102. * CStr & str2 :
  103. *
  104. * RETURNS:
  105. * bool: true if str1 is contained in str2, else false.
  106. *
  107. *+-------------------------------------------------------------------------*/
  108. bool
  109. CEOTSymbol::IsMatch(CStr &str1, CStr &str2)
  110. {
  111. // trim spaces off either end.
  112. str1.TrimLeft();
  113. str1.TrimRight();
  114. CStr strTemp;
  115. int length;
  116. while((length = str2.GetLength()) != 0 )
  117. {
  118. int index = str2.Find(TEXT(','));
  119. if(index!=-1)
  120. {
  121. strTemp = str2.Left(index); // index is the pos of the ',' so we're OK.
  122. str2 = str2.Right(length - index -1);
  123. }
  124. else
  125. {
  126. strTemp = str2;
  127. str2.Empty();
  128. }
  129. strTemp.TrimLeft();
  130. strTemp.TrimRight();
  131. // compare str1 and strTemp
  132. if( str1.CompareNoCase((LPCTSTR)strTemp)==0)
  133. return true; // match
  134. }
  135. return false;
  136. }
  137. int
  138. CEOTSymbol::FindMatchingSymbol(LPCTSTR szDescription) // finds a symbol matching the given description.
  139. {
  140. CStr strDescription = szDescription;
  141. int iSelect = -1;
  142. for(int i = 0; i<NUM_SYMBOLS; i++)
  143. {
  144. CStr strDescTemp;
  145. int ID = s_rgEOTSymbol[i].GetID();
  146. strDescTemp.LoadString(_Module.GetResourceInstance(), ID); // get the string.
  147. if(IsMatch(strDescription, strDescTemp))
  148. {
  149. iSelect = i; // perfect match
  150. break;
  151. }
  152. CStr strDescTemp2;
  153. int ID2 = s_rgEOTSymbol[i].GetIDSecondary();
  154. if(ID2)
  155. strDescTemp2.LoadString(_Module.GetResourceInstance(), ID2); // get the string.
  156. if(IsMatch(strDescription, strDescTemp2))
  157. {
  158. iSelect = i; // imperfect match, keep trying.
  159. }
  160. }
  161. return iSelect;
  162. }
  163. //############################################################################
  164. //############################################################################
  165. //
  166. // Implementation of class CTaskSymbolDialog
  167. //
  168. //############################################################################
  169. //############################################################################
  170. CTaskSymbolDlg::CTaskSymbolDlg(CConsoleTask& rConsoleTask, bool bFindMatchingSymbol)
  171. : m_ConsoleTask (rConsoleTask),
  172. m_bCustomIcon (rConsoleTask.HasCustomIcon())
  173. {
  174. m_bFindMatchingSymbol = bFindMatchingSymbol;
  175. }
  176. LRESULT CTaskSymbolDlg::OnInitDialog(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& handled)
  177. {
  178. m_listGlyphs = GetDlgItem (IDC_GLYPH_LIST);
  179. m_wndCustomIcon = GetDlgItem (IDC_CustomIcon);
  180. m_imageList.Create (16, 28, ILC_COLOR , 20, 10);
  181. m_listGlyphs.SetImageList((HIMAGELIST) m_imageList, LVSIL_NORMAL);
  182. int cxIconSpacing = s_cxIcon + s_cxIconGutter;
  183. m_listGlyphs.SetIconSpacing (cxIconSpacing, cxIconSpacing);
  184. int iSelect = 0;
  185. // insert all the items
  186. for(int i=0; i< NUM_SYMBOLS; i++)
  187. {
  188. LV_ITEM item;
  189. ZeroMemory(&item, sizeof(item));
  190. item.mask = LVIF_PARAM;
  191. item.lParam = i;
  192. if(s_rgEOTSymbol[i].GetValue()==m_ConsoleTask.GetSymbol())
  193. {
  194. iSelect = i;
  195. }
  196. m_listGlyphs.InsertItem(&item);
  197. }
  198. /*
  199. * check the appropriate radio button
  200. */
  201. int nCheckedButton = (m_bCustomIcon) ? IDC_CustomIconRadio : IDC_MMCIconsRadio;
  202. CheckRadioButton (IDC_CustomIconRadio, IDC_MMCIconsRadio, nCheckedButton);
  203. SC scNoTrace = ScEnableControls (nCheckedButton);
  204. /*
  205. * if this task has a custom icon, initialize the preview control
  206. */
  207. if (m_bCustomIcon)
  208. m_wndCustomIcon.SetIcon (m_ConsoleTask.GetLargeCustomIcon());
  209. if(m_bFindMatchingSymbol) // a description string was passed in, use it to populate the page.
  210. {
  211. tstring strName = m_ConsoleTask.GetName();
  212. if(strName.length()>0)
  213. iSelect = CEOTSymbol::FindMatchingSymbol((LPCTSTR)strName.data());
  214. }
  215. /*
  216. * select the icon for this task
  217. */
  218. LV_ITEM item;
  219. ZeroMemory(&item, sizeof(item));
  220. item.iItem = iSelect;
  221. item.mask = LVIF_STATE;
  222. item.state = LVIS_FOCUSED | LVIS_SELECTED;
  223. item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
  224. m_listGlyphs.SetItem(&item);
  225. m_listGlyphs.EnsureVisible(iSelect, 0);
  226. return 0;
  227. }
  228. /*+-------------------------------------------------------------------------*
  229. * CTaskSymbolDlg::OnCtlColorStatic
  230. *
  231. * WM_CTLCOLORSTATIC handler for CTaskSymbolDlg.
  232. *--------------------------------------------------------------------------*/
  233. LRESULT CTaskSymbolDlg::OnCtlColorStatic(UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  234. {
  235. HBRUSH hbrRet = NULL;
  236. switch (::GetDlgCtrlID (((HWND) lParam)))
  237. {
  238. /*
  239. * for the custom icon preview window and its well, if we're using a
  240. * custom icon, return a COLOR_WINDOW brush so the static won't paint
  241. * the background with COLOR_3DFACE
  242. */
  243. case IDC_CustomIcon:
  244. case IDC_CustomIconWell:
  245. if (m_bCustomIcon)
  246. hbrRet = GetSysColorBrush (COLOR_WINDOW);
  247. break;
  248. }
  249. /*
  250. * if we didn't supply a brush, let this message go through to DefWindowProc
  251. */
  252. if (hbrRet == NULL)
  253. bHandled = false;
  254. return ((LPARAM) hbrRet);
  255. }
  256. /*+-------------------------------------------------------------------------*
  257. * CTaskSymbolDlg::OnIconSourceChanged
  258. *
  259. * BN_CLICKED handler for CTaskSymbolDlg.
  260. *--------------------------------------------------------------------------*/
  261. LRESULT CTaskSymbolDlg::OnIconSourceChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  262. {
  263. m_bCustomIcon = (wID == IDC_CustomIconRadio);
  264. SC scNoTrace = ScEnableControls (wID);
  265. return (0);
  266. }
  267. /*+-------------------------------------------------------------------------*
  268. * CTaskSymbolDlg::ScEnableControls
  269. *
  270. * Enables the controls belonging to a particular radio button on the
  271. * symbol dialog
  272. *--------------------------------------------------------------------------*/
  273. SC CTaskSymbolDlg::ScEnableControls (int id)
  274. {
  275. DECLARE_SC (sc, _T("CTaskSymbolDlg::ScEnableControls"));
  276. /*
  277. * validate input
  278. */
  279. ASSERT ((id == IDC_CustomIconRadio) || (id == IDC_MMCIconsRadio));
  280. if (! ((id == IDC_CustomIconRadio) || (id == IDC_MMCIconsRadio)))
  281. return (sc = E_INVALIDARG);
  282. /*
  283. * controls to be enabled when "Custom Icon" radio button is selected
  284. */
  285. static const int nCustomIconCtlIDs[] = {
  286. IDC_CustomIcon,
  287. IDC_CustomIconWell,
  288. IDB_SELECT_TASK_ICON,
  289. 0 // terminator
  290. };
  291. /*
  292. * controls to be enabled when "MMC Icons" radio button is selected
  293. */
  294. static const int nMMCIconCtlIDs[] = {
  295. IDC_GLYPH_LIST,
  296. IDC_DESCRIPTION,
  297. IDC_DESCRIPTION2,
  298. IDC_DESCRIPTIONLabel,
  299. IDC_DESCRIPTION2Label,
  300. 0 // terminator
  301. };
  302. const int* pnEnableIDs = NULL;
  303. const int* pnDisableIDs = NULL;
  304. /*
  305. * pick the right sets of controls to enable/disable
  306. */
  307. if (id == IDC_CustomIconRadio)
  308. {
  309. pnEnableIDs = nCustomIconCtlIDs;
  310. pnDisableIDs = nMMCIconCtlIDs;
  311. }
  312. else
  313. {
  314. pnEnableIDs = nMMCIconCtlIDs;
  315. pnDisableIDs = nCustomIconCtlIDs;
  316. }
  317. /*
  318. * enable/disable the controls
  319. */
  320. for (int i = 0; pnEnableIDs[i] != 0; i++)
  321. ::EnableWindow (GetDlgItem (pnEnableIDs[i]), true);
  322. for (int i = 0; pnDisableIDs[i] != 0; i++)
  323. ::EnableWindow (GetDlgItem (pnDisableIDs[i]), false);
  324. return (sc);
  325. }
  326. LRESULT
  327. CTaskSymbolDlg::OnSymbolChanged(int id, LPNMHDR pnmh, BOOL& bHandled )
  328. {
  329. NMLISTVIEW* pnmlv = (NMLISTVIEW *) pnmh;
  330. if(! ((pnmlv->uNewState & LVNI_FOCUSED) && (pnmlv->iItem !=-1)) )
  331. return 0;
  332. int nItem = pnmlv->iItem;
  333. CStr strDescription;
  334. int ID = s_rgEOTSymbol[nItem].GetID();
  335. strDescription.LoadString(_Module.GetResourceInstance(), ID); // get the string.
  336. SetDlgItemText(IDC_DESCRIPTION, (LPCTSTR) strDescription);
  337. CStr strDescription2;
  338. int ID2 = s_rgEOTSymbol[nItem].GetIDSecondary();
  339. if(ID2)
  340. strDescription2.LoadString(_Module.GetResourceInstance(), ID2); // get the string.
  341. SetDlgItemText(IDC_DESCRIPTION2, (LPCTSTR) strDescription2);
  342. return 0;
  343. }
  344. LRESULT
  345. CTaskSymbolDlg::OnCustomDraw(int id, LPNMHDR pnmh, BOOL& bHandled )
  346. {
  347. NMCUSTOMDRAW* pnmcd = (NMCUSTOMDRAW *) pnmh;
  348. switch(pnmcd->dwDrawStage & ~CDDS_SUBITEM)
  349. {
  350. case CDDS_PREPAINT: // the initial notification
  351. return CDRF_NOTIFYITEMDRAW; // we want to know about each item's paint.
  352. case CDDS_ITEMPREPAINT:
  353. DrawItem(pnmcd);
  354. return CDRF_SKIPDEFAULT; // we've drawn the whole item ourselves
  355. default:
  356. return 0;
  357. }
  358. }
  359. void
  360. CTaskSymbolDlg::DrawItem(NMCUSTOMDRAW *pnmcd)
  361. {
  362. DECLARE_SC(sc, TEXT("CTaskSymbolDlg::DrawItem"));
  363. int nItem = pnmcd->dwItemSpec;
  364. HDC &hdc = pnmcd->hdc;
  365. LV_ITEM item;
  366. ZeroMemory(&item, sizeof(item));
  367. item.iItem = nItem;
  368. item.mask = LVIF_STATE;
  369. item.stateMask = (UINT) -1; //get all the state bits.
  370. m_listGlyphs.GetItem(&item);
  371. /*
  372. * get the icon rect for the item and offset it downward by the size
  373. * of our border margin
  374. */
  375. RECT rectIcon;
  376. m_listGlyphs.GetItemRect(nItem, &rectIcon, LVIR_ICON);
  377. OffsetRect (&rectIcon, 0, s_cxSelectionMargin);
  378. /*
  379. * Make a slightly inflated copy the icon rectangle to draw in the
  380. * selection color. We inflate to make the selection stand out a little
  381. * more for large icons.
  382. */
  383. RECT rectBackground = rectIcon;
  384. InflateRect (&rectBackground, s_cxSelectionMargin, s_cxSelectionMargin);
  385. bool bWindowHasFocus = (GetFocus() == (HWND)m_listGlyphs);
  386. bool bSelected = item.state & LVIS_SELECTED;
  387. bool bDisabled = !m_listGlyphs.IsWindowEnabled();
  388. // Create the select rectangle or empty the rectangle.
  389. int nBackColorIndex = (bDisabled) ? COLOR_3DFACE :
  390. (bSelected) ? COLOR_HIGHLIGHT :
  391. COLOR_WINDOW;
  392. FillRect (hdc, &rectBackground, (HBRUSH) LongToHandle(nBackColorIndex+1));
  393. // draw the symbol icon
  394. s_rgEOTSymbol[nItem].Draw(hdc, &rectIcon);
  395. if(bWindowHasFocus && bSelected)
  396. ::DrawFocusRect(hdc, &rectBackground);
  397. //ReleaseDC(hdc); DONT release the DC!
  398. }
  399. BOOL
  400. CTaskSymbolDlg::OnOK()
  401. {
  402. int nItem = m_listGlyphs.GetSelectedIndex();
  403. /*
  404. * make sure we've selected an item
  405. */
  406. if (( m_bCustomIcon && (m_CustomIconLarge == NULL)) ||
  407. (!m_bCustomIcon && (nItem == -1)))
  408. {
  409. CStr strError;
  410. strError.LoadString(GetStringModule(), IDS_SYMBOL_REQUIRED);
  411. MessageBox(strError, NULL, MB_OK | MB_ICONEXCLAMATION);
  412. return (false);
  413. }
  414. if (m_bCustomIcon)
  415. m_ConsoleTask.SetCustomIcon(m_CustomIconSmall, m_CustomIconLarge);
  416. else
  417. m_ConsoleTask.SetSymbol(s_rgEOTSymbol[nItem].GetValue());
  418. return TRUE;
  419. }
  420. /*+-------------------------------------------------------------------------*
  421. *
  422. * CTaskSymbolDlg::OnSelectTaskIcon
  423. *
  424. * PURPOSE: Uses the shell-provided icon picker dialog to allow the user to select
  425. * a custom icon for the console task.
  426. *
  427. * PARAMETERS:
  428. * WORD wNotifyCode :
  429. * WORD wID :
  430. * HWND hWndCtl :
  431. * BOOL& bHandled :
  432. *
  433. * RETURNS:
  434. * LRESULT
  435. *
  436. *+-------------------------------------------------------------------------*/
  437. LRESULT
  438. CTaskSymbolDlg::OnSelectTaskIcon(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  439. {
  440. DECLARE_SC(sc, TEXT("CTaskSymbolDlg::OnSelectTaskIcon"));
  441. static CStr s_strCustomIconFile;
  442. static int s_nIconIndex = 0;
  443. int nIconIndex = s_nIconIndex;
  444. TCHAR szIconFile[MAX_PATH];
  445. /*
  446. * shouldn't get here unless we think we're using a custom icon
  447. */
  448. ASSERT (m_bCustomIcon);
  449. /*
  450. * reuse the last custom icon source; if it's not available,
  451. * default to mmc.exe
  452. */
  453. if (s_strCustomIconFile.IsEmpty())
  454. {
  455. LPTSTR pszCustomIconFile = s_strCustomIconFile.GetBuffer (MAX_PATH);
  456. sc = ScCheckPointers (pszCustomIconFile, E_OUTOFMEMORY);
  457. if (sc)
  458. {
  459. MMCErrorBox (sc);
  460. return (0);
  461. }
  462. GetModuleFileName (NULL, pszCustomIconFile, MAX_PATH);
  463. s_strCustomIconFile.ReleaseBuffer();
  464. }
  465. lstrcpy (szIconFile, s_strCustomIconFile);
  466. if (PickIconDlg (m_hWnd, szIconFile, countof (szIconFile), &nIconIndex))
  467. {
  468. TCHAR szIconFile2[MAX_PATH];
  469. ExpandEnvironmentStrings(szIconFile, szIconFile2, MAX_PATH);
  470. /*
  471. * remember the user's selection for next time
  472. */
  473. s_strCustomIconFile = szIconFile;
  474. s_nIconIndex = nIconIndex;
  475. // need to extract and copy the icon rather than use LoadImage, because LoadImage uses a custom icon
  476. CSmartIcon smartIconTemp;
  477. smartIconTemp.Attach(::ExtractIcon (_Module.m_hInst, szIconFile2, nIconIndex));
  478. m_CustomIconSmall.Attach((HICON) ::CopyImage((HICON)smartIconTemp, IMAGE_ICON, 16, 16, LR_COPYFROMRESOURCE));
  479. m_CustomIconLarge.Attach((HICON) ::CopyImage((HICON)smartIconTemp, IMAGE_ICON, 32, 32, LR_COPYFROMRESOURCE));
  480. /*
  481. * update the custom icon preview window
  482. */
  483. m_wndCustomIcon.SetIcon (m_CustomIconLarge);
  484. m_wndCustomIcon.InvalidateRect (NULL);
  485. }
  486. return 0;
  487. }