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.

2712 lines
84 KiB

  1. //---------------------------------------------------------------------------
  2. // This file contains Taskbar and Start Menu property sheet code
  3. //---------------------------------------------------------------------------
  4. #include "cabinet.h"
  5. #include "rcids.h"
  6. #include "util.h"
  7. #include <help.h> // help ids
  8. #include <regstr.h>
  9. #include <atlstuff.h>
  10. #include "dlg.h"
  11. #include "tray.h"
  12. #include "traycmn.h"
  13. #include "startmnu.h"
  14. #include "desktop2.h"
  15. #include "uemapp.h"
  16. #define GROUPID_CURRENTITEMS 5
  17. #define GROUPID_PASTITEMS 6
  18. #define MAX_PROGS_ALLOWED 30
  19. const static DWORD aInitStartMenuHelpIDs[] = {
  20. IDC_NO_HELP_1, NO_HELP,
  21. IDC_NO_HELP_2, NO_HELP,
  22. IDC_NO_HELP_3, NO_HELP,
  23. IDC_NO_HELP_4, NO_HELP,
  24. IDC_GROUPBOX, IDH_COMM_GROUPBOX,
  25. IDC_GROUPBOX_2, IDH_MENUCONFIG_CLEAR,
  26. IDC_GROUPBOX_3, IDH_COMM_GROUPBOX,
  27. IDC_ADDSHORTCUT, IDH_TRAY_ADD_PROGRAM,
  28. IDC_DELSHORTCUT, IDH_TRAY_REMOVE_PROGRAM,
  29. IDC_EXPLOREMENUS, IDH_TRAY_ADVANCED,
  30. IDC_KILLDOCUMENTS, IDH_MENUCONFIG_CLEAR,
  31. IDC_RESORT, IDH_TRAY_RESORT_BUTTON,
  32. IDC_STARTMENUSETTINGSTEXT, IDH_TRAY_START_MENU_SETTINGS,
  33. 0, 0
  34. };
  35. const static DWORD aTaskOptionsHelpIDs[] = { // Context Help IDs
  36. IDC_TASKBARAPPEARANCE,IDH_TASKBAR_OPTIONS_BITMAP,
  37. IDC_NOTIFYAPPEARANCE, IDH_TASKBAR_OPTIONS_BITMAP,
  38. IDC_TRAYOPTAUTOHIDE, IDH_TRAY_TASKBAR_AUTOHIDE,
  39. IDC_TRAYOPTSHOWCLOCK, IDH_TRAY_SHOW_CLOCK,
  40. IDC_TRAYOPTONTOP, IDH_TRAY_TASKBAR_ONTOP,
  41. IDC_LOCKTASKBAR, IDH_TRAY_ENABLEMOVERESIZE,
  42. IDC_GROUPITEMS, IDH_TRAY_GROUPING,
  43. IDC_NOTIFYMAN, IDH_TRAY_HIDE_ICONS,
  44. IDC_CUSTOMIZE, IDH_TRAY_CUSTOMIZE_ICONS,
  45. IDC_QUICKLAUNCH, IDH_TRAY_QUICKLAUNCH,
  46. 0, 0
  47. };
  48. const static DWORD aNotifyOptionsHelpIDs[] = { // Context Help IDs
  49. IDC_NOTIFY_TEXT, NO_HELP,
  50. IDC_NOTIFY_TEXT2, NO_HELP,
  51. IDC_COMBO_ACTION, NO_HELP,
  52. IDC_NOTIFY_ITEMS, NO_HELP,
  53. IDB_NOTIFY_RESTOREDEFAULTS, IDH_TRAY_RESTOREDEFBUTTON,
  54. 0, 0
  55. };
  56. const static DWORD aStartTabHelpIDs[] = {
  57. IDC_STARTMENUPREVIEW, IDH_START_PREVIEW,
  58. IDC_NEWSCHOOL, IDH_START_SELECTPERSONAL,
  59. IDC_OLDSCHOOL, IDH_START_SELECTCLASSIC,
  60. IDC_NEWSTARTCUSTOMIZE, IDH_START_CUSTOMIZEPERSONAL,
  61. IDC_OLDSTARTCUSTOMIZE, IDH_START_CUSTOMIZECLASSIC,
  62. 0, 0
  63. };
  64. const static DWORD aStartCustGeneralTabHelpIDs[] = {
  65. IDC_SPCUST_ICONLARGE, IDH_START_SPCUST_LARGE,
  66. IDC_SPCUST_ICONSMALL, IDH_START_SPCUST_SMALL,
  67. IDC_SPCUST_LARGE, IDH_START_SPCUST_LARGE,
  68. IDC_SPCUST_SMALL, IDH_START_SPCUST_SMALL,
  69. IDC_SPCUST_MINPROGS, IDH_START_SPCUST_MINPROGS,
  70. IDC_SPCUST_MINPROGS_ARROW, IDH_START_SPCUST_MINPROGS,
  71. IDB_SPCUST_CLEARPROG, IDH_START_SPCUST_CLEARPROG,
  72. IDC_SPCUST_INTERNET, IDH_START_SPCUST_INTERNET,
  73. IDC_SPCUST_INTERNETCB, IDH_START_SPCUST_INTERNETCB,
  74. IDC_SPCUST_EMAIL, IDH_START_SPCUST_EMAIL,
  75. IDC_SPCUST_EMAILCB, IDH_START_SPCUST_EMAILCB,
  76. 0, 0
  77. };
  78. const static DWORD aStartCustAdvancedTabHelpIDs[] = {
  79. IDC_SPCUST_HOVEROPEN, IDH_START_SPCUST_HOVEROPEN,
  80. IDC_SPCUST_NOTIFYNEW, IDH_START_SPCUST_NOTIFYNEW,
  81. IDC_STARTMENUSETTINGS, IDH_START_STARTMENUSETTINGS,
  82. IDC_SPCUST_RECENT_GROUPBOX, NO_HELP,
  83. IDC_SPCUST_RECENT_TEXT, NO_HELP,
  84. IDC_SPCUST_RECENT, IDH_START_SPCUST_RECENT,
  85. IDB_SPCUST_CLEARDOCS, IDH_START_SPCUST_CLEARDOCS,
  86. 0, 0
  87. };
  88. #define REGSTR_VAL_LARGEICONSTEMP TEXT("Start_LargeIcons")
  89. #define REGSTR_VAL_ADMINTOOLSTEMP TEXT("Start_AdminToolsTemp")
  90. void SetDlgItemBitmap(HWND hDlg, int idStatic, int iResource);
  91. void SetDlgItemIcon(HWND hDlg, int idStatic, HICON hi);
  92. void SetProgramIcon(HWND hDlg, int idLarge, int idSmall);
  93. void _TaskbarOptionsUpdateDisplay(HWND hDlg);
  94. void _TaskbarOptionsSizeControls(HWND hDlg);
  95. void _TaskbarOptionsDestroyBitmaps(HWND hDlg);
  96. BOOL_PTR WINAPI AdvancedOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  97. typedef struct
  98. {
  99. HWND hwndTree;
  100. IRegTreeOptions *pTO;
  101. } SMADVANCED;
  102. void SendPSMChanged(HWND hDlg)
  103. {
  104. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  105. }
  106. class CPinHelper
  107. {
  108. public:
  109. CPinHelper();
  110. ~CPinHelper();
  111. void Save(BOOL bShowEmail, BOOL bShowBrowser);
  112. void GetPinInfo(BOOL *pbPinBrowser, BOOL *pbPinEmail);
  113. private:
  114. void SavePinInfo(LPCITEMIDLIST pidlVictim, BOOL bOld, BOOL bNew);
  115. LPITEMIDLIST _pidlBrowser;
  116. LPITEMIDLIST _pidlEmail;
  117. IStartMenuPin *_psmp;
  118. };
  119. CPinHelper::CPinHelper()
  120. {
  121. _pidlBrowser = ILCreateFromPath(TEXT("shell:::{2559a1f4-21d7-11d4-bdaf-00c04f60b9f0}"));
  122. _pidlEmail = ILCreateFromPath(TEXT("shell:::{2559a1f5-21d7-11d4-bdaf-00c04f60b9f0}"));
  123. CoCreateInstance(CLSID_StartMenuPin, NULL, CLSCTX_INPROC_SERVER,
  124. IID_PPV_ARG(IStartMenuPin, &_psmp));
  125. }
  126. CPinHelper::~CPinHelper()
  127. {
  128. ILFree(_pidlBrowser);
  129. ILFree(_pidlEmail);
  130. ATOMICRELEASE(_psmp);
  131. }
  132. void CPinHelper::GetPinInfo(BOOL *pbPinBrowser, BOOL *pbPinEmail)
  133. {
  134. *pbPinBrowser = FALSE;
  135. *pbPinEmail = FALSE;
  136. if (_psmp)
  137. {
  138. IEnumIDList *peidl;
  139. if (SUCCEEDED(_psmp->EnumObjects(&peidl)))
  140. {
  141. LPITEMIDLIST pidl;
  142. while (peidl->Next(1, &pidl, NULL) == S_OK)
  143. {
  144. if (ILIsEqual(pidl, _pidlBrowser)) *pbPinBrowser = TRUE;
  145. if (ILIsEqual(pidl, _pidlEmail)) *pbPinEmail = TRUE;
  146. ILFree(pidl);
  147. }
  148. peidl->Release();
  149. }
  150. }
  151. }
  152. void CPinHelper::SavePinInfo(LPCITEMIDLIST pidlVictim, BOOL bOld, BOOL bNew)
  153. {
  154. ASSERT(bOld == TRUE || bOld == FALSE);
  155. ASSERT(bNew == TRUE || bNew == FALSE);
  156. if (pidlVictim && _psmp && bOld != bNew)
  157. {
  158. if (bNew)
  159. {
  160. _psmp->Modify(NULL, pidlVictim);
  161. _psmp->Modify(pidlVictim, SMPIN_POS(0));
  162. }
  163. else
  164. {
  165. _psmp->Modify(pidlVictim, NULL);
  166. }
  167. }
  168. }
  169. void CPinHelper::Save(BOOL bShowEmail, BOOL bShowBrowser)
  170. {
  171. // Get old settings
  172. BOOL bShowBrowserOld, bShowEmailOld;
  173. GetPinInfo(&bShowBrowserOld, &bShowEmailOld);
  174. //
  175. // Do in reverse order because we insert at the top of the list.
  176. //
  177. SavePinInfo(_pidlEmail, bShowEmailOld, bShowEmail);
  178. SavePinInfo(_pidlBrowser, bShowBrowserOld, bShowBrowser);
  179. }
  180. class ATL_NO_VTABLE CNotificationsDlg :
  181. public CComObjectRootEx<CComSingleThreadModel>,
  182. public CDialogImpl<CNotificationsDlg>,
  183. public INotificationCB
  184. {
  185. public:
  186. CNotificationsDlg()
  187. {
  188. _pTrayNotify = NULL;
  189. _fItemChanged = FALSE;
  190. _hPlaceholderIcon = NULL;
  191. _nIndex = -1;
  192. _fComboBoxActive = FALSE;
  193. };
  194. virtual ~CNotificationsDlg()
  195. {
  196. if (_pTrayNotify)
  197. {
  198. _pTrayNotify->Release();
  199. _pTrayNotify = NULL;
  200. }
  201. };
  202. DECLARE_NOT_AGGREGATABLE(CNotificationsDlg)
  203. BEGIN_COM_MAP(CNotificationsDlg)
  204. COM_INTERFACE_ENTRY(INotificationCB)
  205. END_COM_MAP()
  206. enum {IDD = DLG_NOTIFY};
  207. BEGIN_MSG_MAP_EX(CNotificationsDlg)
  208. MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
  209. MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
  210. MESSAGE_HANDLER(WM_HELP, OnHelp)
  211. NOTIFY_HANDLER_EX(IDC_NOTIFY_ITEMS, LVN_ITEMCHANGED, OnItemChanged)
  212. NOTIFY_HANDLER_EX(IDC_NOTIFY_ITEMS, LVN_ENDSCROLL, OnEndScroll)
  213. NOTIFY_CODE_HANDLER(HDN_ITEMCHANGED, OnHeaderItemChanged)
  214. COMMAND_HANDLER_EX(IDC_COMBO_ACTION, CBN_SELENDOK, OnComboSelEnd)
  215. COMMAND_ID_HANDLER_EX(IDB_NOTIFY_RESTOREDEFAULTS, OnRestoreDefaults)
  216. COMMAND_RANGE_HANDLER(IDOK, IDNO, OnCloseCmd)
  217. END_MSG_MAP()
  218. //*** INotificationCB ***
  219. STDMETHODIMP Notify(DWORD dwMessage, LPNOTIFYITEM pNotifyItem);
  220. //*** Message Callbacks ***
  221. LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  222. LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  223. LRESULT OnHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  224. LRESULT OnItemChanged(LPNMHDR pnmh);
  225. LRESULT OnEndScroll(LPNMHDR pnmh);
  226. LRESULT OnHeaderItemChanged(WPARAM wParam, LPNMHDR pnmh, LPARAM lParam);
  227. LRESULT OnComboSelEnd(UINT uMsg, UINT uID , HWND hwnd);
  228. LRESULT OnRestoreDefaults(UINT uMsg, UINT uID , HWND hwnd);
  229. LRESULT OnCloseCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
  230. static LRESULT CALLBACK s_ListViewSubClassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  231. LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  232. static LRESULT CALLBACK s_ComboBoxSubClassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  233. LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  234. //*** Other ***
  235. void ApplyChanges(void);
  236. private:
  237. HRESULT _AddItem(CNotificationItem& ni, int iIndex);
  238. void _ShowComboBox();
  239. int _GetCurSel();
  240. void _LoadAndSetLVItemText(UINT uResourceID, DWORD nRow, DWORD nCol);
  241. CSimpleArray<CNotificationItem> _saItems; //copy of the data, initialized by user
  242. BOOL _fItemChanged;
  243. ITrayNotify* _pTrayNotify;
  244. int _nPrevIndex;
  245. HWND _hwndCombo;
  246. HWND _hwndListView;
  247. RECT _rcOldPos;
  248. HICON _hPlaceholderIcon;
  249. BOOL _fComboBoxActive;
  250. int _nIndex;
  251. };
  252. HRESULT CNotificationsDlg::_AddItem(CNotificationItem& ni, int iIndex)
  253. {
  254. HIMAGELIST himl = ListView_GetImageList(_hwndListView, LVSIL_SMALL);
  255. BOOL fInsert = FALSE;
  256. LV_ITEM lvitem = {0};
  257. int iImage = -1;
  258. if (!ni.hIcon)
  259. {
  260. if (!_hPlaceholderIcon)
  261. {
  262. _hPlaceholderIcon = (HICON)LoadImage(hinstCabinet,
  263. MAKEINTRESOURCE(ICO_TRAYPROP_PLACEHOLDER), IMAGE_ICON,
  264. GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
  265. LR_LOADMAP3DCOLORS);
  266. }
  267. if (_hPlaceholderIcon)
  268. ni.hIcon = CopyIcon(_hPlaceholderIcon);
  269. }
  270. if (iIndex == -1)
  271. {
  272. iIndex = _saItems.GetSize();
  273. iImage = ImageList_AddIcon(himl, ni.hIcon);
  274. fInsert = TRUE;
  275. }
  276. else
  277. {
  278. lvitem.mask = LVIF_IMAGE;
  279. lvitem.iItem = iIndex;
  280. lvitem.iSubItem = 0;
  281. ListView_GetItem(_hwndListView, &lvitem);
  282. ImageList_ReplaceIcon(himl, lvitem.iImage, ni.hIcon);
  283. iImage = lvitem.iImage;
  284. fInsert = FALSE;
  285. }
  286. if (!ni.pszIconText || ni.pszIconText[0] == 0)
  287. {
  288. TCHAR szTemp[MAX_PATH];
  289. if (LoadString(hinstCabinet, IDS_NOTITLE, szTemp, ARRAYSIZE(szTemp)))
  290. ni.SetIconText(szTemp);
  291. // ni.m_strText.LoadString(IDS_NOTITLE);
  292. }
  293. else
  294. // Replace '\n' with ' '
  295. {
  296. LPTSTR szTemp = NULL;
  297. while (NULL != (szTemp = StrChr(ni.pszIconText, TEXT('\n'))))
  298. {
  299. ni.pszIconText[szTemp-ni.pszIconText] = TEXT(' ');
  300. }
  301. }
  302. lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_GROUPID;
  303. lvitem.iItem = iIndex;
  304. lvitem.iSubItem = 0;
  305. lvitem.pszText = ni.pszIconText;
  306. lvitem.iImage = iImage;
  307. lvitem.iGroupId = (ni.hWnd == NULL) ? GROUPID_PASTITEMS : GROUPID_CURRENTITEMS;
  308. if (fInsert)
  309. ListView_InsertItem(_hwndListView, &lvitem);
  310. else
  311. ListView_SetItem(_hwndListView, &lvitem);
  312. lvitem.mask = LVIF_TEXT;
  313. lvitem.iItem = iIndex;
  314. lvitem.iSubItem = 1;
  315. CString str;
  316. str.LoadString(IDS_NOTIFY_FIRST + ni.dwUserPref);
  317. lvitem.pszText = (LPTSTR)(LPCTSTR)str;
  318. ListView_SetItem(_hwndListView, &lvitem);
  319. if (fInsert)
  320. {
  321. _saItems.Add(ni);
  322. }
  323. else
  324. {
  325. _saItems[iIndex] = ni;
  326. }
  327. return S_OK;
  328. }
  329. HRESULT CNotificationsDlg::Notify(DWORD dwMessage, NOTIFYITEM * pNotifyItem)
  330. {
  331. if (!pNotifyItem || (!pNotifyItem->hWnd && !pNotifyItem->pszExeName))
  332. return E_INVALIDARG;
  333. ASSERT(pNotifyItem);
  334. CNotificationItem ni = *pNotifyItem;
  335. switch (dwMessage)
  336. {
  337. case NIM_ADD:
  338. case NIM_MODIFY:
  339. {
  340. // We never need to modify a Past Item
  341. for (int i = 0; (i < _saItems.GetSize() && ni.hWnd); i++)
  342. {
  343. // If the Item is already in the list just update it
  344. if (_saItems[i] == ni)
  345. {
  346. return _AddItem(ni, i);
  347. }
  348. }
  349. // If it is not in the list add it
  350. return _AddItem(ni, -1);
  351. }
  352. break;
  353. case NIM_DELETE:
  354. {
  355. for (int i = 0; (i < _saItems.GetSize()); i++)
  356. {
  357. if (_saItems[i] == ni)
  358. {
  359. _saItems.RemoveAt(i);
  360. ListView_DeleteItem(_hwndListView, i);
  361. _ShowComboBox();
  362. return S_OK;
  363. }
  364. }
  365. break;
  366. }
  367. }
  368. return E_INVALIDARG;
  369. }
  370. LRESULT CNotificationsDlg::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  371. {
  372. _hwndListView = GetDlgItem(IDC_NOTIFY_ITEMS);
  373. _nPrevIndex = -2;
  374. _rcOldPos.top = -500;
  375. CImageList il;
  376. int iSize = GetSystemMetrics(SM_CXSMICON);
  377. il.Create(iSize, iSize, SHGetImageListFlags(_hwndListView), _saItems.GetSize(), 4);
  378. if (il)
  379. {
  380. CString str;
  381. //list view control holding all the items
  382. ListView_SetExtendedListViewStyle(_hwndListView, LVS_EX_FULLROWSELECT);
  383. ListView_EnableGroupView(_hwndListView, TRUE);
  384. static const struct {
  385. int ids;
  386. int idGroup;
  387. } groupData[] = {{ IDS_NOTIFY_CURRENTITEMS, GROUPID_CURRENTITEMS },
  388. { IDS_NOTIFY_PASTITEMS, GROUPID_PASTITEMS }};
  389. for (int i = 0; i < ARRAYSIZE(groupData); i++)
  390. {
  391. str.LoadString(groupData[i].ids);
  392. LVGROUP lvgrp = { sizeof(LVGROUP) };
  393. lvgrp.mask = LVGF_HEADER | LVGF_GROUPID;
  394. lvgrp.pszHeader = (LPTSTR)(LPCTSTR)str;
  395. lvgrp.cchHeader = lstrlen(lvgrp.pszHeader);
  396. lvgrp.iGroupId = groupData[i].idGroup;
  397. SendMessage(_hwndListView, LVM_INSERTGROUP, -1, (LPARAM)&lvgrp);
  398. }
  399. //Split width of columns 3/5, 2/5
  400. RECT rc;
  401. ::GetClientRect(_hwndListView, &rc);
  402. int width = rc.right - rc.left - GetSystemMetrics(SM_CXHSCROLL);
  403. int width0 = 3*width/5;
  404. int width1 = width-width0;
  405. LV_COLUMN lvcol = {0};
  406. lvcol.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
  407. str.LoadString(IDS_NOTIFYNAME);
  408. lvcol.pszText = (LPTSTR)(LPCTSTR)str;
  409. lvcol.cx = width0;
  410. lvcol.iSubItem = 0;
  411. ListView_InsertColumn(_hwndListView, 0, &lvcol);
  412. str.LoadString(IDS_BEHAVIOR);
  413. lvcol.pszText = (LPTSTR)(LPCTSTR)str;
  414. lvcol.cx = width1;
  415. lvcol.iSubItem = 1;
  416. ListView_InsertColumn(_hwndListView, 1, &lvcol);
  417. il.SetBkColor(GetSysColor(COLOR_WINDOW));
  418. ListView_SetImageList(_hwndListView, il, LVSIL_SMALL);
  419. il.Detach();
  420. _hwndCombo = GetDlgItem(IDC_COMBO_ACTION);
  421. // make sure combo box uses same font as list view
  422. ::SendMessage(_hwndCombo, WM_SETFONT, (WPARAM)::SendMessage(_hwndListView, WM_GETFONT, 0, 0), MAKELPARAM(TRUE, 0));
  423. for (int i = IDS_NOTIFY_FIRST; i < IDS_NOTIFY_LAST; i++)
  424. {
  425. CString strTemp;
  426. strTemp.LoadString(i);
  427. ComboBox_AddString(_hwndCombo, strTemp);
  428. }
  429. ::SetParent(_hwndCombo, _hwndListView);
  430. HWND hwndHeader = ListView_GetHeader(_hwndListView);
  431. ::SetWindowPos(_hwndCombo, hwndHeader, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW);
  432. ::SetWindowSubclass(_hwndListView, s_ListViewSubClassWndProc, 0,
  433. reinterpret_cast<DWORD_PTR>(this));
  434. ::SetWindowSubclass(_hwndCombo, s_ComboBoxSubClassWndProc, 0,
  435. reinterpret_cast<DWORD_PTR>(this));
  436. }
  437. _saItems.RemoveAll();
  438. if (_pTrayNotify)
  439. {
  440. _pTrayNotify->Release();
  441. _pTrayNotify = NULL;
  442. }
  443. if (SUCCEEDED(CoCreateInstance(CLSID_TrayNotify, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARG(ITrayNotify, &_pTrayNotify))))
  444. {
  445. INotificationCB* pCB;
  446. if (SUCCEEDED(QueryInterface(IID_PPV_ARG(INotificationCB, &pCB))))
  447. {
  448. _pTrayNotify->RegisterCallback(pCB);
  449. pCB->Release();
  450. }
  451. }
  452. // Set the selected and focused state to the first item
  453. // ListView_SetItemState(hwndLV, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  454. bHandled = TRUE;
  455. return 0;
  456. }
  457. LRESULT CNotificationsDlg::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  458. {
  459. ::WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aNotifyOptionsHelpIDs);
  460. bHandled = TRUE;
  461. return 0;
  462. }
  463. LRESULT CNotificationsDlg::OnHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  464. {
  465. ::WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aNotifyOptionsHelpIDs);
  466. bHandled = TRUE;
  467. return 0;
  468. }
  469. LRESULT CNotificationsDlg::OnItemChanged(LPNMHDR pnmh)
  470. {
  471. _ShowComboBox();
  472. return 0;
  473. }
  474. LRESULT CNotificationsDlg::OnEndScroll(LPNMHDR pnmh)
  475. {
  476. _ShowComboBox();
  477. return 0;
  478. }
  479. LRESULT CNotificationsDlg::OnHeaderItemChanged(WPARAM wParam, LPNMHDR pnmh, LPARAM lParam)
  480. {
  481. HWND hwndHeader = ListView_GetHeader(_hwndListView);
  482. if (pnmh->hwndFrom == hwndHeader)
  483. {
  484. _ShowComboBox();
  485. }
  486. return 0;
  487. }
  488. int CNotificationsDlg::_GetCurSel()
  489. {
  490. return (int)::SendMessage(_hwndListView, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
  491. }
  492. void CNotificationsDlg::_LoadAndSetLVItemText(UINT uResourceID, DWORD nRow, DWORD nCol)
  493. {
  494. CString str;
  495. str.LoadString(uResourceID);
  496. ListView_SetItemText(_hwndListView, nRow, nCol, (LPTSTR)(LPCTSTR)str);
  497. }
  498. LRESULT CNotificationsDlg::OnComboSelEnd(UINT uMsg, UINT uID ,HWND hwnd)
  499. {
  500. int nCurIndex = _fComboBoxActive ? _nIndex : _GetCurSel();
  501. if (nCurIndex != -1)
  502. {
  503. DWORD dwUserPref = ComboBox_GetCurSel(_hwndCombo);
  504. if (dwUserPref != _saItems[nCurIndex].dwUserPref)
  505. {
  506. _fItemChanged = TRUE;
  507. _saItems[nCurIndex].dwUserPref = dwUserPref;
  508. _LoadAndSetLVItemText(IDS_NOTIFY_FIRST + dwUserPref, nCurIndex, 1);
  509. }
  510. }
  511. return 0;
  512. }
  513. LRESULT CNotificationsDlg::OnRestoreDefaults(UINT uMsg, UINT uID , HWND hwnd)
  514. {
  515. for (int i=0;i<_saItems.GetSize();i++)
  516. {
  517. if (_saItems[i].dwUserPref != TNUP_AUTOMATIC)
  518. {
  519. _fItemChanged = TRUE;
  520. _saItems[i].dwUserPref = TNUP_AUTOMATIC;
  521. _LoadAndSetLVItemText(IDS_AUTOMATIC, i, 1);
  522. }
  523. }
  524. return 0;
  525. }
  526. LRESULT CNotificationsDlg::OnCloseCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  527. {
  528. if (wID == IDOK)
  529. {
  530. ApplyChanges();
  531. }
  532. if (_hPlaceholderIcon)
  533. {
  534. DestroyIcon(_hPlaceholderIcon);
  535. _hPlaceholderIcon = NULL;
  536. }
  537. _saItems.RemoveAll();
  538. if (_hwndListView)
  539. {
  540. RemoveWindowSubclass(_hwndListView, s_ListViewSubClassWndProc, 0);
  541. }
  542. if (_hwndCombo)
  543. {
  544. RemoveWindowSubclass(_hwndCombo, s_ComboBoxSubClassWndProc, 0);
  545. }
  546. if (_pTrayNotify)
  547. {
  548. _pTrayNotify->RegisterCallback(NULL);
  549. }
  550. bHandled = TRUE;
  551. ::EndDialog(m_hWnd, wID);
  552. return 0;
  553. }
  554. LRESULT CALLBACK CNotificationsDlg::s_ListViewSubClassWndProc( HWND hwnd, UINT uMsg,
  555. WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData )
  556. {
  557. CNotificationsDlg * pNotificationsDlg = reinterpret_cast<CNotificationsDlg*>(dwRefData);
  558. AssertMsg((pNotificationsDlg != NULL), TEXT("pNotificationsDlg SHOULD NOT be NULL."));
  559. switch (uMsg)
  560. {
  561. case WM_KEYDOWN:
  562. {
  563. if (wParam == VK_RIGHT && !pNotificationsDlg->_fComboBoxActive)
  564. {
  565. int nIndex = pNotificationsDlg->_GetCurSel();
  566. if (nIndex != -1)
  567. {
  568. pNotificationsDlg->_nIndex = nIndex;
  569. pNotificationsDlg->_fComboBoxActive = TRUE;
  570. ::SetFocus(pNotificationsDlg->_hwndCombo);
  571. }
  572. return 0;
  573. }
  574. }
  575. break;
  576. }
  577. return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  578. }
  579. LRESULT CALLBACK CNotificationsDlg::s_ComboBoxSubClassWndProc( HWND hwnd, UINT uMsg,
  580. WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData )
  581. {
  582. CNotificationsDlg * pNotificationsDlg = reinterpret_cast<CNotificationsDlg*>(dwRefData);
  583. AssertMsg((pNotificationsDlg != NULL), TEXT("pNotificationsDlg SHOULD NOT be NULL."));
  584. switch (uMsg)
  585. {
  586. case WM_KEYDOWN:
  587. {
  588. if (pNotificationsDlg->_fComboBoxActive)
  589. {
  590. if (wParam == VK_LEFT)
  591. {
  592. pNotificationsDlg->_fComboBoxActive = FALSE;
  593. pNotificationsDlg->_nIndex = 0;
  594. ::SetFocus(pNotificationsDlg->_hwndListView);
  595. return 0;
  596. }
  597. else if (wParam == VK_RIGHT)
  598. {
  599. // Disable selection in combo on right button
  600. return 0;
  601. }
  602. }
  603. }
  604. break;
  605. case WM_KILLFOCUS:
  606. {
  607. if (pNotificationsDlg->_fComboBoxActive)
  608. {
  609. pNotificationsDlg->_fComboBoxActive = FALSE;
  610. pNotificationsDlg->_nIndex = 0;
  611. }
  612. }
  613. break;
  614. }
  615. return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  616. }
  617. void CNotificationsDlg::ApplyChanges(void)
  618. {
  619. if (!_fItemChanged)
  620. return;
  621. if (_pTrayNotify)
  622. {
  623. for (int i = 0; i < _saItems.GetSize(); i++)
  624. {
  625. _pTrayNotify->SetPreference(&_saItems[i]);
  626. }
  627. }
  628. }
  629. void CNotificationsDlg::_ShowComboBox(void)
  630. {
  631. int nCurIndex = _GetCurSel();
  632. if (!_fComboBoxActive && nCurIndex == -1)
  633. {
  634. ::ShowWindow(_hwndCombo, SW_HIDE);
  635. }
  636. else if (nCurIndex != -1)
  637. {
  638. RECT rcListView;
  639. ::GetClientRect(_hwndListView, &rcListView);
  640. RECT rc;
  641. ListView_GetItemRect(_hwndListView, nCurIndex, &rc, LVIR_BOUNDS);
  642. RECT rcHeader;
  643. HWND hwndHeader = ListView_GetHeader(_hwndListView);
  644. Header_GetItemRect(hwndHeader, 1, &rcHeader);
  645. rc.left = rcHeader.left;
  646. rc.right = rcHeader.right;
  647. if (!EqualRect(&_rcOldPos, &rc))
  648. {
  649. _rcOldPos = rc;
  650. ::MoveWindow(_hwndCombo, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
  651. }
  652. if (!::IsWindowVisible(_hwndCombo))
  653. {
  654. ::ShowWindow(_hwndCombo, SW_SHOW);
  655. ComboBox_SetCurSel(_hwndCombo, _saItems[nCurIndex].dwUserPref);
  656. }
  657. }
  658. }
  659. //This is the property sheet for all of the task bar stuff
  660. class CTaskBarPropertySheet : public CPropertySheetImpl<CTaskBarPropertySheet>
  661. {
  662. public:
  663. CTaskBarPropertySheet(UINT nStartPage, HWND hwndParent, DWORD dwFlags) :
  664. CPropertySheetImpl<CTaskBarPropertySheet>((LPCTSTR)NULL, nStartPage, hwndParent),
  665. _dwFlags(dwFlags)
  666. {
  667. LoadString(hinstCabinet, IDS_STARTMENUANDTASKBAR, szPath, ARRAYSIZE(szPath));
  668. SetTitle(szPath);
  669. HPROPSHEETPAGE hpage;
  670. PROPSHEETPAGE psp;
  671. psp.dwSize = sizeof(psp);
  672. psp.dwFlags = PSP_DEFAULT;
  673. psp.hInstance = hinstCabinet;
  674. //taskbar page
  675. psp.pszTemplate = MAKEINTRESOURCE(DLG_TRAY_OPTIONS);
  676. psp.pfnDlgProc = s_TaskbarOptionsDlgProc;
  677. psp.lParam = (LPARAM) this;
  678. hpage = CreatePropertySheetPage(&psp);
  679. if (hpage)
  680. AddPage(hpage);
  681. //start page
  682. psp.pszTemplate = MAKEINTRESOURCE(DLG_START);
  683. psp.pfnDlgProc = s_StartMenuDlgProc;
  684. psp.lParam = (LPARAM) this;
  685. hpage = CreatePropertySheetPage(&psp);
  686. if (hpage)
  687. AddPage(hpage);
  688. //
  689. // We really want to have the tree-options work like the StartPageOptionHelper class above, but
  690. // it stores state in the treeview, which goes away when the child dialog is closed. So for now,
  691. // have it save when the customize dialog is closed, not when the parent is closed.
  692. // Still, have the lifetime of the object be controlled by the parent.
  693. //
  694. if (FAILED(CoCreateInstance(CLSID_CRegTreeOptions, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IRegTreeOptions, &_Adv.pTO))))
  695. {
  696. TraceMsg(TF_WARNING, "ctbps failed to create CRegTreeOptions");
  697. }
  698. _pDlgNotify = new CComObject<CNotificationsDlg>;
  699. if (_pDlgNotify)
  700. {
  701. _pDlgNotify->AddRef();
  702. }
  703. }
  704. ~CTaskBarPropertySheet()
  705. {
  706. ATOMICRELEASE(_Adv.pTO);
  707. ATOMICRELEASE(_pDlgNotify);
  708. }
  709. // We aren't handling any messages special, so we just make an empty map
  710. DECLARE_EMPTY_MSG_MAP()
  711. private:
  712. // dlgproc's for the various pages
  713. static BOOL_PTR s_TaskbarOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  714. static BOOL_PTR s_StartMenuDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  715. BOOL_PTR TaskbarOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  716. BOOL_PTR StartMenuDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  717. void _ApplyTaskbarOptionsFromDialog(HWND hDlg);
  718. void _ApplyStartOptionsFromDialog(HWND hDlg);
  719. // for the old style customize dialog
  720. SMADVANCED _Adv;
  721. //need to keep storage for the title until the property sheet is created
  722. TCHAR szPath[MAX_PATH];
  723. CComObject<CNotificationsDlg>* _pDlgNotify;
  724. DWORD _dwFlags;
  725. };
  726. //
  727. // RegSaveDefaultClient
  728. //
  729. void RegSaveDefaultClient(HWND hwndCB, LPCTSTR pszPath)
  730. {
  731. int iSelected = ComboBox_GetCurSel(hwndCB);
  732. if (iSelected >= 0)
  733. {
  734. LPTSTR pszKey = (LPTSTR)ComboBox_GetItemData(hwndCB, iSelected);
  735. if (pszKey)
  736. {
  737. if (SHSetValue(HKEY_CURRENT_USER, pszPath, NULL, REG_SZ, pszKey, sizeof(TCHAR) * (1 + lstrlen(pszKey))) == ERROR_SUCCESS)
  738. {
  739. SHSendMessageBroadcast(WM_SETTINGCHANGE, 0, (LPARAM)pszPath);
  740. }
  741. }
  742. }
  743. }
  744. BOOL RegGetDefaultClient(HWND hwndCB, HKEY hkRoot, LPCTSTR pszPath)
  745. {
  746. TCHAR szCurrent[MAX_PATH];
  747. LONG cb = sizeof(szCurrent);
  748. cb = sizeof(szCurrent);
  749. if (RegQueryValue(hkRoot, pszPath, szCurrent, &cb) != ERROR_SUCCESS ||
  750. szCurrent[0] == TEXT('\0'))
  751. {
  752. return FALSE;
  753. }
  754. // Now make sure the selected client exists
  755. int i = ComboBox_GetCount(hwndCB);
  756. while (--i >= 0)
  757. {
  758. LPTSTR pszKey = (LPTSTR)ComboBox_GetItemData(hwndCB, i);
  759. // Use StrCmpIC so we don't get faked out by Hungarian locale...
  760. if (pszKey && StrCmpIC(pszKey, szCurrent) == 0)
  761. {
  762. ComboBox_SetCurSel(hwndCB, i);
  763. return TRUE;
  764. }
  765. }
  766. return FALSE;
  767. }
  768. void RegPopulateComboBox(HWND hwndCB, LPCTSTR pszPath)
  769. {
  770. TCHAR szFriendlyName [MAX_PATH];
  771. TCHAR szKeyName [MAX_PATH];
  772. DWORD i; // Index counter
  773. HKEY hkeyProtocol;
  774. // See if the clients key even exists...
  775. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszPath, 0, KEY_READ, &hkeyProtocol) != ERROR_SUCCESS)
  776. return;
  777. // populate the dropdown
  778. for(i=0; // always start with 0
  779. ERROR_SUCCESS==RegEnumKey(hkeyProtocol, i, szKeyName, ARRAYSIZE(szKeyName));
  780. i++) // get next entry
  781. {
  782. // get the friendly name of the client
  783. if (SUCCEEDED(SHLoadLegacyRegUIString(hkeyProtocol, szKeyName, szFriendlyName, ARRAYSIZE(szFriendlyName))))
  784. {
  785. // save its key name so we can find it later
  786. LPTSTR pszKeyName = StrDup(szKeyName);
  787. if (pszKeyName)
  788. {
  789. // add name to dropdown
  790. int iAdded = ComboBox_AddString(hwndCB, szFriendlyName);
  791. if (iAdded >= 0)
  792. {
  793. ComboBox_SetItemData(hwndCB, iAdded, pszKeyName);
  794. }
  795. else
  796. {
  797. LocalFree(pszKeyName);
  798. }
  799. }
  800. }
  801. }
  802. RegCloseKey(hkeyProtocol);
  803. // Do this after populating the dropdown because we need to look into
  804. // the dropdown to see if the current value is valid or not
  805. //
  806. // First try HKCU; then try HKLM...
  807. //
  808. if (!RegGetDefaultClient(hwndCB, HKEY_CURRENT_USER, pszPath))
  809. {
  810. RegGetDefaultClient(hwndCB, HKEY_LOCAL_MACHINE, pszPath);
  811. }
  812. }
  813. void RegClearClientComboBox(HWND hDlg, UINT idc)
  814. {
  815. HWND hwndCB = GetDlgItem(hDlg, idc);
  816. int i = ComboBox_GetCount(hwndCB);
  817. while (--i >= 0)
  818. {
  819. LPTSTR pszKey = (LPTSTR)ComboBox_GetItemData(hwndCB, i);
  820. LocalFree(pszKey);
  821. }
  822. }
  823. void HandleClearButtonClick(HWND hwndClear);
  824. void SetDocButton(HWND hDlg, int id);
  825. //This is the property sheet for the "Customize Simple Start Menu" dlg
  826. class CCustomizeSPPropSheet : public CPropertySheetImpl<CCustomizeSPPropSheet>
  827. {
  828. public:
  829. CCustomizeSPPropSheet(HWND hwndParent) :
  830. CPropertySheetImpl<CCustomizeSPPropSheet>((LPCTSTR)NULL, 0, hwndParent)
  831. , _fInsideInit(FALSE)
  832. {
  833. HPROPSHEETPAGE hpage;
  834. PROPSHEETPAGE psp;
  835. // We are heap-allocated so these should be pre-initialized properly
  836. ASSERT(_bDirtyTree == FALSE);
  837. ASSERT(_prto == NULL);
  838. ASSERT(_pph == NULL);
  839. LoadString(hinstCabinet, IDS_SPCUST_TITLE, _szTitle, ARRAYSIZE(_szTitle));
  840. SetTitle(_szTitle);
  841. m_psh.dwFlags |= PSH_NOAPPLYNOW;
  842. psp.dwSize = sizeof(psp);
  843. psp.dwFlags = PSP_DEFAULT;
  844. psp.hInstance = hinstCabinet;
  845. //General page
  846. psp.pszTemplate = MAKEINTRESOURCE(DLG_PAGE_SMGENERAL);
  847. psp.pfnDlgProc = s_GeneralTabDlgProc;
  848. psp.lParam = (LPARAM) this;
  849. hpage = CreatePropertySheetPage(&psp);
  850. if (hpage)
  851. AddPage(hpage);
  852. //Advanced page
  853. psp.pszTemplate = MAKEINTRESOURCE(DLG_PAGE_SMADVANCED);
  854. psp.pfnDlgProc = s_AdvancedTabDlgProc;
  855. psp.lParam = (LPARAM) this;
  856. hpage = CreatePropertySheetPage(&psp);
  857. if (hpage)
  858. AddPage(hpage);
  859. };
  860. ~CCustomizeSPPropSheet()
  861. {
  862. if (_pph)
  863. delete _pph;
  864. ATOMICRELEASE(_prto);
  865. }
  866. private:
  867. // dlgproc's for the various pages
  868. static BOOL_PTR s_GeneralTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  869. static BOOL_PTR s_AdvancedTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  870. BOOL_PTR GeneralTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  871. BOOL_PTR AdvancedTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  872. BOOL GeneralTabInit(HWND hDlg);
  873. BOOL AdvancedTabInit(HWND hDlg);
  874. BOOL OnCommand(UINT id, UINT code, HWND hwndCtl, HWND hwndDlg); // shared command handler
  875. BOOL OnGeneralApply(HWND hwndDlg);
  876. BOOL_PTR OnAdvancedNotify(HWND hwndDlg, NMHDR * pnm);
  877. BOOL_PTR OnAdvancedHelp(HWND hDlg, HELPINFO *phi);
  878. void _InitMagicEntries();
  879. void _SaveMagicEntries();
  880. //helpers
  881. DWORD _ReadStartPageSetting(LPCTSTR pszVal, DWORD dwDefault)
  882. {
  883. DWORD dw, cb=sizeof(dw), dwType;
  884. SHRegGetUSValue(REGSTR_PATH_STARTPANE_SETTINGS, pszVal, &dwType, &dw, &cb, FALSE, &dwDefault, sizeof(dwDefault));
  885. return dw; // since we passed a default value, above fn will return our default on failure
  886. }
  887. BOOL _ReadStartPageCUSetting(LPCTSTR pszVal, DWORD *pdw) // returns TRUE/FALSE for present under CU or not, actual value in pdw
  888. {
  889. DWORD cb=sizeof(*pdw), dwType;
  890. return NO_ERROR == SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_STARTPANE_SETTINGS, pszVal, &dwType, pdw, &cb);
  891. }
  892. BOOL _WriteStartPageSetting(LPCTSTR pszVal, DWORD dwVal)
  893. {
  894. return SHSetValue(HKEY_CURRENT_USER, REGSTR_PATH_STARTPANE_SETTINGS, pszVal, REG_DWORD, &dwVal, sizeof(DWORD)) == NO_ERROR;
  895. }
  896. BOOL _ClearStartPageSetting(LPCTSTR pszVal)
  897. {
  898. return SHDeleteValue(HKEY_CURRENT_USER, REGSTR_PATH_STARTPANE_SETTINGS, pszVal) == NO_ERROR;
  899. }
  900. // State
  901. BOOL _bLargeIcons;
  902. IRegTreeOptions *_prto;
  903. // Dirty Flags
  904. BOOL _bDirtyTree; // to avoid saving the tree if we don't need to
  905. BOOL _bDirtyClients; // to avoid saving the clients if we don't need to
  906. BOOL _bDirtyPinList; // to avoid re-persisting the pin list (and possibly changing the order)
  907. BOOL _bCustNetPlaces; // Did the user previously have net places customized?
  908. BOOL _bCustNetConn; // Did the user previously have net connections customized?
  909. // random bits
  910. CPinHelper *_pph;
  911. TCHAR _szTitle[80]; // needed for the propsheet title...
  912. // We need this to take care of initialization!
  913. BOOL _fInsideInit;
  914. };
  915. BOOL_PTR CCustomizeSPPropSheet::s_GeneralTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  916. {
  917. CCustomizeSPPropSheet* self = NULL;
  918. if (uMsg == WM_INITDIALOG)
  919. {
  920. ::SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  921. self = (CCustomizeSPPropSheet*) ((PROPSHEETPAGE*)lParam)->lParam;
  922. }
  923. else
  924. {
  925. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)::GetWindowLongPtr(hDlg, DWLP_USER);
  926. if (psp)
  927. self = (CCustomizeSPPropSheet*)psp->lParam;
  928. }
  929. if (self)
  930. {
  931. return self->GeneralTabDlgProc(hDlg, uMsg, wParam, lParam);
  932. }
  933. else
  934. {
  935. return FALSE;
  936. }
  937. }
  938. BOOL_PTR CCustomizeSPPropSheet::s_AdvancedTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  939. {
  940. CCustomizeSPPropSheet* self = NULL;
  941. if (uMsg == WM_INITDIALOG)
  942. {
  943. ::SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  944. self = (CCustomizeSPPropSheet*) ((PROPSHEETPAGE*)lParam)->lParam;
  945. }
  946. else
  947. {
  948. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)::GetWindowLongPtr(hDlg, DWLP_USER);
  949. if (psp)
  950. self = (CCustomizeSPPropSheet*)psp->lParam;
  951. }
  952. if (self)
  953. {
  954. return self->AdvancedTabDlgProc(hDlg, uMsg, wParam, lParam);
  955. }
  956. else
  957. {
  958. return FALSE;
  959. }
  960. }
  961. BOOL_PTR CCustomizeSPPropSheet::GeneralTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  962. {
  963. switch (uMsg)
  964. {
  965. case WM_INITDIALOG:
  966. return GeneralTabInit(hDlg);
  967. case WM_COMMAND:
  968. return OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND) lParam, hDlg);
  969. case WM_DESTROY:
  970. {
  971. SetDlgItemIcon(hDlg, IDC_SPCUST_ICONSMALL, NULL);
  972. SetDlgItemIcon(hDlg, IDC_SPCUST_ICONLARGE, NULL);
  973. RegClearClientComboBox(hDlg, IDC_SPCUST_EMAILCB);
  974. RegClearClientComboBox(hDlg, IDC_SPCUST_INTERNETCB);
  975. break;
  976. }
  977. case WM_NOTIFY:
  978. switch (((NMHDR*)lParam)->code)
  979. {
  980. case PSN_APPLY:
  981. return OnGeneralApply(hDlg);
  982. }
  983. break;
  984. case WM_HELP:
  985. ::WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aStartCustGeneralTabHelpIDs);
  986. break;
  987. case WM_CONTEXTMENU:
  988. ::WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aStartCustGeneralTabHelpIDs);
  989. break;
  990. }
  991. return FALSE;
  992. }
  993. BOOL CCustomizeSPPropSheet::GeneralTabInit(HWND hDlg)
  994. {
  995. _fInsideInit = TRUE; //We are getting inside initilization!
  996. ::SendMessage(::GetDlgItem(hDlg, IDC_SPCUST_MINPROGS_ARROW), UDM_SETRANGE, 0, (LPARAM)MAKELONG(MAX_PROGS_ALLOWED, 0));
  997. // set up icon size
  998. _bLargeIcons = _ReadStartPageSetting(REGSTR_VAL_DV2_LARGEICONS, /*bDefault*/ TRUE);
  999. ::CheckDlgButton(hDlg, IDC_SPCUST_LARGE, _bLargeIcons);
  1000. ::CheckDlgButton(hDlg, IDC_SPCUST_SMALL, !_bLargeIcons);
  1001. SetProgramIcon(hDlg, IDC_SPCUST_ICONLARGE, IDC_SPCUST_ICONSMALL);
  1002. // Set up the Number of programs dropdown
  1003. DWORD dwMinMFU = _ReadStartPageSetting(REGSTR_VAL_DV2_MINMFU, REGSTR_VAL_DV2_MINMFU_DEFAULT);
  1004. ::SetDlgItemInt(hDlg, IDC_SPCUST_MINPROGS, dwMinMFU, FALSE);
  1005. // Set up internet, email checkboxes and comboboxes
  1006. BOOL bInternet=FALSE, bMail=FALSE;
  1007. RegPopulateComboBox(::GetDlgItem(hDlg, IDC_SPCUST_EMAILCB), TEXT("SOFTWARE\\Clients\\mail"));
  1008. RegPopulateComboBox(::GetDlgItem(hDlg, IDC_SPCUST_INTERNETCB), TEXT("SOFTWARE\\Clients\\StartMenuInternet"));
  1009. // if this fails, its not fatal, we just won't be able to persist the pin info
  1010. _pph = new CPinHelper();
  1011. if (_pph)
  1012. {
  1013. _pph->GetPinInfo(&bInternet, &bMail);
  1014. }
  1015. ::CheckDlgButton(hDlg, IDC_SPCUST_INTERNET, bInternet);
  1016. ::CheckDlgButton(hDlg, IDC_SPCUST_EMAIL, bMail);
  1017. ::EnableWindow(::GetDlgItem(hDlg, IDC_SPCUST_INTERNETCB), bInternet);
  1018. ::EnableWindow(::GetDlgItem(hDlg, IDC_SPCUST_EMAILCB), bMail);
  1019. _fInsideInit = FALSE; //We are done initializing.
  1020. return TRUE;
  1021. }
  1022. // Temp until the new UEM code gets in...
  1023. void ClearUEMData()
  1024. {
  1025. HKEY hk;
  1026. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER TEXT("\\UserAssist\\{75048700-EF1F-11D0-9888-006097DEACF9}\\Count"),
  1027. 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_SET_VALUE,
  1028. &hk))
  1029. {
  1030. int cValues;
  1031. if (ERROR_SUCCESS == RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, (DWORD*) &cValues, NULL, NULL, NULL, NULL))
  1032. {
  1033. while (cValues >= 0)
  1034. {
  1035. TCHAR szValue[MAX_PATH];
  1036. DWORD cch = ARRAYSIZE(szValue);
  1037. DWORD cbData;
  1038. if (ERROR_SUCCESS != RegEnumValue(hk, --cValues, szValue, &cch, NULL, NULL, NULL, &cbData))
  1039. break;
  1040. // don't nuke the session value
  1041. if (cbData > 8)
  1042. RegDeleteValue(hk, szValue);
  1043. }
  1044. #ifdef DEBUG
  1045. RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, (DWORD*) &cValues, NULL, NULL, NULL, NULL);
  1046. ASSERT(cValues == 1); // the session info value should still exist
  1047. #endif
  1048. }
  1049. RegCloseKey(hk);
  1050. // Set the "Apps installed prior to this point are not interesting"
  1051. // to the current time. Since we deleted all the usages, we have to
  1052. // do something to prevent all the user's apps from being redetected
  1053. // as "newly installed and not yet run".
  1054. FILETIME ftNow;
  1055. GetSystemTimeAsFileTime(&ftNow);
  1056. SHRegSetUSValue(DV2_REGPATH, DV2_SYSTEM_START_TIME, REG_BINARY,
  1057. &ftNow, sizeof(ftNow), SHREGSET_FORCE_HKCU);
  1058. // Start a new session - this kick-starts anybody who is listening
  1059. // to UEM events to tell them their cache is invalid
  1060. UEMFireEvent(&UEMIID_SHELL, UEME_CTLSESSION, UEMF_XEVENT, TRUE, -1);
  1061. }
  1062. }
  1063. void AdjustNumOfProgsOnStartMenu(HWND hwndDlg, UINT Id)
  1064. {
  1065. BOOL fTranslated;
  1066. int iNumOfProgs = (int)GetDlgItemInt(hwndDlg, Id, &fTranslated, FALSE);
  1067. int iNewNumOfProgs = min(max(iNumOfProgs, 0), MAX_PROGS_ALLOWED);
  1068. if((iNumOfProgs != iNewNumOfProgs) || (!fTranslated))
  1069. {
  1070. SetDlgItemInt(hwndDlg, Id, (UINT)iNewNumOfProgs, FALSE);
  1071. SendPSMChanged(hwndDlg);
  1072. }
  1073. }
  1074. // NOTE - shared WM_COMMAND handler
  1075. //
  1076. BOOL CCustomizeSPPropSheet::OnCommand(UINT id, UINT code, HWND hwndCtl, HWND hwndDlg)
  1077. {
  1078. switch (id)
  1079. {
  1080. ////// General Tab Controls
  1081. case IDC_SPCUST_LARGE:
  1082. case IDC_SPCUST_SMALL:
  1083. _bLargeIcons = (id == IDC_SPCUST_LARGE);
  1084. SendPSMChanged(hwndDlg);
  1085. return FALSE;
  1086. case IDC_SPCUST_MINPROGS:
  1087. if(code == EN_KILLFOCUS)
  1088. AdjustNumOfProgsOnStartMenu(hwndDlg, id);
  1089. else
  1090. {
  1091. if ((_fInsideInit == FALSE) && (code == EN_CHANGE))
  1092. SendPSMChanged(hwndDlg);
  1093. }
  1094. return FALSE;
  1095. case IDB_SPCUST_CLEARPROG:
  1096. ClearUEMData();
  1097. return FALSE;
  1098. case IDC_SPCUST_INTERNET:
  1099. case IDC_SPCUST_EMAIL:
  1100. COMPILETIME_ASSERT(IDC_SPCUST_INTERNETCB == IDC_SPCUST_INTERNET+1);
  1101. COMPILETIME_ASSERT(IDC_SPCUST_EMAILCB == IDC_SPCUST_EMAIL+1);
  1102. ::EnableWindow(::GetDlgItem(hwndDlg, id+1), ::IsDlgButtonChecked(hwndDlg, id));
  1103. _bDirtyPinList = TRUE;
  1104. SendPSMChanged(hwndDlg);
  1105. return FALSE;
  1106. case IDC_SPCUST_INTERNETCB:
  1107. case IDC_SPCUST_EMAILCB:
  1108. if (code == CBN_SELCHANGE)
  1109. {
  1110. _bDirtyClients = TRUE;
  1111. SendPSMChanged(hwndDlg);
  1112. }
  1113. return FALSE;
  1114. ////// Advanced Tab Controls
  1115. case IDC_SPCUST_RECENT:
  1116. SendPSMChanged(hwndDlg);
  1117. return FALSE;
  1118. case IDB_SPCUST_CLEARDOCS:
  1119. HandleClearButtonClick(hwndCtl);
  1120. return FALSE;
  1121. case IDC_SPCUST_HOVEROPEN:
  1122. case IDC_SPCUST_NOTIFYNEW:
  1123. SendPSMChanged(hwndDlg);
  1124. return FALSE;
  1125. break;
  1126. }
  1127. return TRUE;
  1128. }
  1129. BOOL CCustomizeSPPropSheet::OnGeneralApply(HWND hDlg)
  1130. {
  1131. TraceMsg(TF_ALWAYS, "cspps.General apply", _bDirtyTree);
  1132. _WriteStartPageSetting(REGSTR_VAL_DV2_LARGEICONS, _bLargeIcons);
  1133. if (_pph && _bDirtyPinList)
  1134. {
  1135. BOOL bInternet = ::IsDlgButtonChecked(hDlg, IDC_SPCUST_INTERNET);
  1136. BOOL bMail = ::IsDlgButtonChecked(hDlg, IDC_SPCUST_EMAIL);
  1137. _pph->Save(bMail, bInternet);
  1138. }
  1139. if (_bDirtyClients)
  1140. {
  1141. // persist Internet, Mail comboboxes
  1142. RegSaveDefaultClient(::GetDlgItem(hDlg, IDC_SPCUST_EMAILCB), TEXT("Software\\Clients\\mail"));
  1143. RegSaveDefaultClient(::GetDlgItem(hDlg, IDC_SPCUST_INTERNETCB), TEXT("SOFTWARE\\Clients\\StartMenuInternet"));
  1144. }
  1145. BOOL bTranslated;
  1146. DWORD dwMinMFU = ::GetDlgItemInt(hDlg, IDC_SPCUST_MINPROGS, &bTranslated, FALSE);
  1147. if (EVAL(bTranslated))
  1148. {
  1149. dwMinMFU = min(max(dwMinMFU, 0), MAX_PROGS_ALLOWED);
  1150. _WriteStartPageSetting(REGSTR_VAL_DV2_MINMFU, dwMinMFU);
  1151. }
  1152. return TRUE;
  1153. }
  1154. BOOL_PTR CCustomizeSPPropSheet::OnAdvancedNotify(HWND hwndDlg, NMHDR * pnm)
  1155. {
  1156. ::SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, 0); // handled
  1157. switch (pnm->code)
  1158. {
  1159. case PSN_APPLY:
  1160. TraceMsg(TF_ALWAYS, "cspps.Advanced apply - _bDirtyTree=%d", _bDirtyTree);
  1161. if (_bDirtyTree)
  1162. {
  1163. _prto->WalkTree(WALK_TREE_SAVE);
  1164. }
  1165. _WriteStartPageSetting(REGSTR_VAL_DV2_SHOWRECDOCS, ::IsDlgButtonChecked(hwndDlg, IDC_SPCUST_RECENT) ? 2 : 0); // 2 so that it cascades
  1166. _WriteStartPageSetting(REGSTR_VAL_DV2_AUTOCASCADE, ::IsDlgButtonChecked(hwndDlg, IDC_SPCUST_HOVEROPEN));
  1167. _WriteStartPageSetting(REGSTR_VAL_DV2_NOTIFYNEW, ::IsDlgButtonChecked(hwndDlg, IDC_SPCUST_NOTIFYNEW));
  1168. // fall through to PSN_RESET case...
  1169. case PSN_RESET:
  1170. _SaveMagicEntries(); // this must be called on both cancel and apply, so that it cleans up properly...
  1171. break;
  1172. case TVN_KEYDOWN:
  1173. {
  1174. TV_KEYDOWN *pnmtv = (TV_KEYDOWN*)pnm;
  1175. if (pnmtv->wVKey == VK_SPACE)
  1176. {
  1177. HWND hwndTree = ::GetDlgItem(hwndDlg, IDC_STARTMENUSETTINGS);
  1178. _prto->ToggleItem((HTREEITEM)SendMessage(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, 0L));
  1179. _bDirtyTree = TRUE;
  1180. SendPSMChanged(hwndDlg);
  1181. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); // eat the key
  1182. }
  1183. break;
  1184. }
  1185. case NM_CLICK:
  1186. case NM_DBLCLK:
  1187. // is this click in our tree?
  1188. if ( pnm->idFrom == IDC_STARTMENUSETTINGS )
  1189. {
  1190. HWND hwndTree = ::GetDlgItem(hwndDlg, IDC_STARTMENUSETTINGS);
  1191. TV_HITTESTINFO ht;
  1192. DWORD dwPos = GetMessagePos(); // get where we were hit
  1193. ht.pt.x = GET_X_LPARAM(dwPos);
  1194. ht.pt.y = GET_Y_LPARAM(dwPos);
  1195. ::ScreenToClient(hwndTree, &ht.pt); // translate it to our window
  1196. // retrieve the item hit
  1197. HTREEITEM hti = TreeView_HitTest(hwndTree, &ht);
  1198. if (hti)
  1199. {
  1200. _prto->ToggleItem(hti);
  1201. _bDirtyTree = TRUE;
  1202. SendPSMChanged(hwndDlg);
  1203. }
  1204. }
  1205. break;
  1206. // no help yet- needs ids/text from UA
  1207. #if 0
  1208. case NM_RCLICK: // right mouse click
  1209. if (pnm->hwndFrom == hwndTree)
  1210. {
  1211. _DoTreeHelp(pAdv, (WPARAM)pnm->hwndFrom);
  1212. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); // eat the click
  1213. return TRUE;
  1214. }
  1215. break;
  1216. #endif
  1217. }
  1218. return TRUE;
  1219. }
  1220. BOOL_PTR CCustomizeSPPropSheet::OnAdvancedHelp(HWND hDlg, HELPINFO *phi)
  1221. {
  1222. if (phi->iCtrlId != IDC_STARTMENUSETTINGS)
  1223. {
  1224. ::WinHelp((HWND)(phi->hItemHandle), NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)aStartCustAdvancedTabHelpIDs);
  1225. }
  1226. else
  1227. {
  1228. HTREEITEM hItem;
  1229. HWND hwndTree = ::GetDlgItem(hDlg, IDC_STARTMENUSETTINGS);
  1230. //Is this help invoked throught F1 key
  1231. if (GetAsyncKeyState(VK_F1) < 0)
  1232. {
  1233. // Yes. WE need to give help for the currently selected item
  1234. hItem = TreeView_GetSelection(hwndTree);
  1235. }
  1236. else
  1237. {
  1238. //No, We need to give help for the item at the cursor position
  1239. TV_HITTESTINFO ht;
  1240. ht.pt = phi->MousePos;
  1241. ::ScreenToClient(hwndTree, &ht.pt); // Translate it to our window
  1242. hItem = TreeView_HitTest(hwndTree, &ht);
  1243. }
  1244. if (hItem)
  1245. _prto->ShowHelp(hItem, HELP_WM_HELP);
  1246. }
  1247. return TRUE;
  1248. }
  1249. BOOL_PTR CCustomizeSPPropSheet::AdvancedTabDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1250. {
  1251. switch (uMsg)
  1252. {
  1253. case WM_INITDIALOG:
  1254. return AdvancedTabInit(hDlg);
  1255. case WM_COMMAND:
  1256. return OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND) lParam, hDlg);
  1257. case WM_NOTIFY:
  1258. return OnAdvancedNotify(hDlg, (NMHDR*)lParam);
  1259. case WM_HELP:
  1260. return OnAdvancedHelp(hDlg, (HELPINFO*) lParam);
  1261. break;
  1262. case WM_CONTEXTMENU:
  1263. ::WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aStartCustAdvancedTabHelpIDs);
  1264. break;
  1265. }
  1266. return FALSE;
  1267. }
  1268. int DefaultNetConValue()
  1269. {
  1270. return ShouldShowConnectTo() ? 2 : 0; // default to menu-style (2)
  1271. }
  1272. int DefaultNetPlacesValue()
  1273. {
  1274. return ShouldShowNetPlaces() ? 1 : 0; // default to link -style (1)
  1275. }
  1276. // These two "magic" functions maintain the proper behavior of the network places and network connections settings
  1277. // which, by default, turn on when there are n or more items in the folder. But they can also be customized by the
  1278. // user to force them on or off.
  1279. void CCustomizeSPPropSheet::_InitMagicEntries()
  1280. {
  1281. BOOL bNewNetPlaces;
  1282. BOOL bNewNetConn;
  1283. _bCustNetPlaces = _ReadStartPageCUSetting(REGSTR_VAL_DV2_SHOWNETPL, (DWORD*) &bNewNetPlaces);
  1284. _bCustNetConn = _ReadStartPageCUSetting(REGSTR_VAL_DV2_SHOWNETCONN, (DWORD*) &bNewNetConn);
  1285. // if the user didn't previously customize these settings, then use the auto-magic setting
  1286. if (!_bCustNetPlaces)
  1287. bNewNetPlaces = DefaultNetPlacesValue();
  1288. if (!_bCustNetConn)
  1289. bNewNetConn = DefaultNetConValue();
  1290. // Write it out, so the rgtreeoption control will reflect either the user's customization, or the magic value
  1291. _WriteStartPageSetting(REGSTR_VAL_DV2_SHOWNETPL, bNewNetPlaces);
  1292. _WriteStartPageSetting(REGSTR_VAL_DV2_SHOWNETCONN, bNewNetConn);
  1293. // for the admin tools radio buttons:
  1294. // 0 = don't show anywhere
  1295. // 1 = display in all programs (StartMenuAdminTools = 1, Start_AdminToolsRoot = 0)
  1296. // 2 = display in all programs and root (StartMenuAdminTools = 1, Start_AdminToolsRoot = 2)
  1297. int iAdminToolsTemp = _ReadStartPageSetting(REGSTR_VAL_DV2_ADMINTOOLSROOT, FALSE) ? 2 :
  1298. (_ReadStartPageSetting(TEXT("StartMenuAdminTools"), FALSE) ? 1 : 0);
  1299. _WriteStartPageSetting(REGSTR_VAL_ADMINTOOLSTEMP, iAdminToolsTemp);
  1300. }
  1301. void CCustomizeSPPropSheet::_SaveMagicEntries()
  1302. {
  1303. BOOL bNewNetPlaces = _ReadStartPageSetting(REGSTR_VAL_DV2_SHOWNETPL, FALSE);
  1304. BOOL bNewNetConn = _ReadStartPageSetting(REGSTR_VAL_DV2_SHOWNETCONN, FALSE);
  1305. // if the user previously had it customized, then we don't need to clear it since it will either
  1306. // contain the original value we loaded in _InitMagicEntries, or the updated value if the user changed it.
  1307. // if it wasn't originally customized, then we need to clear it if the tree isn't even dirty, or the current value is the magic value we loaded
  1308. if (!_bCustNetPlaces && (!_bDirtyTree || bNewNetPlaces == DefaultNetPlacesValue()))
  1309. _ClearStartPageSetting(REGSTR_VAL_DV2_SHOWNETPL);
  1310. if (!_bCustNetConn && (!_bDirtyTree || bNewNetConn == DefaultNetConValue()))
  1311. _ClearStartPageSetting(REGSTR_VAL_DV2_SHOWNETCONN);
  1312. if (_bDirtyTree)
  1313. {
  1314. // see comment above for how this should work
  1315. int iAdminToolsTemp = _ReadStartPageSetting(REGSTR_VAL_ADMINTOOLSTEMP, FALSE);
  1316. int iATRoot = 0;
  1317. int iATPrograms = 0;
  1318. if (iAdminToolsTemp >= 1)
  1319. {
  1320. iATPrograms = 1;
  1321. if (iAdminToolsTemp == 2)
  1322. {
  1323. iATRoot = 2;
  1324. }
  1325. }
  1326. _WriteStartPageSetting(REGSTR_VAL_DV2_ADMINTOOLSROOT, iATRoot);
  1327. _WriteStartPageSetting(TEXT("StartMenuAdminTools"), iATPrograms);
  1328. }
  1329. _ClearStartPageSetting(REGSTR_VAL_ADMINTOOLSTEMP);
  1330. }
  1331. BOOL CCustomizeSPPropSheet::AdvancedTabInit(HWND hDlg)
  1332. {
  1333. if (SUCCEEDED(CoCreateInstance(CLSID_CRegTreeOptions, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IRegTreeOptions, &_prto))))
  1334. {
  1335. HRESULT hr;
  1336. HWND hwndTV = ::GetDlgItem(hDlg, IDC_STARTMENUSETTINGS);
  1337. // Compute the magic entries before we init the RegTreeOptions
  1338. // (so we will have correct information for him!)
  1339. _InitMagicEntries();
  1340. // HACKHACK - IRegTreeOptions is ANSI, so we temporarily turn off UNICODE
  1341. #undef TEXT
  1342. #define TEXT(s) s
  1343. hr = _prto->InitTree(hwndTV, HKEY_LOCAL_MACHINE, REGSTR_PATH_SMADVANCED "\\StartPanel", NULL);
  1344. #undef TEXT
  1345. #define TEXT(s) __TEXT(s)
  1346. TreeView_SelectSetFirstVisible(hwndTV, TreeView_GetRoot(hwndTV));
  1347. ::CheckDlgButton(hDlg, IDC_SPCUST_RECENT, _ReadStartPageSetting(REGSTR_VAL_DV2_SHOWRECDOCS, IsOS(OS_PERSONAL) ? FALSE : TRUE));
  1348. ::CheckDlgButton(hDlg, IDC_SPCUST_HOVEROPEN,_ReadStartPageSetting(REGSTR_VAL_DV2_AUTOCASCADE, TRUE));
  1349. ::CheckDlgButton(hDlg, IDC_SPCUST_NOTIFYNEW,_ReadStartPageSetting(REGSTR_VAL_DV2_NOTIFYNEW, TRUE));
  1350. if(SHRestricted(REST_NORECENTDOCSMENU))
  1351. {
  1352. //Since this policy is present, hide all the relevant controls
  1353. ::ShowWindow(::GetDlgItem(hDlg, IDC_SPCUST_RECENT_GROUPBOX), FALSE);// Group box
  1354. ::ShowWindow(::GetDlgItem(hDlg, IDC_SPCUST_RECENT_TEXT), FALSE); // Description Text.
  1355. ::ShowWindow(::GetDlgItem(hDlg, IDC_SPCUST_RECENT), FALSE); // Check box
  1356. ::ShowWindow(::GetDlgItem(hDlg, IDB_SPCUST_CLEARDOCS), FALSE); // Clear button.
  1357. }
  1358. SetDocButton(hDlg, IDB_SPCUST_CLEARDOCS);
  1359. return TRUE;
  1360. }
  1361. return FALSE;
  1362. }
  1363. BOOL_PTR CTaskBarPropertySheet::s_TaskbarOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1364. {
  1365. CTaskBarPropertySheet* self = NULL;
  1366. if (uMsg == WM_INITDIALOG)
  1367. {
  1368. ::SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  1369. self = (CTaskBarPropertySheet*) ((PROPSHEETPAGE*)lParam)->lParam;
  1370. }
  1371. else
  1372. {
  1373. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)::GetWindowLongPtr(hDlg, DWLP_USER);
  1374. if (psp)
  1375. self = (CTaskBarPropertySheet*)psp->lParam;
  1376. }
  1377. BOOL_PTR fValue = FALSE;
  1378. if (self)
  1379. {
  1380. self->TaskbarOptionsDlgProc(hDlg, uMsg, wParam, lParam);
  1381. }
  1382. return fValue;
  1383. }
  1384. void _TaskbarOptions_OnInitDialog(HWND hDlg)
  1385. {
  1386. TRAYVIEWOPTS tvo;
  1387. c_tray.GetTrayViewOpts(&tvo);
  1388. CheckDlgButton(hDlg, IDC_QUICKLAUNCH, tvo.fShowQuickLaunch);
  1389. CheckDlgButton(hDlg, IDC_TRAYOPTONTOP, tvo.fAlwaysOnTop);
  1390. CheckDlgButton(hDlg, IDC_TRAYOPTAUTOHIDE, (tvo.uAutoHide & AH_ON));
  1391. CheckDlgButton(hDlg, IDC_TRAYOPTSHOWCLOCK, !tvo.fHideClock);
  1392. if (SHRestricted(REST_HIDECLOCK))
  1393. {
  1394. EnableWindow(GetDlgItem(hDlg, IDC_TRAYOPTSHOWCLOCK), FALSE);
  1395. }
  1396. if (SHRestricted(REST_NOTOOLBARSONTASKBAR))
  1397. {
  1398. EnableWindow(GetDlgItem(hDlg, IDC_QUICKLAUNCH), FALSE);
  1399. }
  1400. // Restriction- either the tray is disabled by policy, or the "smart" auto tray
  1401. // is disabled by policy
  1402. if (tvo.fNoTrayItemsDisplayPolicyEnabled || tvo.fNoAutoTrayPolicyEnabled)
  1403. {
  1404. EnableWindow(GetDlgItem(hDlg, IDC_NOTIFYMAN), FALSE);
  1405. EnableWindow(GetDlgItem(hDlg, IDC_CUSTOMIZE), FALSE);
  1406. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_NOTIFY), FALSE);
  1407. }
  1408. else
  1409. {
  1410. EnableWindow(GetDlgItem(hDlg, IDC_CUSTOMIZE), tvo.fAutoTrayEnabledByUser);
  1411. CheckDlgButton(hDlg, IDC_NOTIFYMAN, tvo.fAutoTrayEnabledByUser);
  1412. }
  1413. CheckDlgButton(hDlg, IDC_LOCKTASKBAR, !_IsSizeMoveEnabled());
  1414. BOOL fEnable = !_IsSizeMoveRestricted();
  1415. EnableWindow(GetDlgItem(hDlg, IDC_LOCKTASKBAR), fEnable);
  1416. if (SHRestricted(REST_NOTASKGROUPING))
  1417. {
  1418. // If there is a restriction of any kine, hide the window
  1419. ShowWindow(GetDlgItem(hDlg, IDC_GROUPITEMS), FALSE);
  1420. }
  1421. else if (SHRegGetBoolUSValue(REGSTR_EXPLORER_ADVANCED, TEXT("TaskbarGlomming"),
  1422. FALSE, TRUE))
  1423. {
  1424. CheckDlgButton(hDlg, IDC_GROUPITEMS, TRUE);
  1425. }
  1426. _TaskbarOptionsSizeControls(hDlg);
  1427. _TaskbarOptionsUpdateDisplay(hDlg);
  1428. }
  1429. BOOL_PTR CTaskBarPropertySheet::TaskbarOptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1430. {
  1431. INSTRUMENT_WNDPROC(SHCNFI_TRAYVIEWOPTIONS_DLGPROC, hDlg, uMsg, wParam, lParam);
  1432. switch (uMsg)
  1433. {
  1434. case WM_COMMAND:
  1435. if (GET_WM_COMMAND_ID(wParam, lParam) == IDC_CUSTOMIZE)
  1436. {
  1437. if (_pDlgNotify)
  1438. {
  1439. _pDlgNotify->DoModal();
  1440. }
  1441. }
  1442. _TaskbarOptionsUpdateDisplay(hDlg);
  1443. SendPSMChanged(hDlg);
  1444. break;
  1445. case WM_INITDIALOG:
  1446. _TaskbarOptions_OnInitDialog(hDlg);
  1447. if (_dwFlags & TPF_INVOKECUSTOMIZE)
  1448. {
  1449. ::PostMessage(hDlg, WM_COMMAND, IDC_CUSTOMIZE, 0);
  1450. }
  1451. break;
  1452. case WM_SYSCOLORCHANGE:
  1453. _TaskbarOptionsUpdateDisplay(hDlg);
  1454. return TRUE;
  1455. case WM_DESTROY:
  1456. _TaskbarOptionsDestroyBitmaps(hDlg);
  1457. break;
  1458. case WM_NOTIFY:
  1459. switch (((NMHDR *)lParam)->code)
  1460. {
  1461. case PSN_APPLY:
  1462. // save settings here
  1463. _ApplyTaskbarOptionsFromDialog(hDlg);
  1464. return TRUE;
  1465. case PSN_KILLACTIVE:
  1466. case PSN_SETACTIVE:
  1467. return TRUE;
  1468. }
  1469. break;
  1470. case WM_HELP:
  1471. ::WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aTaskOptionsHelpIDs);
  1472. break;
  1473. case WM_CONTEXTMENU:
  1474. ::WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aTaskOptionsHelpIDs);
  1475. break;
  1476. }
  1477. return FALSE;
  1478. }
  1479. void _StartOptions_OnInitDialog(HWND hDlg)
  1480. {
  1481. // If StartPanel UI is turned off, then this check box should not show up!
  1482. if (SHRestricted(REST_NOSTARTPANEL))
  1483. {
  1484. //If the restriction exists, then hide this check box.
  1485. ShowWindow(::GetDlgItem(hDlg, IDC_NEWSCHOOL), FALSE);
  1486. ShowWindow(::GetDlgItem(hDlg, IDC_NEWSCHOOLDESCRIPTION), FALSE);
  1487. ShowWindow(::GetDlgItem(hDlg, IDC_NEWSTARTCUSTOMIZE), FALSE);
  1488. // And the only thing you can do is check the OldSchool button
  1489. CheckDlgButton(hDlg, IDC_OLDSCHOOL, TRUE);
  1490. // TODO - PM's need to figure out what to do in the case where new start menu is restricted
  1491. // or not available. This propsheet page is rather pointless in that case...
  1492. SetDlgItemBitmap(hDlg, IDC_STARTMENUPREVIEW, IDB_STARTPREVIEWCLASSIC);
  1493. }
  1494. else
  1495. {
  1496. SHELLSTATE ss = {0};
  1497. SHGetSetSettings(&ss, SSF_STARTPANELON, FALSE);
  1498. CheckDlgButton(hDlg, IDC_NEWSCHOOL, BOOLIFY(ss.fStartPanelOn));
  1499. CheckDlgButton(hDlg, IDC_OLDSCHOOL, !BOOLIFY(ss.fStartPanelOn));
  1500. SetDlgItemBitmap(hDlg, IDC_STARTMENUPREVIEW,
  1501. ss.fStartPanelOn ? IDB_STARTPREVIEWNEW : IDB_STARTPREVIEWCLASSIC);
  1502. // disable "customize" for the style thats off.
  1503. EnableWindow(GetDlgItem(hDlg, ss.fStartPanelOn ? IDC_OLDSTARTCUSTOMIZE : IDC_NEWSTARTCUSTOMIZE), FALSE);
  1504. }
  1505. }
  1506. // On destroy, clean up the bitmaps we loaded so we don't leak them
  1507. void _StartOptions_OnDestroy(HWND hDlg)
  1508. {
  1509. SetDlgItemBitmap(hDlg, IDC_STARTMENUPREVIEW, 0);
  1510. }
  1511. BOOL_PTR CTaskBarPropertySheet::s_StartMenuDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1512. {
  1513. CTaskBarPropertySheet* self = NULL;
  1514. if (uMsg == WM_INITDIALOG)
  1515. {
  1516. ::SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  1517. self = (CTaskBarPropertySheet*) ((PROPSHEETPAGE*)lParam)->lParam;
  1518. }
  1519. else
  1520. {
  1521. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)::GetWindowLongPtr(hDlg, DWLP_USER);
  1522. if (psp)
  1523. self = (CTaskBarPropertySheet*)psp->lParam;
  1524. }
  1525. BOOL_PTR fValue = FALSE;
  1526. if (self)
  1527. {
  1528. self->StartMenuDlgProc(hDlg, uMsg, wParam, lParam);
  1529. }
  1530. return fValue;
  1531. }
  1532. BOOL_PTR CTaskBarPropertySheet::StartMenuDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1533. {
  1534. switch (uMsg)
  1535. {
  1536. case WM_COMMAND:
  1537. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1538. {
  1539. case IDC_NEWSCHOOL:
  1540. case IDC_OLDSCHOOL:
  1541. if (HIWORD(wParam) == BN_CLICKED)
  1542. {
  1543. ::EnableWindow(::GetDlgItem(hDlg, IDC_NEWSTARTCUSTOMIZE), GET_WM_COMMAND_ID(wParam, lParam) == IDC_NEWSCHOOL);
  1544. ::EnableWindow(::GetDlgItem(hDlg, IDC_OLDSTARTCUSTOMIZE), GET_WM_COMMAND_ID(wParam, lParam) == IDC_OLDSCHOOL);
  1545. SetDlgItemBitmap(hDlg, IDC_STARTMENUPREVIEW,
  1546. GET_WM_COMMAND_ID(wParam, lParam) == IDC_NEWSCHOOL ? IDB_STARTPREVIEWNEW : IDB_STARTPREVIEWCLASSIC);
  1547. SendPSMChanged(hDlg);
  1548. }
  1549. break;
  1550. case IDC_NEWSTARTCUSTOMIZE:
  1551. {
  1552. CCustomizeSPPropSheet *pps = new CCustomizeSPPropSheet(hDlg);
  1553. if (pps)
  1554. {
  1555. if (pps->DoModal() == IDOK)
  1556. {
  1557. // if anything changed, let the propsheet know
  1558. SendPSMChanged(hDlg);
  1559. }
  1560. delete pps;
  1561. }
  1562. break;
  1563. }
  1564. case IDC_OLDSTARTCUSTOMIZE:
  1565. {
  1566. if (DialogBoxParam(hinstCabinet, MAKEINTRESOURCE(DLG_STARTMENU_CONFIG), hDlg, AdvancedOptDlgProc, (LPARAM)&_Adv))
  1567. {
  1568. // if anything changed, let the propsheet know
  1569. SendPSMChanged(hDlg);
  1570. }
  1571. break;
  1572. }
  1573. }
  1574. break;
  1575. case WM_INITDIALOG:
  1576. {
  1577. _StartOptions_OnInitDialog(hDlg);
  1578. }
  1579. break;
  1580. case WM_DESTROY:
  1581. _StartOptions_OnDestroy(hDlg);
  1582. break;
  1583. case WM_NOTIFY:
  1584. switch (((NMHDR *)lParam)->code)
  1585. {
  1586. case PSN_APPLY:
  1587. // save settings here
  1588. _ApplyStartOptionsFromDialog(hDlg);
  1589. return TRUE;
  1590. case PSN_KILLACTIVE:
  1591. case PSN_SETACTIVE:
  1592. return TRUE;
  1593. }
  1594. break;
  1595. case WM_HELP:
  1596. ::WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aStartTabHelpIDs);
  1597. break;
  1598. case WM_CONTEXTMENU:
  1599. ::WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (ULONG_PTR)(void *)aStartTabHelpIDs);
  1600. break;
  1601. }
  1602. return FALSE;
  1603. }
  1604. void _UpdateNotifySetting(BOOL fNotifySetting)
  1605. {
  1606. ITrayNotify * pTrayNotify = NULL;
  1607. if (SUCCEEDED(CoCreateInstance(CLSID_TrayNotify, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARG(ITrayNotify, &pTrayNotify))))
  1608. {
  1609. pTrayNotify->EnableAutoTray(fNotifySetting);
  1610. pTrayNotify->Release();
  1611. }
  1612. }
  1613. void CTaskBarPropertySheet ::_ApplyTaskbarOptionsFromDialog(HWND hDlg)
  1614. {
  1615. // We need to get the Cabinet structure from the property sheet info.
  1616. BOOL fAlwaysOnTop;
  1617. BOOL fAutoHide;
  1618. BOOL fChanged;
  1619. LONG lRet;
  1620. TRAYVIEWOPTS tvo;
  1621. // First check for Always on Top
  1622. fAlwaysOnTop = ::IsDlgButtonChecked(hDlg, IDC_TRAYOPTONTOP);
  1623. c_tray._UpdateAlwaysOnTop(fAlwaysOnTop);
  1624. // And change the Autohide state
  1625. fAutoHide = ::IsDlgButtonChecked(hDlg, IDC_TRAYOPTAUTOHIDE);
  1626. lRet = c_tray._SetAutoHideState(fAutoHide);
  1627. c_tray.GetTrayViewOpts(&tvo);
  1628. if (!HIWORD(lRet) && fAutoHide)
  1629. {
  1630. // we tried and failed.
  1631. if (!(tvo.uAutoHide & AH_ON))
  1632. {
  1633. ::CheckDlgButton(hDlg, IDC_TRAYOPTAUTOHIDE, FALSE);
  1634. _TaskbarOptionsUpdateDisplay(hDlg);
  1635. }
  1636. }
  1637. fChanged = LOWORD(lRet);
  1638. if (fChanged)
  1639. c_tray._AppBarNotifyAll(NULL, ABN_STATECHANGE, NULL, 0);
  1640. // show/hide the clock
  1641. tvo.fHideClock = !::IsDlgButtonChecked(hDlg, IDC_TRAYOPTSHOWCLOCK);
  1642. if (!tvo.fNoTrayItemsDisplayPolicyEnabled && !tvo.fNoAutoTrayPolicyEnabled)
  1643. {
  1644. BOOL fNotifySetting = ::IsDlgButtonChecked(hDlg, IDC_NOTIFYMAN);
  1645. if (tvo.fAutoTrayEnabledByUser != fNotifySetting)
  1646. {
  1647. tvo.fAutoTrayEnabledByUser = fNotifySetting;
  1648. _UpdateNotifySetting(fNotifySetting);
  1649. }
  1650. }
  1651. tvo.fShowQuickLaunch = ::IsDlgButtonChecked(hDlg, IDC_QUICKLAUNCH);
  1652. c_tray.SetTrayViewOpts(&tvo);
  1653. SendMessage(c_tray.GetTrayNotifyHWND(), TNM_HIDECLOCK, 0, tvo.fHideClock);
  1654. c_tray.SizeWindows();
  1655. // Update registry for locked taskbar
  1656. DWORD dwEnableSizeMove = !::IsDlgButtonChecked(hDlg, IDC_LOCKTASKBAR);
  1657. SHRegSetUSValue(REGSTR_EXPLORER_ADVANCED, TEXT("TaskbarSizeMove"),
  1658. REG_DWORD, &dwEnableSizeMove, sizeof(DWORD), SHREGSET_FORCE_HKCU);
  1659. //Update registry for grouping behavior
  1660. DWORD dwGlom = ::IsDlgButtonChecked(hDlg, IDC_GROUPITEMS);
  1661. SHRegSetUSValue(REGSTR_EXPLORER_ADVANCED, TEXT("TaskbarGlomming"),
  1662. REG_DWORD, &dwGlom, sizeof(DWORD), SHREGSET_FORCE_HKCU);
  1663. ::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, (LPARAM)TEXT("TraySettings"), SMTO_NOTIMEOUTIFNOTHUNG, 1000, NULL);
  1664. }
  1665. void CTaskBarPropertySheet::_ApplyStartOptionsFromDialog(HWND hDlg)
  1666. {
  1667. if(!SHRestricted(REST_NOSTARTPANEL))
  1668. {
  1669. //Get the current state of the check box
  1670. BOOL fStartPanelOn = BOOLIFY(::IsDlgButtonChecked(hDlg, IDC_NEWSCHOOL) );
  1671. SHELLSTATE ss = {0};
  1672. //See if Startpage is currently on or off.
  1673. SHGetSetSettings(&ss, SSF_STARTPANELON, FALSE);
  1674. //Check if the check box has been toggled
  1675. if(fStartPanelOn != BOOLIFY(ss.fStartPanelOn))
  1676. {
  1677. // Toggle the setting
  1678. ss.fStartPanelOn = fStartPanelOn;
  1679. SHGetSetSettings(&ss, SSF_STARTPANELON, TRUE);
  1680. //Tell the desktop window so it can add/remove the desktop icons
  1681. ::PostMessage(v_hwndDesktop, DTM_STARTPAGEONOFF, 0, 0);
  1682. }
  1683. // Tell the Start Menu to rebuild itself now that we changed it
  1684. // (This part is unconditional since the user may have merely
  1685. // changed a setting with the Start Menu)
  1686. ::PostMessage(v_hwndTray, SBM_REBUILDMENU, 0, 0);
  1687. }
  1688. }
  1689. //---------------------------------------------------------------------------
  1690. void _TaskbarOptionsDestroyBitmaps(HWND hDlg)
  1691. {
  1692. SetDlgItemBitmap(hDlg, IDC_TASKBARAPPEARANCE, 0);
  1693. SetDlgItemBitmap(hDlg, IDC_NOTIFYAPPEARANCE, 0);
  1694. }
  1695. typedef struct
  1696. {
  1697. int idc;
  1698. int iAdd;
  1699. }
  1700. CONTROLBITMAP;
  1701. int _TaskbarPickBitmap(HWND hDlg, int iBmpBase, const CONTROLBITMAP* pca, int cca)
  1702. {
  1703. for (int i = 0; i < cca; i++)
  1704. {
  1705. if (!IsDlgButtonChecked(hDlg, pca[i].idc))
  1706. {
  1707. iBmpBase += pca[i].iAdd;
  1708. }
  1709. }
  1710. return iBmpBase;
  1711. }
  1712. void _TaskbarOptionsUpdateDisplay(HWND hDlg)
  1713. {
  1714. static const CONTROLBITMAP c_caTaskbar[] =
  1715. {
  1716. { IDC_LOCKTASKBAR, 1 },
  1717. { IDC_GROUPITEMS, 2 },
  1718. { IDC_QUICKLAUNCH, 4 },
  1719. };
  1720. static const CONTROLBITMAP c_caNotify[] =
  1721. {
  1722. { IDC_TRAYOPTSHOWCLOCK, 1 },
  1723. { IDC_NOTIFYMAN, 2 },
  1724. };
  1725. //
  1726. // top preview
  1727. //
  1728. int iBmp;
  1729. if (IsDlgButtonChecked(hDlg, IDC_TRAYOPTAUTOHIDE))
  1730. {
  1731. iBmp = IDB_TAAUTOHIDE;
  1732. }
  1733. else
  1734. {
  1735. iBmp = _TaskbarPickBitmap(hDlg, IDB_TAQLLOCKGROUP, c_caTaskbar, ARRAYSIZE(c_caTaskbar));
  1736. }
  1737. SetDlgItemBitmap(hDlg, IDC_TASKBARAPPEARANCE, iBmp);
  1738. //
  1739. // bottom preview
  1740. //
  1741. iBmp = _TaskbarPickBitmap(hDlg, IDB_NACLOCKCLEAN, c_caNotify, ARRAYSIZE(c_caNotify));
  1742. SetDlgItemBitmap(hDlg, IDC_NOTIFYAPPEARANCE, iBmp);
  1743. //
  1744. // customize button
  1745. //
  1746. EnableWindow(GetDlgItem(hDlg, IDC_CUSTOMIZE), IsDlgButtonChecked(hDlg, IDC_NOTIFYMAN));
  1747. }
  1748. #define CX_PREVIEW 336
  1749. #define CY_PREVIEW 35
  1750. // need to do this by hand because dialog units to pixels will change,
  1751. // but the bitmaps won't
  1752. void _TaskbarOptionsSizeControls(HWND hDlg)
  1753. {
  1754. static const int c_IDC[] =
  1755. {
  1756. IDC_TASKBARAPPEARANCE,
  1757. IDC_NOTIFYAPPEARANCE
  1758. };
  1759. for (int i = 0; i < ARRAYSIZE(c_IDC); i++)
  1760. {
  1761. SetWindowPos(GetDlgItem(hDlg, c_IDC[i]), NULL, 0, 0, CX_PREVIEW, CY_PREVIEW,
  1762. SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
  1763. }
  1764. }
  1765. typedef BOOL (* PFCFGSTART) (HWND, BOOL);
  1766. void CallAppWiz(HWND hDlg, BOOL bDelItems)
  1767. {
  1768. HINSTANCE hmodWiz = LoadLibrary(TEXT("AppWiz.Cpl"));
  1769. if (hmodWiz)
  1770. {
  1771. PFCFGSTART pfnCfgStart = (PFCFGSTART)GetProcAddress(hmodWiz, "ConfigStartMenu");
  1772. if (pfnCfgStart)
  1773. {
  1774. pfnCfgStart(hDlg, bDelItems);
  1775. }
  1776. FreeLibrary(hmodWiz);
  1777. }
  1778. }
  1779. BOOL ExecExplorerAtStartMenu(HWND hDlg)
  1780. {
  1781. SHELLEXECUTEINFO ei;
  1782. BOOL fWorked= FALSE;
  1783. TCHAR szParams[MAX_PATH];
  1784. ei.cbSize = sizeof(ei);
  1785. ei.hwnd = hDlg;
  1786. ei.lpVerb = NULL;
  1787. ei.fMask = 0;
  1788. ei.lpFile = TEXT("Explorer.exe");
  1789. if (IsUserAnAdmin())
  1790. {
  1791. lstrcpy(szParams, TEXT("/E,"));
  1792. SHGetSpecialFolderPath(hDlg, &(szParams[ARRAYSIZE(TEXT("/E,"))-1]),
  1793. CSIDL_STARTMENU, FALSE);
  1794. }
  1795. else
  1796. {
  1797. lstrcpy(szParams, TEXT("/E,/Root,"));
  1798. SHGetSpecialFolderPath(hDlg, &(szParams[ARRAYSIZE(TEXT("/E,/Root,"))-1]),
  1799. CSIDL_STARTMENU, FALSE);
  1800. }
  1801. ei.lpParameters = szParams;
  1802. ei.lpDirectory = NULL;
  1803. ei.lpClass = NULL;
  1804. ei.nShow = SW_SHOWDEFAULT;
  1805. ei.hInstApp = hinstCabinet;
  1806. return(ShellExecuteEx(&ei));
  1807. }
  1808. const TCHAR *c_szRegMruKeysToDelete[] =
  1809. {
  1810. TEXT("Software\\Microsoft\\Internet Explorer\\TypedURLs"),
  1811. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU"),
  1812. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Doc Find Spec MRU"),
  1813. // New for Whistler (should've been in Windows 2000 and Millennium but we forgot)
  1814. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Comdlg32\\OpenSaveMRU"),
  1815. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Comdlg32\\LastVisitedMRU"),
  1816. };
  1817. void SetDocButton(HWND hDlg, int id)
  1818. {
  1819. LPITEMIDLIST pidl;
  1820. BOOL bAreDocs = FALSE;
  1821. HRESULT hr = SHGetSpecialFolderLocation(hDlg, CSIDL_RECENT, &pidl);
  1822. if (SUCCEEDED(hr))
  1823. {
  1824. IShellFolder *psf = BindToFolder(pidl);
  1825. if (psf)
  1826. {
  1827. HRESULT hres;
  1828. LPENUMIDLIST penum;
  1829. hres = psf->EnumObjects(hDlg, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &penum);
  1830. if (SUCCEEDED(hres))
  1831. {
  1832. unsigned long celt;
  1833. LPITEMIDLIST pidlenum;
  1834. if ((S_OK == penum->Next(1, &pidlenum, &celt)) && (celt == 1))
  1835. {
  1836. SHFree(pidlenum);
  1837. bAreDocs = TRUE;
  1838. }
  1839. penum->Release();
  1840. }
  1841. psf->Release();
  1842. }
  1843. SHFree(pidl);
  1844. }
  1845. // Check other MRU registry keys
  1846. if (!bAreDocs)
  1847. {
  1848. int i;
  1849. for (i = 0; i < ARRAYSIZE(c_szRegMruKeysToDelete); i++)
  1850. {
  1851. HKEY hkey;
  1852. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegMruKeysToDelete[i], 0L, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS)
  1853. {
  1854. bAreDocs = TRUE;
  1855. RegCloseKey(hkey);
  1856. }
  1857. }
  1858. }
  1859. Button_Enable(GetDlgItem(hDlg, id), bAreDocs);
  1860. }
  1861. void ClearRecentDocumentsAndMRUStuff(BOOL fBroadcastChange)
  1862. {
  1863. int i;
  1864. SHAddToRecentDocs(0, NULL);
  1865. // Flush other MRUs in the registry for privacy
  1866. for (i = 0; i < ARRAYSIZE(c_szRegMruKeysToDelete); i++)
  1867. {
  1868. SHDeleteKey(HKEY_CURRENT_USER, c_szRegMruKeysToDelete[i]);
  1869. if (fBroadcastChange)
  1870. SHSendMessageBroadcast(WM_SETTINGCHANGE, 0,
  1871. (LPARAM)c_szRegMruKeysToDelete[i]);
  1872. }
  1873. }
  1874. void HandleClearButtonClick(HWND hwndClear)
  1875. {
  1876. HCURSOR hc = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1877. ClearRecentDocumentsAndMRUStuff(TRUE);
  1878. SetCursor(hc);
  1879. //
  1880. // Before disabling the button, shove focus off it.
  1881. //
  1882. if (GetFocus() == hwndClear)
  1883. {
  1884. SendMessage(GetParent(hwndClear), WM_NEXTDLGCTL, 0, MAKELONG(FALSE, 0));
  1885. }
  1886. Button_Enable(hwndClear, FALSE);
  1887. }
  1888. void Reorder(HDPA hdpa)
  1889. {
  1890. for (int i = DPA_GetPtrCount(hdpa) - 1; i >= 0; i--)
  1891. {
  1892. PORDERITEM poi = (PORDERITEM)DPA_FastGetPtr(hdpa, i);
  1893. poi->nOrder = i;
  1894. }
  1895. }
  1896. void MenuOrderSort(HKEY hkeyRoot, IShellFolder* psf);
  1897. void MenuOrderSortKeyWithFolder(HKEY hkeyRoot, LPTSTR pszKey, IShellFolder* psf)
  1898. {
  1899. HKEY hkey;
  1900. if (ERROR_SUCCESS == RegOpenKeyEx(hkeyRoot, pszKey, 0, KEY_READ | KEY_WRITE, &hkey))
  1901. {
  1902. MenuOrderSort(hkey, psf);
  1903. RegCloseKey(hkey);
  1904. }
  1905. }
  1906. // Binds to the Key pszKey, under hkey root, using psf, and sorts the resultant order.
  1907. void MenuOrderSortSubKey(HKEY hkeyRoot, LPTSTR szFolder, LPTSTR pszKey, IShellFolder* psf)
  1908. {
  1909. LPITEMIDLIST pidl;
  1910. DWORD cbEaten;
  1911. DWORD dwAttrib;
  1912. WCHAR wszKey[MAX_PATH];
  1913. SHTCharToUnicode(szFolder, wszKey, ARRAYSIZE(wszKey));
  1914. if (SUCCEEDED(psf->ParseDisplayName(NULL, NULL, wszKey, &cbEaten, &pidl, &dwAttrib)))
  1915. {
  1916. IShellFolder* psfSub;
  1917. if (SUCCEEDED(psf->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfSub))))
  1918. {
  1919. MenuOrderSortKeyWithFolder(hkeyRoot, pszKey, psfSub);
  1920. psfSub->Release();
  1921. }
  1922. ILFree(pidl);
  1923. }
  1924. }
  1925. void MenuOrderSort(HKEY hkeyRoot, IShellFolder* psf)
  1926. {
  1927. // Try to open Value Order
  1928. IStream* pstm = SHOpenRegStream(hkeyRoot, TEXT(""), TEXT("Order"), STGM_READWRITE);
  1929. if (pstm)
  1930. {
  1931. IOrderList2* pol2;
  1932. if (SUCCEEDED(CoCreateInstance(CLSID_OrderListExport, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IOrderList2, &pol2))))
  1933. {
  1934. HDPA hdpa;
  1935. if (SUCCEEDED(pol2->LoadFromStream(pstm, &hdpa, psf)))
  1936. {
  1937. // Since it's stored ordered by name, this should be no problem.
  1938. Reorder(hdpa);
  1939. // Set the seek pointer at the beginning.
  1940. LARGE_INTEGER liZero = {0};
  1941. pstm->Seek(liZero, STREAM_SEEK_SET, NULL);
  1942. pol2->SaveToStream(pstm, hdpa);
  1943. DPA_Destroy(hdpa);
  1944. }
  1945. pol2->Release();
  1946. }
  1947. pstm->Release();
  1948. }
  1949. // Now enumerate sub keys.
  1950. TCHAR szKey[MAX_PATH];
  1951. DWORD cbKey = ARRAYSIZE(szKey);
  1952. int iIndex = 0;
  1953. while (ERROR_SUCCESS == RegEnumKeyEx(hkeyRoot, iIndex, szKey, &cbKey, NULL, NULL, NULL, NULL))
  1954. {
  1955. MenuOrderSortSubKey(hkeyRoot, szKey, szKey, psf);
  1956. iIndex++;
  1957. cbKey = ARRAYSIZE(szKey);
  1958. }
  1959. }
  1960. // Defined in Tray.c
  1961. IShellFolder* BindToFolder(LPCITEMIDLIST pidl);
  1962. void StartMenuSort()
  1963. {
  1964. IShellFolder* psf = NULL;
  1965. LPITEMIDLIST pidl;
  1966. HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_STARTMENU, &pidl);
  1967. if (SUCCEEDED(hr))
  1968. {
  1969. LPITEMIDLIST pidl2;
  1970. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_STARTMENU, &pidl2)))
  1971. {
  1972. IAugmentedShellFolder2* pasf;
  1973. IShellFolder* psfCommon;
  1974. IShellFolder* psfUser;
  1975. HRESULT hres = CoCreateInstance(CLSID_MergedFolder, NULL, CLSCTX_INPROC,
  1976. IID_PPV_ARG(IAugmentedShellFolder2, &pasf));
  1977. if (SUCCEEDED(hres))
  1978. {
  1979. psfUser = BindToFolder(pidl);
  1980. if (psfUser)
  1981. {
  1982. pasf->AddNameSpace(NULL, psfUser, pidl, ASFF_DEFAULT | ASFF_DEFNAMESPACE_ALL);
  1983. psfUser->Release();
  1984. }
  1985. psfCommon = BindToFolder(pidl2);
  1986. if (psfCommon)
  1987. {
  1988. pasf->AddNameSpace(NULL, psfCommon, pidl2, ASFF_DEFAULT);
  1989. psfCommon->Release();
  1990. }
  1991. hres = pasf->QueryInterface(IID_PPV_ARG(IShellFolder, &psf));
  1992. pasf->Release();
  1993. }
  1994. ILFree(pidl2);
  1995. }
  1996. else
  1997. {
  1998. psf = BindToFolder(pidl);
  1999. }
  2000. ILFree(pidl);
  2001. }
  2002. if (psf)
  2003. {
  2004. HKEY hkeyRoot;
  2005. // Recursivly sort the orders. Should this be on another thread?
  2006. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, STRREG_STARTMENU,
  2007. 0, KEY_READ | KEY_WRITE, &hkeyRoot))
  2008. {
  2009. MenuOrderSort(hkeyRoot, psf);
  2010. // Sort the My Documents menu item:
  2011. LPITEMIDLIST pidlMyDocs;
  2012. SHGetFolderLocation(NULL, CSIDL_PERSONAL, NULL, 0, &pidlMyDocs);
  2013. if (pidlMyDocs)
  2014. {
  2015. IShellFolder* psfMyDocs;
  2016. if (SUCCEEDED(SHBindToObjectEx(NULL, pidlMyDocs, NULL, IID_PPV_ARG(IShellFolder, &psfMyDocs))))
  2017. {
  2018. MenuOrderSortKeyWithFolder(hkeyRoot, TEXT("MyDocuments"), psfMyDocs);
  2019. psfMyDocs->Release();
  2020. }
  2021. ILFree(pidlMyDocs);
  2022. }
  2023. // What happens if the Filesystem programs is not equal to the hard coded string "Programs"? This
  2024. // happens on German: Programme != Programs and we fail to sort. So let's verify:
  2025. TCHAR szPath[MAX_PATH];
  2026. SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL, 0, szPath);
  2027. LPTSTR pszName = PathFindFileName(szPath);
  2028. if (StrCmpI(pszName, TEXT("Programs")) != 0)
  2029. {
  2030. // Ok, It's not the same, so go bind to that sub tree and sort it.
  2031. MenuOrderSortSubKey(hkeyRoot, pszName, TEXT("Programs"), psf);
  2032. }
  2033. RegCloseKey(hkeyRoot);
  2034. }
  2035. psf->Release();
  2036. }
  2037. }
  2038. BOOL Advanced_OnInitDialog(HWND hwndDlg, SMADVANCED* pAdv)
  2039. {
  2040. if (!pAdv || !pAdv->pTO)
  2041. {
  2042. EndDialog(hwndDlg, 0);
  2043. return FALSE; // no memory?
  2044. }
  2045. SetWindowPtr(hwndDlg, DWLP_USER, pAdv);
  2046. // since the large icon setting is stored in the tray state, not as a standalone reg key, we need to have a temp reg key for the regtreeop to use...
  2047. TRAYVIEWOPTS tvo;
  2048. c_tray.GetTrayViewOpts(&tvo);
  2049. BOOL fLargePrev = !tvo.fSMSmallIcons;
  2050. SHSetValue(HKEY_CURRENT_USER, REGSTR_EXPLORER_ADVANCED, REGSTR_VAL_LARGEICONSTEMP, REG_DWORD, (void*) &fLargePrev, sizeof(fLargePrev));
  2051. pAdv->hwndTree = GetDlgItem( hwndDlg, IDC_STARTMENUSETTINGS );
  2052. // HACKHACK - IRegTreeOptions is ANSI, so we temporarily turn off UNICODE
  2053. #undef TEXT
  2054. #define TEXT(s) s
  2055. HRESULT hr = pAdv->pTO->InitTree(pAdv->hwndTree, HKEY_LOCAL_MACHINE, REGSTR_PATH_SMADVANCED "\\StartMenu", NULL);
  2056. #undef TEXT
  2057. #define TEXT(s) __TEXT(s)
  2058. // find the first root and make sure that it is visible
  2059. TreeView_EnsureVisible(pAdv->hwndTree, TreeView_GetRoot( pAdv->hwndTree ));
  2060. SetDocButton(hwndDlg, IDC_KILLDOCUMENTS);
  2061. return SUCCEEDED(hr);
  2062. }
  2063. void InitStartMenu_DoTreeHelp(SMADVANCED* pAdv, WPARAM wParam)
  2064. {
  2065. TV_HITTESTINFO ht;
  2066. GetCursorPos( &ht.pt ); // get where we were hit
  2067. if (pAdv->hwndTree == WindowFromPoint(ht.pt))
  2068. {
  2069. ScreenToClient( pAdv->hwndTree, &ht.pt ); // translate it to our window
  2070. // retrieve the item hit
  2071. pAdv->pTO->ShowHelp(TreeView_HitTest( pAdv->hwndTree, &ht),HELP_CONTEXTMENU);
  2072. }
  2073. else
  2074. {
  2075. WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU,
  2076. (ULONG_PTR)(LPVOID)aInitStartMenuHelpIDs);
  2077. }
  2078. }
  2079. BOOL_PTR CALLBACK AdvancedOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  2080. {
  2081. SMADVANCED* pAdv = (SMADVANCED*)GetWindowPtr(hwndDlg, DWLP_USER);
  2082. INSTRUMENT_WNDPROC(SHCNFI_INITSTARTMENU_DLGPROC, hwndDlg, msg, wParam, lParam);
  2083. if (msg != WM_INITDIALOG && !pAdv)
  2084. {
  2085. // We've been re-entered after being destroyed. Bail.
  2086. return FALSE;
  2087. }
  2088. switch (msg)
  2089. {
  2090. case WM_COMMAND:
  2091. switch(GET_WM_COMMAND_ID(wParam, lParam))
  2092. {
  2093. case IDC_ADDSHORTCUT:
  2094. CallAppWiz(hwndDlg, FALSE);
  2095. break;
  2096. case IDC_DELSHORTCUT:
  2097. CallAppWiz(hwndDlg, TRUE);
  2098. break;
  2099. case IDC_RESORT:
  2100. {
  2101. SHChangeDWORDAsIDList dwidl;
  2102. StartMenuSort();
  2103. // Notify everyone that the order changed
  2104. dwidl.cb = sizeof(dwidl) - sizeof(dwidl.cbZero);
  2105. dwidl.dwItem1 = SHCNEE_ORDERCHANGED;
  2106. dwidl.dwItem2 = 0;
  2107. dwidl.cbZero = 0;
  2108. SHChangeNotify(SHCNE_EXTENDED_EVENT, SHCNF_FLUSH, (LPCITEMIDLIST)&dwidl, NULL);
  2109. break;
  2110. }
  2111. case IDC_EXPLOREMENUS:
  2112. ExecExplorerAtStartMenu(hwndDlg);
  2113. break;
  2114. case IDC_KILLDOCUMENTS:
  2115. {
  2116. HandleClearButtonClick(GET_WM_COMMAND_HWND(wParam, lParam));
  2117. }
  2118. break;
  2119. case IDOK:
  2120. {
  2121. pAdv->pTO->WalkTree(WALK_TREE_SAVE);
  2122. TRAYVIEWOPTS tvo;
  2123. c_tray.GetTrayViewOpts(&tvo);
  2124. BOOL fSmallPrev = tvo.fSMSmallIcons;
  2125. // note that we are loading the classic setting for large icons here....
  2126. BOOL fSmallNew = !SHRegGetBoolUSValue(REGSTR_EXPLORER_ADVANCED, REGSTR_VAL_LARGEICONSTEMP, FALSE, TRUE /* default to large*/);
  2127. if (fSmallPrev != fSmallNew)
  2128. {
  2129. tvo.fSMSmallIcons = fSmallNew;
  2130. c_tray.SetTrayViewOpts(&tvo);
  2131. IMenuPopup_SetIconSize(c_tray.GetStartMenu(), fSmallNew ? BMICON_SMALL : BMICON_LARGE);
  2132. }
  2133. ::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, (LPARAM)TEXT("TraySettings"), SMTO_NOTIMEOUTIFNOTHUNG, 1000, NULL);
  2134. }
  2135. // fall through
  2136. case IDCANCEL:
  2137. SHDeleteValue(HKEY_CURRENT_USER, REGSTR_EXPLORER_ADVANCED, REGSTR_VAL_LARGEICONSTEMP);
  2138. EndDialog(hwndDlg, FALSE); // false to not enable parent's apply
  2139. break;
  2140. }
  2141. break;
  2142. case WM_INITDIALOG:
  2143. return Advanced_OnInitDialog(hwndDlg, (SMADVANCED *)lParam);
  2144. case WM_NOTIFY:
  2145. {
  2146. LPNMHDR pnm = (NMHDR *)lParam;
  2147. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, 0); // handled
  2148. switch (pnm->code)
  2149. {
  2150. case TVN_KEYDOWN:
  2151. {
  2152. TV_KEYDOWN *pnmKeyDown = (TV_KEYDOWN*)((NMHDR *)lParam);
  2153. if (pnmKeyDown->wVKey == VK_SPACE)
  2154. {
  2155. pAdv->pTO->ToggleItem((HTREEITEM)SendMessage(pAdv->hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, 0L));
  2156. SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0L);
  2157. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, TRUE); // eat the key
  2158. }
  2159. break;
  2160. }
  2161. case NM_CLICK:
  2162. case NM_DBLCLK:
  2163. // is this click in our tree?
  2164. if ( pnm->idFrom == IDC_STARTMENUSETTINGS )
  2165. {
  2166. TV_HITTESTINFO ht;
  2167. DWORD dwPos = GetMessagePos(); // get where we were hit
  2168. ht.pt.x = GET_X_LPARAM(dwPos);
  2169. ht.pt.y = GET_Y_LPARAM(dwPos);
  2170. ScreenToClient( pAdv->hwndTree, &ht.pt ); // translate it to our window
  2171. // retrieve the item hit
  2172. pAdv->pTO->ToggleItem(TreeView_HitTest( pAdv->hwndTree, &ht));
  2173. SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0L);
  2174. }
  2175. break;
  2176. case NM_RCLICK: // right mouse click
  2177. if (pnm->hwndFrom == pAdv->hwndTree)
  2178. {
  2179. InitStartMenu_DoTreeHelp(pAdv, (WPARAM)pnm->hwndFrom);
  2180. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, TRUE); // eat the click
  2181. return TRUE;
  2182. }
  2183. break;
  2184. }
  2185. break;
  2186. }
  2187. case WM_HELP: // F1
  2188. {
  2189. LPHELPINFO phi = (LPHELPINFO)lParam;
  2190. if (phi->iCtrlId != IDC_STARTMENUSETTINGS)
  2191. {
  2192. WinHelp( (HWND)(phi->hItemHandle), NULL,
  2193. HELP_WM_HELP, (ULONG_PTR)(LPTSTR)aInitStartMenuHelpIDs);
  2194. }
  2195. else
  2196. {
  2197. HTREEITEM hItem;
  2198. //Is this help invoked throught F1 key
  2199. if (GetAsyncKeyState(VK_F1) < 0)
  2200. {
  2201. // Yes. WE need to give help for the currently selected item
  2202. hItem = TreeView_GetSelection(pAdv->hwndTree);
  2203. }
  2204. else
  2205. {
  2206. //No, We need to give help for the item at the cursor position
  2207. TV_HITTESTINFO ht;
  2208. ht.pt = phi->MousePos;
  2209. ScreenToClient(pAdv->hwndTree, &ht.pt); // Translate it to our window
  2210. hItem = TreeView_HitTest(pAdv->hwndTree, &ht);
  2211. }
  2212. pAdv->pTO->ShowHelp(hItem, HELP_WM_HELP);
  2213. }
  2214. break;
  2215. }
  2216. case WM_CONTEXTMENU: // right mouse click
  2217. {
  2218. InitStartMenu_DoTreeHelp(pAdv, wParam);
  2219. break;
  2220. }
  2221. case WM_DESTROY:
  2222. {
  2223. // will be free'd when our parent is destroyed
  2224. pAdv->pTO->WalkTree(WALK_TREE_DELETE);
  2225. // make sure we don't re-enter
  2226. SetWindowPtr( hwndDlg, DWLP_USER, NULL );
  2227. }
  2228. break; // WM_DESTORY
  2229. default:
  2230. return FALSE;
  2231. }
  2232. return TRUE;
  2233. }
  2234. #define TPF_PAGEFLAGS (TPF_STARTMENUPAGE | TPF_TASKBARPAGE)
  2235. void DoTaskBarProperties(HWND hwnd, DWORD dwFlags)
  2236. {
  2237. ASSERT(((dwFlags & TPF_PAGEFLAGS) == TPF_STARTMENUPAGE) ||
  2238. ((dwFlags & TPF_PAGEFLAGS) == TPF_TASKBARPAGE));
  2239. UINT nStartPage = (dwFlags & TPF_TASKBARPAGE) ? 0 : 1;
  2240. CTaskBarPropertySheet sheet(nStartPage, hwnd, dwFlags);
  2241. sheet.DoModal(hwnd);
  2242. }
  2243. // Passing iResource=0 deletes the bitmap in the control
  2244. void SetDlgItemBitmap(HWND hDlg, int idStatic, int iResource)
  2245. {
  2246. HBITMAP hbm;
  2247. if (iResource)
  2248. {
  2249. hbm = (HBITMAP)LoadImage(hinstCabinet, MAKEINTRESOURCE(iResource), IMAGE_BITMAP, 0,0, LR_LOADMAP3DCOLORS);
  2250. }
  2251. else
  2252. {
  2253. hbm = NULL;
  2254. }
  2255. hbm = (HBITMAP)SendDlgItemMessage(hDlg, idStatic, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbm);
  2256. if (hbm)
  2257. DeleteObject(hbm);
  2258. }
  2259. void SetDlgItemIcon(HWND hDlg, int idStatic, HICON hIcon)
  2260. {
  2261. HICON hiOld = (HICON)SendDlgItemMessage(hDlg, idStatic, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  2262. if (hiOld)
  2263. DestroyIcon(hiOld);
  2264. }
  2265. // REVIEW - use SHGetFileInfo?
  2266. void SetProgramIcon(HWND hDlg, int idLarge, int idSmall)
  2267. {
  2268. HICON hIconLarge = NULL;
  2269. HICON hIconSmall = NULL;
  2270. LPITEMIDLIST pidlMyComp = ILCreateFromPath(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}")); // CLSID_MyComputer;
  2271. if (pidlMyComp)
  2272. {
  2273. IShellFolder *psfDesktop;
  2274. if (SUCCEEDED(SHGetDesktopFolder(&psfDesktop)))
  2275. {
  2276. IExtractIcon *pxi;
  2277. if (SUCCEEDED(psfDesktop->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pidlMyComp, IID_PPV_ARG_NULL(IExtractIcon, &pxi))))
  2278. {
  2279. TCHAR szIconFile[MAX_PATH];
  2280. int iIndex;
  2281. UINT wFlags;
  2282. if (S_OK == pxi->GetIconLocation(GIL_FORSHELL, szIconFile, ARRAYSIZE(szIconFile), &iIndex, &wFlags))
  2283. {
  2284. pxi->Extract(szIconFile, iIndex, &hIconLarge, &hIconSmall, (GetSystemMetrics(SM_CXSMICON)<<16) | GetSystemMetrics(SM_CXICON));
  2285. }
  2286. pxi->Release();
  2287. }
  2288. psfDesktop->Release();
  2289. }
  2290. ILFree(pidlMyComp);
  2291. }
  2292. if (hIconLarge)
  2293. SetDlgItemIcon(hDlg, idLarge, hIconLarge);
  2294. if (hIconSmall)
  2295. SetDlgItemIcon(hDlg, idSmall, hIconSmall);
  2296. }