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.

1559 lines
41 KiB

  1. #include "shellprv.h"
  2. #include "ids.h"
  3. #include "help.h"
  4. #include "ascstr.h"
  5. #include "ftcmmn.h"
  6. #include "ftprop.h"
  7. #include "ftedit.h"
  8. #include "ftadv.h"
  9. #define SUBITEM_EXT 0
  10. #define SUBITEM_PROGIDDESCR 1
  11. #define WM_FINISHFILLLISTVIEW (WM_USER + 1)
  12. static DWORD s_rgdwHelpIDsArray[] =
  13. { // Context Help IDs
  14. IDC_NO_HELP_1, NO_HELP,
  15. IDC_FT_PROP_LV_FILETYPES, IDH_FCAB_FT_PROP_LV_FILETYPES,
  16. IDC_FT_PROP_ANIM, IDH_FCAB_FT_PROP_LV_FILETYPES,
  17. IDC_FT_PROP_NEW, IDH_FCAB_FT_PROP_NEW,
  18. IDC_FT_PROP_OPENEXE_TXT, IDH_FCAB_FT_PROP_DETAILS,
  19. IDC_FT_PROP_OPENICON, IDH_FCAB_FT_PROP_DETAILS,
  20. IDC_FT_PROP_OPENEXE, IDH_FCAB_FT_PROP_DETAILS,
  21. IDC_FT_PROP_CHANGEOPENSWITH, IDH_FPROP_GEN_CHANGE,
  22. IDC_FT_PROP_TYPEOFFILE_TXT, IDH_FCAB_FT_PROP_DETAILS,
  23. IDC_FT_PROP_EDITTYPEOFFILE, IDH_FCAB_FT_PROP_EDIT,
  24. IDC_FT_PROP_GROUPBOX, IDH_FCAB_FT_PROP_DETAILS,
  25. IDC_FT_PROP_REMOVE, IDH_FCAB_FT_PROP_REMOVE,
  26. 0, 0
  27. };
  28. CFTPropDlg::CFTPropDlg() :
  29. CFTDlg((ULONG_PTR)s_rgdwHelpIDsArray), _iLVSel(-1), _fStopThread(FALSE)
  30. {}
  31. LRESULT CFTPropDlg::OnInitDialog(WPARAM wParam, LPARAM lParam)
  32. {
  33. HRESULT hres = _InitAssocStore();
  34. if (SUCCEEDED(hres))
  35. hres = _InitListView();
  36. if (SUCCEEDED(hres))
  37. _InitPreFillListView();
  38. if (SUCCEEDED(hres))
  39. SHCreateThread(_FillListViewWrapper, (LPVOID)this, 0, _ThreadAddRefCallBack);
  40. return TRUE;
  41. }
  42. LRESULT CFTPropDlg::OnFinishInitDialog()
  43. {
  44. HRESULT hres;
  45. _InitPostFillListView();
  46. hres = _SelectListViewItem(0);
  47. if (FAILED(hres))
  48. {
  49. if (E_OUTOFMEMORY == hres)
  50. {
  51. ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_ERROR +
  52. ERROR_NOT_ENOUGH_MEMORY), MAKEINTRESOURCE(IDS_FT),
  53. MB_OK | MB_ICONSTOP);
  54. }
  55. EndDialog(_hwnd, -1);
  56. }
  57. else
  58. SHCreateThread(_UpdateAllListViewItemImagesWrapper, (LPVOID)this, 0, _ThreadAddRefCallBack);
  59. return TRUE;
  60. }
  61. LRESULT CFTPropDlg::OnCtlColorStatic(WPARAM wParam, LPARAM lParam)
  62. {
  63. LRESULT fRet = FALSE;
  64. // This is to set the color of the background of the animate control
  65. // see doc on ACS_TRANSPARENT and WM_CTLCOLORSTATIC
  66. if ((HWND)lParam == GetDlgItem(_hwnd, IDC_FT_PROP_ANIM))
  67. {
  68. SetBkColor(GET_WM_CTLCOLOR_HDC(wParam, lParam, WM_CTLCOLORSTATIC), GetSysColor(COLOR_WINDOW));
  69. fRet = (LRESULT)GetSysColorBrush(COLOR_WINDOW);
  70. }
  71. return fRet;
  72. }
  73. //static
  74. DWORD WINAPI CFTPropDlg::_FillListViewWrapper(LPVOID lpParameter)
  75. {
  76. ((CFTPropDlg*)lpParameter)->_FillListView();
  77. ((CFTPropDlg*)lpParameter)->Release();
  78. return 0;
  79. }
  80. //static
  81. DWORD WINAPI CFTPropDlg::_UpdateAllListViewItemImagesWrapper(LPVOID lpParameter)
  82. {
  83. ((CFTPropDlg*)lpParameter)->_UpdateAllListViewItemImages();
  84. ((CFTPropDlg*)lpParameter)->Release();
  85. return 0;
  86. }
  87. //static
  88. DWORD WINAPI CFTPropDlg::_ThreadAddRefCallBack(LPVOID lpParameter)
  89. {
  90. return ((CFTPropDlg*)lpParameter)->AddRef();
  91. }
  92. LRESULT CFTPropDlg::OnDestroy(WPARAM wParam, LPARAM lParam)
  93. {
  94. DWORD dwRet = FALSE;
  95. int iCount = 0;
  96. LVITEM lvItem = {0};
  97. HWND hwndLV = _GetLVHWND();
  98. _fStopThread = TRUE;
  99. HICON hIconOld = (HICON)SendDlgItemMessage(_hwnd, IDC_FT_PROP_OPENICON, STM_GETIMAGE, IMAGE_ICON,
  100. (LPARAM)0);
  101. if (hIconOld)
  102. DeleteObject(hIconOld);
  103. // go through all the items in the listview and delete the strings dynamically
  104. // allocated for progIDs
  105. lvItem.mask = LVIF_PARAM;
  106. lvItem.iSubItem = SUBITEM_EXT;
  107. iCount = ListView_GetItemCount(hwndLV);
  108. for (lvItem.iItem = 0; lvItem.iItem < iCount; ++lvItem.iItem)
  109. {
  110. ListView_GetItem(hwndLV, &lvItem);
  111. if (lvItem.lParam)
  112. {
  113. LocalFree((HLOCAL)lvItem.lParam);
  114. }
  115. }
  116. CFTDlg::OnDestroy(wParam, lParam);
  117. return TRUE;
  118. }
  119. struct LVCOMPAREINFO
  120. {
  121. HWND hwndLV;
  122. int iCol;
  123. };
  124. int CALLBACK AlphaCompareItem(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  125. {
  126. struct LVCOMPAREINFO *plvci = (struct LVCOMPAREINFO *)lParamSort;
  127. TCHAR sz1[MAX_PATH];
  128. TCHAR sz2[MAX_PATH];
  129. ListView_GetItemText(plvci->hwndLV, lParam1, plvci->iCol, sz1, ARRAYSIZE(sz1));
  130. ListView_GetItemText(plvci->hwndLV, lParam2, plvci->iCol, sz2, ARRAYSIZE(sz2));
  131. return lstrcmpi(sz1, sz2);
  132. }
  133. LRESULT CFTPropDlg::OnListViewColumnClick(int iCol)
  134. {
  135. struct LVCOMPAREINFO lvci;
  136. lvci.hwndLV = _GetLVHWND();
  137. lvci.iCol = iCol;
  138. _fUpdateImageAgain = TRUE;
  139. return SendMessage(_GetLVHWND(), LVM_SORTITEMSEX, (WPARAM)&lvci, (LPARAM)AlphaCompareItem);
  140. }
  141. LRESULT CFTPropDlg::OnListViewSelItem(int iItem, LPARAM lParam)
  142. {
  143. //
  144. // Need to update the lower pane of the dialog
  145. //
  146. // Get the extension
  147. TCHAR szExt[MAX_EXT];
  148. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  149. LVITEM lvItem = {0};
  150. _iLVSel = iItem;
  151. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  152. lvItem.iItem = iItem;
  153. lvItem.iSubItem = SUBITEM_EXT;
  154. lvItem.pszText = szExt;
  155. lvItem.cchTextMax = ARRAYSIZE(szExt);
  156. ListView_GetItem(_GetLVHWND(), &lvItem);
  157. ListView_GetItemText(_GetLVHWND(), iItem, SUBITEM_PROGIDDESCR, szProgIDDescr,
  158. ARRAYSIZE(szProgIDDescr));
  159. _EnableLowerPane(TRUE);
  160. if (!lvItem.lParam)
  161. {
  162. _UpdateGroupBox(szExt, TRUE);
  163. }
  164. else
  165. {
  166. _UpdateGroupBox(szProgIDDescr, FALSE);
  167. }
  168. _UpdateProgIDButtons(szExt, (LPTSTR)lvItem.lParam);
  169. // We rely on this being after _UpdateProgIDButtons (see _fPerUserAdvButton)
  170. _UpdateDeleteButton(lvItem.lParam ? FALSE : TRUE);
  171. _UpdateAdvancedText(szExt, szProgIDDescr, lvItem.lParam ? FALSE : TRUE);
  172. _UpdateOpensWith(szExt, (LPTSTR)lvItem.lParam);
  173. return FALSE;
  174. }
  175. HRESULT CFTPropDlg::_UpdateDeleteButton(BOOL fExt)
  176. {
  177. BOOL fTrue = _ShouldEnableButtons();
  178. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_REMOVE),
  179. (_fPerUserAdvButton || !fExt) ? FALSE : fTrue);
  180. return S_OK;
  181. }
  182. HRESULT CFTPropDlg::_UpdateProgIDButtons(LPTSTR pszExt, LPTSTR pszProgID)
  183. {
  184. HRESULT hres = E_FAIL;
  185. if (pszExt && *pszExt)
  186. {
  187. TCHAR szButtonText[50];
  188. HWND hwndAdvButton = GetDlgItem(_hwnd, IDC_FT_PROP_EDITTYPEOFFILE);
  189. _SetAdvancedRestoreButtonHelpID(IDH_FCAB_FT_PROP_EDIT);
  190. // Is this a progID only association?
  191. if (!pszProgID)
  192. {
  193. // No
  194. IAssocInfo* pAI;
  195. hres = _pAssocStore->GetAssocInfo(pszExt, AIINIT_EXT, &pAI);
  196. if (SUCCEEDED(hres))
  197. {
  198. hres = pAI->GetBOOL(AIBOOL_PERUSERINFOAVAILABLE, &_fPerUserAdvButton);
  199. ASSERT(SUCCEEDED(hres) || (FAILED(hres) && (FALSE == _fPerUserAdvButton)));
  200. if (_fPerUserAdvButton)
  201. {
  202. // Restore mode
  203. LoadString(g_hinst, IDS_FT_PROP_BTN_RESTORE, szButtonText, ARRAYSIZE(szButtonText));
  204. _SetAdvancedRestoreButtonHelpID(IDH_FCAB_FT_PROP_EDIT_RESTORE);
  205. }
  206. else
  207. {
  208. TCHAR szProgID[MAX_PROGID];
  209. DWORD cchProgID = ARRAYSIZE(szProgID);
  210. hres = pAI->GetString(AISTR_PROGID, szProgID, &cchProgID);
  211. LoadString(g_hinst, IDS_FT_PROP_BTN_ADVANCED, szButtonText, ARRAYSIZE(szButtonText));
  212. if (SUCCEEDED(hres))
  213. {
  214. IAssocInfo * pAIProgID;
  215. hres = _pAssocStore->GetAssocInfo(szProgID, AIINIT_PROGID, &pAIProgID);
  216. if (SUCCEEDED(hres))
  217. {
  218. BOOL fEdit = _ShouldEnableButtons();
  219. if (fEdit)
  220. {
  221. pAIProgID->GetBOOL(AIBOOL_EDIT, &fEdit);
  222. }
  223. EnableWindow(hwndAdvButton, fEdit);
  224. pAIProgID->Release();
  225. }
  226. }
  227. }
  228. pAI->Release();
  229. }
  230. }
  231. else
  232. {
  233. // Yes
  234. IAssocInfo* pAIProgID;
  235. LoadString(g_hinst, IDS_FT_PROP_BTN_ADVANCED, szButtonText, ARRAYSIZE(szButtonText));
  236. hres = _pAssocStore->GetAssocInfo(pszProgID, AIINIT_PROGID, &pAIProgID);
  237. if (SUCCEEDED(hres))
  238. {
  239. BOOL fEdit = _ShouldEnableButtons();
  240. if (fEdit)
  241. {
  242. pAIProgID->GetBOOL(AIBOOL_EDIT, &fEdit);
  243. }
  244. EnableWindow(hwndAdvButton, fEdit);
  245. pAIProgID->Release();
  246. }
  247. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_CHANGEOPENSWITH), FALSE);
  248. }
  249. SetWindowText(hwndAdvButton, szButtonText);
  250. }
  251. return hres;
  252. }
  253. LRESULT CFTPropDlg::OnDeleteButton(WORD wNotif)
  254. {
  255. // Warn user about the evil consequences of his act
  256. if (ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_FT_MB_REMOVETYPE),
  257. MAKEINTRESOURCE(IDS_FT), MB_YESNO | MB_ICONQUESTION) == IDYES)
  258. {
  259. LVITEM lvItem = {0};
  260. TCHAR szExt[MAX_EXT];
  261. // Set stuff
  262. lvItem.iSubItem = SUBITEM_EXT;
  263. lvItem.pszText = szExt;
  264. lvItem.cchTextMax = ARRAYSIZE(szExt);
  265. if (_GetListViewSelectedItem(LVIF_TEXT | LVIF_IMAGE, 0, &lvItem))
  266. {
  267. HRESULT hres;
  268. IAssocInfo* pAI;
  269. hres = _pAssocStore->GetAssocInfo(szExt, AIINIT_EXT, &pAI);
  270. if (SUCCEEDED(hres))
  271. {
  272. hres = pAI->Delete(AIALL_NONE);
  273. if (SUCCEEDED(hres))
  274. {
  275. _DeleteListViewItem(lvItem.iItem);
  276. PropSheet_CancelToClose(GetParent(_hwnd));
  277. }
  278. pAI->Release();
  279. }
  280. }
  281. }
  282. return FALSE;
  283. }
  284. LRESULT CFTPropDlg::OnNewButton(WORD wNotif)
  285. {
  286. FTEDITPARAM ftEditParam;
  287. CFTEditDlg* pEditDlg = NULL;
  288. // Fill structure
  289. ftEditParam.dwExt = ARRAYSIZE(ftEditParam.szExt);
  290. ftEditParam.dwProgIDDescr = ARRAYSIZE(ftEditParam.szProgIDDescr);
  291. // This one should be one way, it will come back with a value
  292. *ftEditParam.szProgID = 0;
  293. ftEditParam.dwProgID = ARRAYSIZE(ftEditParam.szProgID);
  294. pEditDlg = new CFTEditDlg(&ftEditParam);
  295. if (pEditDlg)
  296. {
  297. if (IDOK == pEditDlg->DoModal(g_hinst, MAKEINTRESOURCE(DLG_FILETYPEOPTIONSEDITNEW),
  298. _hwnd))
  299. {
  300. HWND hwndLV = _GetLVHWND();
  301. LRESULT lRes = 0;
  302. int iIndex = -1;
  303. HRESULT hres = E_FAIL;
  304. IAssocInfo* pAI = NULL;
  305. LVFINDINFO lvFindInfo = {0};
  306. LPTSTR pszExtNoDot = NULL;
  307. LVITEM lvItem = {0};
  308. TCHAR szExt[MAX_EXT];
  309. lvItem.pszText = szExt;
  310. lvItem.cchTextMax = ARRAYSIZE(szExt);
  311. pszExtNoDot = (TEXT('.') != *(ftEditParam.szExt)) ? ftEditParam.szExt :
  312. ftEditParam.szExt + 1;
  313. lvFindInfo.flags = LVFI_STRING;
  314. lvFindInfo.psz = pszExtNoDot;
  315. iIndex = ListView_FindItem(hwndLV, -1, &lvFindInfo);
  316. // Is this a brand new Ext-ProgID association?
  317. if (-1 == iIndex)
  318. {
  319. // Yes, Insert a new item
  320. SetWindowRedraw(hwndLV, FALSE);
  321. // Add new ext-progID association
  322. hres = _pAssocStore->GetAssocInfo(ftEditParam.szExt, AIINIT_EXT, &pAI);
  323. if (SUCCEEDED(hres))
  324. {
  325. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  326. DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr);
  327. hres = pAI->GetString(AISTR_PROGIDDESCR, szProgIDDescr, &cchProgIDDescr);
  328. if (FAILED(hres) || !*szProgIDDescr)
  329. {
  330. MakeDefaultProgIDDescrFromExt(szProgIDDescr, ARRAYSIZE(szProgIDDescr), pszExtNoDot);
  331. }
  332. // Add to the listview
  333. iIndex = _InsertListViewItem(0, pszExtNoDot, szProgIDDescr);
  334. pAI->Release();
  335. }
  336. // Select newly inserted item
  337. if (-1 != iIndex)
  338. {
  339. _SelectListViewItem(iIndex);
  340. }
  341. // Redraw our list
  342. SetWindowRedraw(hwndLV, TRUE);
  343. _GetListViewSelectedItem(LVIF_PARAM | LVIF_TEXT, 0, &lvItem);
  344. lvItem.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE;
  345. }
  346. else
  347. {
  348. // No just update the item
  349. lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  350. lvItem.iItem = iIndex;
  351. ListView_GetItem(hwndLV, &lvItem);
  352. }
  353. _UpdateListViewItem(&lvItem);
  354. PropSheet_CancelToClose(GetParent(_hwnd));
  355. }
  356. pEditDlg->Release();
  357. }
  358. return FALSE;
  359. }
  360. LRESULT CFTPropDlg::OnAdvancedButton(WORD wNotif)
  361. {
  362. LVITEM lvItem = {0};
  363. TCHAR szExt[MAX_EXT];
  364. // Set stuff
  365. lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  366. lvItem.iSubItem = SUBITEM_EXT;
  367. lvItem.pszText = szExt;
  368. lvItem.cchTextMax = ARRAYSIZE(szExt);
  369. if (_GetListViewSelectedItem(LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM, 0, &lvItem))
  370. {
  371. HRESULT hres;
  372. IAssocInfo* pAI;
  373. if (_fPerUserAdvButton)
  374. {
  375. // Restore mode
  376. hres = _pAssocStore->GetAssocInfo(szExt, AIINIT_EXT, &pAI);
  377. if (SUCCEEDED(hres))
  378. {
  379. hres = pAI->Delete(AIALL_PERUSER);
  380. _UpdateListViewItem(&lvItem);
  381. OnListViewSelItem(lvItem.iItem, (LPARAM)NULL);
  382. pAI->Release();
  383. PropSheet_CancelToClose(GetParent(_hwnd));
  384. }
  385. }
  386. else
  387. {
  388. // we might deal with an ext-progid assoc or only a progID
  389. TCHAR szProgID[MAX_PROGID];
  390. // Is this a progID only?
  391. if (lvItem.lParam)
  392. {
  393. // Yes
  394. StrCpyN(szProgID, (LPTSTR)lvItem.lParam, ARRAYSIZE(szProgID));
  395. hres = S_OK;
  396. }
  397. else
  398. {
  399. // No
  400. DWORD cchProgID = ARRAYSIZE(szProgID);
  401. hres = _pAssocStore->GetAssocInfo(szExt, AIINIT_EXT, &pAI);
  402. if (SUCCEEDED(hres))
  403. {
  404. hres = THR(pAI->GetString(AISTR_PROGID, szProgID, &cchProgID));
  405. pAI->Release();
  406. }
  407. }
  408. if (SUCCEEDED(hres))
  409. {
  410. CFTAdvDlg* pAdvDlg = new CFTAdvDlg(szProgID, szExt);
  411. if (pAdvDlg)
  412. {
  413. if (IDOK == pAdvDlg->DoModal(g_hinst, MAKEINTRESOURCE(DLG_FILETYPEOPTIONSEDIT), _hwnd))
  414. {
  415. _UpdateListViewItem(&lvItem);
  416. OnListViewSelItem(lvItem.iItem, (LPARAM)NULL);
  417. PropSheet_CancelToClose(GetParent(_hwnd));
  418. }
  419. pAdvDlg->Release();
  420. }
  421. }
  422. }
  423. }
  424. return FALSE;
  425. }
  426. LRESULT CFTPropDlg::OnChangeButton(WORD wNotif)
  427. {
  428. // Bring up the "Open With" dialog
  429. LVITEM lvItem = {0};
  430. TCHAR szExt[MAX_EXT];
  431. // Set stuff
  432. lvItem.mask = LVIF_TEXT | LVIF_IMAGE;
  433. lvItem.iSubItem = SUBITEM_EXT;
  434. lvItem.pszText = szExt;
  435. lvItem.cchTextMax = ARRAYSIZE(szExt);
  436. if (_GetListViewSelectedItem(LVIF_TEXT, 0, &lvItem))
  437. {
  438. TCHAR szDotExt[MAX_EXT];
  439. OPENASINFO oai;
  440. *szDotExt = TEXT('.');
  441. StrCpyN(szDotExt + 1, szExt, ARRAYSIZE(szDotExt) - 1);
  442. oai.pcszFile = szDotExt;
  443. oai.pcszClass = NULL;
  444. oai.dwInFlags = (OAIF_REGISTER_EXT | OAIF_FORCE_REGISTRATION); // we want the association to be made
  445. if (SUCCEEDED(OpenAsDialog(GetParent(_hwnd), &oai)))
  446. {
  447. // we changed the association so update the "Opens with:" text
  448. _UpdateOpensWith(szExt, NULL);
  449. // we don't need LVIF_PARAM since we enable the Change button only for Ext-ProgID asssoc
  450. lvItem.mask = LVIF_TEXT | LVIF_IMAGE;
  451. _UpdateListViewItem(&lvItem);
  452. OnListViewSelItem(lvItem.iItem, (LPARAM)NULL);
  453. PropSheet_CancelToClose(GetParent(_hwnd));
  454. }
  455. }
  456. return FALSE;
  457. }
  458. HRESULT CFTPropDlg::_UpdateGroupBox(LPTSTR pszText, BOOL fExt)
  459. {
  460. HRESULT hres = E_OUTOFMEMORY;
  461. LPTSTR psz = NULL;
  462. if (fExt)
  463. {
  464. psz = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_FT_PROP_DETAILSFOR), pszText);
  465. }
  466. else
  467. {
  468. psz = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_FT_PROP_DETAILSFORPROGID), pszText);
  469. }
  470. if (psz)
  471. {
  472. SetDlgItemText(_hwnd, IDC_FT_PROP_GROUPBOX, psz);
  473. LocalFree(psz);
  474. hres = S_OK;
  475. }
  476. return hres;
  477. }
  478. HRESULT CFTPropDlg::_UpdateOpensWith(LPTSTR pszExt, LPTSTR pszProgID)
  479. {
  480. HICON hIconOld = NULL;
  481. if (!pszProgID)
  482. {
  483. IAssocInfo* pAI = NULL;
  484. HRESULT hres = _pAssocStore->GetAssocInfo(pszExt, AIINIT_EXT, &pAI);
  485. if (SUCCEEDED(hres))
  486. {
  487. TCHAR szAppFriendlyName[MAX_APPFRIENDLYNAME];
  488. DWORD dwAppFriendlyName = ARRAYSIZE(szAppFriendlyName);
  489. hres = pAI->GetString(AISTR_APPFRIENDLY, szAppFriendlyName, &dwAppFriendlyName);
  490. if (SUCCEEDED(hres))
  491. {
  492. HICON hIcon = NULL;
  493. int iIcon;
  494. SetDlgItemText(_hwnd, IDC_FT_PROP_OPENEXE, szAppFriendlyName);
  495. hres = pAI->GetDWORD(AIDWORD_APPSMALLICON, (DWORD*)&iIcon);
  496. HIMAGELIST hIL = NULL;
  497. // PERF: Why don't we just use _hImageList? Or ListView_GetImageList()?
  498. Shell_GetImageLists(NULL, &hIL);
  499. if (hIL && SUCCEEDED(hres))
  500. {
  501. hIcon = ImageList_ExtractIcon(g_hinst, hIL, iIcon);
  502. }
  503. hIconOld = (HICON)SendDlgItemMessage(_hwnd, IDC_FT_PROP_OPENICON, STM_SETIMAGE, IMAGE_ICON,
  504. (LPARAM)hIcon);
  505. if (hIconOld)
  506. DestroyIcon(hIconOld);
  507. }
  508. else
  509. {
  510. SetDlgItemText(_hwnd, IDC_FT_PROP_OPENEXE, TEXT(" "));
  511. hIconOld = (HICON)SendDlgItemMessage(_hwnd, IDC_FT_PROP_OPENICON, STM_SETIMAGE, IMAGE_ICON,
  512. (LPARAM)NULL);
  513. if (hIconOld)
  514. DestroyIcon(hIconOld);
  515. }
  516. pAI->Release();
  517. }
  518. }
  519. else
  520. {
  521. SetDlgItemText(_hwnd, IDC_FT_PROP_OPENEXE, TEXT(" "));
  522. hIconOld = (HICON)SendDlgItemMessage(_hwnd, IDC_FT_PROP_OPENICON, STM_SETIMAGE, IMAGE_ICON,
  523. (LPARAM)NULL);
  524. if (hIconOld)
  525. DestroyIcon(hIconOld);
  526. }
  527. return S_OK;
  528. }
  529. HRESULT CFTPropDlg::_UpdateAdvancedText(LPTSTR pszExt, LPTSTR pszFileType, BOOL fExt)
  530. {
  531. HRESULT hres = S_OK;
  532. LPTSTR psz = NULL;
  533. if (_fPerUserAdvButton)
  534. {
  535. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  536. DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr);
  537. IAssocInfo* pAI = NULL;
  538. // we need to show the previous progIDDescr
  539. hres = _pAssocStore->GetAssocInfo(pszExt, AIINIT_EXT, &pAI);
  540. if (SUCCEEDED(hres))
  541. {
  542. hres = pAI->GetString(AISTR_PROGIDDESCR, szProgIDDescr,
  543. &cchProgIDDescr);
  544. if (SUCCEEDED(hres))
  545. {
  546. // Restore mode
  547. psz = ShellConstructMessageString(HINST_THISDLL,
  548. MAKEINTRESOURCE(IDS_FT_PROP_RESTORE),
  549. pszExt, szProgIDDescr);
  550. }
  551. pAI->Release();
  552. }
  553. }
  554. else
  555. {
  556. if (fExt)
  557. {
  558. psz = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_FT_PROP_ADVANCED),
  559. pszExt, pszFileType, pszFileType);
  560. }
  561. else
  562. {
  563. psz = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_FT_PROP_ADVANCED_PROGID),
  564. pszFileType);
  565. }
  566. }
  567. if (SUCCEEDED(hres))
  568. {
  569. if (psz)
  570. {
  571. SetDlgItemText(_hwnd, IDC_FT_PROP_TYPEOFFILE_TXT, psz);
  572. LocalFree(psz);
  573. }
  574. else
  575. hres = E_OUTOFMEMORY;
  576. }
  577. return hres;
  578. }
  579. HRESULT CFTPropDlg::_EnableLowerPane(BOOL fEnable)
  580. {
  581. BOOL fTrue = _ShouldEnableButtons();
  582. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_OPENEXE_TXT), fEnable);
  583. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_OPENEXE), fEnable);
  584. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_TYPEOFFILE_TXT), fEnable);
  585. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_GROUPBOX ), fEnable);
  586. // if user is locked down then we do not enable the buttons
  587. if (!fTrue)
  588. fEnable = FALSE;
  589. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_CHANGEOPENSWITH), fEnable);
  590. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_EDITTYPEOFFILE), fEnable);
  591. return S_OK;
  592. }
  593. HRESULT CFTPropDlg::_InitPreFillListView()
  594. {
  595. // Disable New and Delete
  596. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_NEW), FALSE);
  597. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_REMOVE), FALSE);
  598. _EnableLowerPane(FALSE);
  599. _UpdateGroupBox(TEXT(""), TRUE);
  600. // Hide the advanced text
  601. ShowWindow(GetDlgItem(_hwnd, IDC_FT_PROP_TYPEOFFILE_TXT), SW_HIDE);
  602. return S_OK;
  603. }
  604. HRESULT CFTPropDlg::_InitPostFillListView()
  605. {
  606. BOOL fTrue = _ShouldEnableButtons();
  607. // Enable New and Delete
  608. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_NEW), fTrue);
  609. EnableWindow(GetDlgItem(_hwnd, IDC_FT_PROP_REMOVE), fTrue);
  610. // Show the advanced text
  611. ShowWindow(GetDlgItem(_hwnd, IDC_FT_PROP_TYPEOFFILE_TXT), SW_SHOW);
  612. Animate_Stop(GetDlgItem(_hwnd, IDC_FT_PROP_ANIM));
  613. ShowWindow(GetDlgItem(_hwnd, IDC_FT_PROP_ANIM), SW_HIDE);
  614. ShowWindow(_GetLVHWND(), SW_SHOW);
  615. SetFocus(_GetLVHWND());
  616. return S_OK;
  617. }
  618. HRESULT CFTPropDlg::_InitListView()
  619. {
  620. HRESULT hres = S_OK;
  621. LVCOLUMN lvColumn = {0};
  622. HWND hwndLV = _GetLVHWND();
  623. TCHAR szColumnTitle[40];
  624. RECT rc = {0};
  625. int iWidth = 80;
  626. HWND hwndAni;
  627. //
  628. // Styles
  629. //
  630. ListView_SetExtendedListViewStyleEx(hwndLV, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  631. //
  632. // Set the columns
  633. //
  634. lvColumn.mask = LVCF_TEXT|LVCF_SUBITEM|LVCF_WIDTH;
  635. // Extensions column
  636. LoadString(g_hinst, IDS_FT_PROP_EXTENSIONS, szColumnTitle, ARRAYSIZE(szColumnTitle));
  637. lvColumn.cx = 60;
  638. lvColumn.pszText = szColumnTitle;
  639. lvColumn.cchTextMax = lstrlen(szColumnTitle);
  640. lvColumn.iSubItem = SUBITEM_EXT;
  641. ListView_InsertColumn(hwndLV, SUBITEM_EXT, &lvColumn);
  642. // ProgIDs column
  643. LoadString(g_hinst, IDS_FT, szColumnTitle, ARRAYSIZE(szColumnTitle));
  644. lvColumn.cchTextMax = lstrlen(szColumnTitle);
  645. lvColumn.iSubItem = SUBITEM_PROGIDDESCR;
  646. ListView_InsertColumn(hwndLV, SUBITEM_PROGIDDESCR, &lvColumn);
  647. // Adjust columns width
  648. // we need to do it after inserting both col, cause the last column resizing
  649. // is special cased in list view code.
  650. // Ext column
  651. ListView_SetColumnWidth(hwndLV, SUBITEM_EXT, LVSCW_AUTOSIZE_USEHEADER);
  652. iWidth = ListView_GetColumnWidth(hwndLV, SUBITEM_EXT);
  653. // File type column
  654. GetClientRect(hwndLV, &rc);
  655. ListView_SetColumnWidth(hwndLV, SUBITEM_PROGIDDESCR,
  656. rc.right - iWidth - GetSystemMetrics(SM_CXBORDER) - GetSystemMetrics(SM_CXVSCROLL));
  657. //
  658. // ImageList
  659. //
  660. Shell_GetImageLists(NULL, &_hImageList);
  661. if (_hImageList)
  662. ListView_SetImageList(hwndLV, _hImageList, LVSIL_SMALL);
  663. GetWindowRect(hwndLV, &rc);
  664. MapWindowPoints(NULL, _hwnd, (POINT*)&rc, 2);
  665. hwndAni = GetDlgItem(_hwnd, IDC_FT_PROP_ANIM);
  666. Animate_Open(hwndAni, MAKEINTRESOURCE(IDA_SEARCH)); // open the resource
  667. Animate_Play(hwndAni, 0, -1, -1); // play from start to finish and repeat
  668. MoveWindow(hwndAni, rc.left, rc.top,
  669. rc.right - rc.left, rc.bottom - rc.top, TRUE);
  670. ShowWindow(hwndLV, SW_HIDE);
  671. ShowWindow(hwndAni, SW_SHOW);
  672. return hres;
  673. }
  674. HRESULT CFTPropDlg::_FillListView()
  675. {
  676. // Data stuff
  677. IEnumAssocInfo* pEnum = NULL;
  678. HRESULT hres = E_FAIL;
  679. int iFirstNAItem = -1;
  680. HWND hwndLV = NULL;
  681. int iItem = 0;
  682. TCHAR szNA[50];
  683. ASSERT(_pAssocStore);
  684. // Do the extension first
  685. if (!_fStopThread)
  686. {
  687. hwndLV = _GetLVHWND();
  688. SetWindowRedraw(hwndLV, FALSE);
  689. }
  690. if (!_fStopThread)
  691. {
  692. LoadString(g_hinst, IDS_FT_NA, szNA, ARRAYSIZE(szNA));
  693. hres = _pAssocStore->EnumAssocInfo(ASENUM_EXT |
  694. ASENUM_ASSOC_YES | ASENUM_NOEXCLUDED | ASENUM_NOEXPLORERSHELLACTION |
  695. ASENUM_NOEXE, NULL, AIINIT_NONE, &pEnum);
  696. }
  697. else
  698. hres = E_FAIL;
  699. if (SUCCEEDED(hres))
  700. {
  701. IAssocInfo* pAI = NULL;
  702. while (!_fStopThread && (S_OK == pEnum->Next(&pAI)))
  703. {
  704. TCHAR szExt[MAX_EXT];
  705. DWORD cchExt = ARRAYSIZE(szExt);
  706. hres = pAI->GetString(AISTR_EXT, szExt, &cchExt);
  707. if (SUCCEEDED(hres))
  708. {
  709. BOOL fPerUser = FALSE;
  710. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  711. DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr);
  712. HRESULT hresTmp = E_FAIL;
  713. hresTmp = pAI->GetBOOL(AIBOOL_PERUSERINFOAVAILABLE, &fPerUser);
  714. ASSERT(SUCCEEDED(hresTmp) || (FAILED(hresTmp) && (FALSE == fPerUser)));
  715. if (!fPerUser)
  716. {
  717. hresTmp = pAI->GetString(AISTR_PROGIDDESCR, szProgIDDescr,
  718. &cchProgIDDescr);
  719. }
  720. if (fPerUser || FAILED(hresTmp) || !*szProgIDDescr)
  721. MakeDefaultProgIDDescrFromExt(szProgIDDescr, ARRAYSIZE(szProgIDDescr), szExt);
  722. if (!_fStopThread)
  723. _InsertListViewItem(iItem, szExt, szProgIDDescr);
  724. // See comment in ftenum.cpp, CFTEnumAssocInfo::_EnumKCRStop about sorting
  725. // Check if this is where we need to insert the N/A item later
  726. if ((-1 == iFirstNAItem) && (lstrcmpi(szExt, szNA) > 0))
  727. {
  728. iFirstNAItem = iItem;
  729. }
  730. ++iItem;
  731. }
  732. pAI->Release();
  733. hres = S_OK;
  734. }
  735. pEnum->Release();
  736. pEnum = NULL;
  737. }
  738. // Then do the ProgIDs
  739. if (!_fStopThread)
  740. hres = _pAssocStore->EnumAssocInfo(ASENUM_PROGID | ASENUM_SHOWONLY, NULL, AIINIT_NONE, &pEnum);
  741. else
  742. hres = E_FAIL;
  743. if (SUCCEEDED(hres))
  744. {
  745. IAssocInfo* pAI = NULL;
  746. int cNAItem = 0;
  747. while (!_fStopThread && (S_OK == pEnum->Next(&pAI)))
  748. {
  749. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  750. DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr);
  751. hres = pAI->GetString(AISTR_PROGIDDESCR, szProgIDDescr, &cchProgIDDescr);
  752. if (SUCCEEDED(hres))
  753. {
  754. TCHAR szProgID[MAX_PROGID];
  755. DWORD cchProgID = ARRAYSIZE(szProgID);
  756. hres = pAI->GetString(AISTR_PROGID, szProgID, &cchProgID);
  757. if (SUCCEEDED(hres))
  758. {
  759. // we need to sort the N/A items by the description since they all begin with "N/A"
  760. int iNAItem;
  761. if (!cNAItem)
  762. {
  763. iNAItem = iFirstNAItem;
  764. }
  765. else
  766. {
  767. if (!_fStopThread)
  768. iNAItem = _GetNextNAItemPos(iFirstNAItem, cNAItem, szProgIDDescr);
  769. }
  770. if (!_fStopThread)
  771. {
  772. _InsertListViewItem(iNAItem, szNA, szProgIDDescr, szProgID);
  773. ++cNAItem;
  774. }
  775. }
  776. }
  777. pAI->Release();
  778. hres = S_OK;
  779. }
  780. pEnum->Release();
  781. }
  782. if (!_fStopThread)
  783. {
  784. SetWindowRedraw(hwndLV, TRUE);
  785. PostMessage(_hwnd, WM_FINISHFILLLISTVIEW, 0, 0);
  786. }
  787. return hres;
  788. }
  789. int CFTPropDlg::_GetNextNAItemPos(int iFirstNAItem, int cNAItem, LPTSTR pszProgIDDescr)
  790. {
  791. LVITEM lvItem = {0};
  792. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  793. int iItem = iFirstNAItem;
  794. HWND hwndLV = _GetLVHWND();
  795. lvItem.mask = LVIF_TEXT;
  796. lvItem.iItem = iItem;
  797. lvItem.iSubItem = SUBITEM_PROGIDDESCR;
  798. lvItem.pszText = szProgIDDescr;
  799. lvItem.cchTextMax = ARRAYSIZE(szProgIDDescr);
  800. while (iItem < (iFirstNAItem + cNAItem))
  801. {
  802. if (ListView_GetItem(hwndLV, &lvItem))
  803. {
  804. if (lstrcmpi(pszProgIDDescr, lvItem.pszText) >= 0)
  805. {
  806. ++iItem;
  807. lvItem.iItem = iItem;
  808. }
  809. else
  810. {
  811. break;
  812. }
  813. }
  814. else
  815. {
  816. // This happens when the listview is destroyed (on another thread),
  817. // but this thread is still doing some work. The call above fails,
  818. // we break here or else we'll never go out of the loop.
  819. break;
  820. }
  821. }
  822. return iItem;
  823. }
  824. DWORD CFTPropDlg::_UpdateAllListViewItemImages()
  825. {
  826. HWND hwndLV = NULL;
  827. int iCount = 0;
  828. LVITEM lvItem = {0};
  829. TCHAR szExt[MAX_EXT];
  830. HRESULT hres = E_FAIL;
  831. HRESULT hrInit = SHCoInitialize();
  832. lvItem.iSubItem = SUBITEM_EXT;
  833. lvItem.pszText = szExt;
  834. lvItem.cchTextMax = ARRAYSIZE(szExt);
  835. if (!_fStopThread)
  836. hwndLV = _GetLVHWND();
  837. do
  838. {
  839. _fUpdateImageAgain = FALSE;
  840. if (!_fStopThread)
  841. iCount = ListView_GetItemCount(hwndLV);
  842. for (lvItem.iItem = 0; !_fStopThread && (lvItem.iItem < iCount);
  843. ++lvItem.iItem)
  844. {
  845. IAssocInfo* pAI = NULL;
  846. lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  847. if (!_fStopThread)
  848. ListView_GetItem(hwndLV, &lvItem);
  849. if (!_fStopThread && !lvItem.lParam)
  850. {
  851. hres = _pAssocStore->GetAssocInfo(szExt, AIINIT_EXT, &pAI);
  852. if (SUCCEEDED(hres))
  853. {
  854. BOOL fPerUser = FALSE;
  855. hres = pAI->GetBOOL(AIBOOL_PERUSERINFOAVAILABLE, &fPerUser);
  856. ASSERT(SUCCEEDED(hres) || (FAILED(hres) && (FALSE == fPerUser)));
  857. if (fPerUser)
  858. hres = pAI->GetDWORD(AIDWORD_DOCSMALLICON | AIALL_PERUSER, (DWORD*)&lvItem.iImage);
  859. else
  860. hres = pAI->GetDWORD(AIDWORD_DOCSMALLICON, (DWORD*)&lvItem.iImage);
  861. }
  862. }
  863. else
  864. {
  865. hres = _pAssocStore->GetAssocInfo((LPTSTR)lvItem.lParam, AIINIT_PROGID, &pAI);
  866. if (SUCCEEDED(hres))
  867. {
  868. hres = pAI->GetDWORD(AIDWORD_DOCSMALLICON, (DWORD*)&lvItem.iImage);
  869. }
  870. }
  871. if (SUCCEEDED(hres))
  872. {
  873. lvItem.mask = LVIF_IMAGE;
  874. if (!_fStopThread)
  875. ListView_SetItem(hwndLV, &lvItem);
  876. }
  877. if (pAI)
  878. pAI->Release();
  879. }
  880. }
  881. while (_fUpdateImageAgain && !_fStopThread);
  882. SHCoUninitialize(hrInit);
  883. return (DWORD)_fStopThread;
  884. }
  885. void CFTPropDlg::_UpdateListViewItem(LVITEM* plvItem)
  886. {
  887. HWND hwndLV = _GetLVHWND();
  888. LVITEM lvItem = *plvItem;
  889. // Need to:
  890. // - update image
  891. // - update progIDDescr
  892. if (!lvItem.lParam)
  893. {
  894. IAssocInfo* pAI = NULL;
  895. HRESULT hres = _pAssocStore->GetAssocInfo(lvItem.pszText, AIINIT_EXT, &pAI);
  896. if (SUCCEEDED(hres))
  897. {
  898. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  899. DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr);
  900. HRESULT hresTmp = E_FAIL;
  901. SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
  902. // Icon
  903. BOOL fPerUser = FALSE;
  904. hres = pAI->GetBOOL(AIBOOL_PERUSERINFOAVAILABLE, &fPerUser);
  905. ASSERT(SUCCEEDED(hres) || (FAILED(hres) && (FALSE == fPerUser)));
  906. if (fPerUser)
  907. hres = pAI->GetDWORD(AIDWORD_DOCSMALLICON | AIALL_PERUSER, (DWORD*)&lvItem.iImage);
  908. else
  909. hres = pAI->GetDWORD(AIDWORD_DOCSMALLICON, (DWORD*)&lvItem.iImage);
  910. if (SUCCEEDED(hres))
  911. {
  912. lvItem.mask = LVIF_IMAGE;
  913. ListView_SetItem(hwndLV, &lvItem);
  914. }
  915. // ProgID Description
  916. if (!fPerUser)
  917. {
  918. hresTmp = pAI->GetString(AISTR_PROGIDDESCR, szProgIDDescr,
  919. &cchProgIDDescr);
  920. }
  921. if (fPerUser || FAILED(hresTmp) || !*szProgIDDescr)
  922. MakeDefaultProgIDDescrFromExt(szProgIDDescr, ARRAYSIZE(szProgIDDescr), lvItem.pszText);
  923. if (SUCCEEDED(hres))
  924. {
  925. lvItem.mask = LVIF_TEXT;
  926. lvItem.iSubItem = SUBITEM_PROGIDDESCR;
  927. lvItem.pszText = szProgIDDescr;
  928. lvItem.cchTextMax = lstrlen(szProgIDDescr);
  929. ListView_SetItem(hwndLV, &lvItem);
  930. }
  931. ListView_RedrawItems(hwndLV, lvItem.iItem, lvItem.iItem);
  932. pAI->Release();
  933. }
  934. }
  935. else
  936. {
  937. IAssocInfo* pAI = NULL;
  938. HRESULT hres = _pAssocStore->GetAssocInfo((LPTSTR)lvItem.lParam, AIINIT_PROGID, &pAI);
  939. if (SUCCEEDED(hres))
  940. {
  941. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  942. DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr);
  943. HRESULT hresTmp = E_FAIL;
  944. SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
  945. // Icon
  946. hres = pAI->GetDWORD(AIDWORD_DOCSMALLICON, (DWORD*)&lvItem.iImage);
  947. if (SUCCEEDED(hres))
  948. {
  949. lvItem.mask = LVIF_IMAGE;
  950. ListView_SetItem(hwndLV, &lvItem);
  951. }
  952. // ProgID Description
  953. pAI->GetString(AISTR_PROGIDDESCR, szProgIDDescr,
  954. &cchProgIDDescr);
  955. if (SUCCEEDED(hres))
  956. {
  957. lvItem.mask = LVIF_TEXT;
  958. lvItem.iSubItem = SUBITEM_PROGIDDESCR;
  959. lvItem.pszText = szProgIDDescr;
  960. lvItem.cchTextMax = lstrlen(szProgIDDescr);
  961. ListView_SetItem(hwndLV, &lvItem);
  962. }
  963. ListView_RedrawItems(hwndLV, lvItem.iItem, lvItem.iItem);
  964. pAI->Release();
  965. }
  966. }
  967. }
  968. int CFTPropDlg::_InsertListViewItem(int iItem, LPTSTR pszExt, LPTSTR pszProgIDDescr,
  969. LPTSTR pszProgID)
  970. {
  971. HWND hwndLV = _GetLVHWND();
  972. LVITEM lvItem = {0};
  973. lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  974. // Put generic icon
  975. lvItem.iImage = Shell_GetCachedImageIndex(TEXT("shell32.dll"), II_DOCNOASSOC, 0);
  976. CharUpper(pszExt);
  977. // Extension
  978. if (pszProgID)
  979. {
  980. lvItem.lParam = (LPARAM)LocalAlloc(LPTR, (lstrlen(pszProgID) + 1) * sizeof(TCHAR));
  981. if (lvItem.lParam)
  982. lstrcpy((LPTSTR)lvItem.lParam, pszProgID);
  983. }
  984. else
  985. {
  986. lvItem.lParam = NULL;
  987. }
  988. lvItem.iItem = iItem;
  989. lvItem.iSubItem = SUBITEM_EXT;
  990. lvItem.pszText = pszExt;
  991. lvItem.cchTextMax = lstrlen(pszExt);
  992. lvItem.iItem = ListView_InsertItem(hwndLV, &lvItem);
  993. if (-1 != lvItem.iItem)
  994. {
  995. // ProgID Description
  996. lvItem.mask = LVIF_TEXT;
  997. lvItem.iSubItem = SUBITEM_PROGIDDESCR;
  998. lvItem.pszText = pszProgIDDescr;
  999. lvItem.cchTextMax = lstrlen(pszProgIDDescr);
  1000. ListView_SetItem(hwndLV, &lvItem);
  1001. }
  1002. else
  1003. {
  1004. // LocalFree checks for NULL
  1005. LocalFree((HLOCAL)lvItem.lParam);
  1006. }
  1007. return lvItem.iItem;
  1008. }
  1009. HRESULT CFTPropDlg::_SelectListViewItem(int i)
  1010. {
  1011. LVITEM lvItem = {0};
  1012. lvItem.iItem = i;
  1013. lvItem.mask = LVIF_STATE;
  1014. lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  1015. lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
  1016. ListView_SetItem(_GetLVHWND(), &lvItem);
  1017. ListView_EnsureVisible(_GetLVHWND(), i, FALSE);
  1018. return S_OK;
  1019. }
  1020. HRESULT CFTPropDlg::_DeleteListViewItem(int i)
  1021. {
  1022. HWND hwndLV = _GetLVHWND();
  1023. int iCount = ListView_GetItemCount(hwndLV);
  1024. int iNextSel = -1;
  1025. LVITEM lvItem = {0};
  1026. lvItem.mask = LVIF_PARAM;
  1027. lvItem.iItem = i;
  1028. lvItem.iSubItem = SUBITEM_EXT;
  1029. ListView_GetItem(hwndLV, &lvItem);
  1030. if (lvItem.lParam)
  1031. {
  1032. LocalFree((HLOCAL)lvItem.lParam);
  1033. }
  1034. ListView_DeleteItem(hwndLV, i);
  1035. if (iCount > i)
  1036. iNextSel = i;
  1037. else
  1038. if (i > 0)
  1039. iNextSel = i - 1;
  1040. if (-1 != iNextSel)
  1041. _SelectListViewItem(iNextSel);
  1042. return S_OK;
  1043. }
  1044. BOOL CFTPropDlg::_ShouldEnableButtons()
  1045. {
  1046. // if we have a locked down user, then we never enable the buttons
  1047. BOOL fRet = TRUE;
  1048. if (S_FALSE == _pAssocStore->CheckAccess())
  1049. {
  1050. fRet = FALSE;
  1051. }
  1052. // If the REST_NOFILEASSOCIATE is set (TRUE),
  1053. // then we want to NOT enable buttons.
  1054. fRet &= !SHRestricted(REST_NOFILEASSOCIATE);
  1055. return fRet;
  1056. }
  1057. ///////////////////////////////////////////////////////////////////////////////
  1058. // Misc
  1059. BOOL CFTPropDlg::_GetListViewSelectedItem(UINT uMask, UINT uStateMask, LVITEM* plvItem)
  1060. {
  1061. BOOL fSel = FALSE;
  1062. HWND hwndLV = _GetLVHWND();
  1063. plvItem->mask = uMask | LVIF_STATE;
  1064. plvItem->stateMask = uStateMask | LVIS_SELECTED;
  1065. // Do we have the selection cached?
  1066. if (-1 != _iLVSel)
  1067. {
  1068. // Yes, make sure it's valid
  1069. plvItem->iItem = _iLVSel;
  1070. ListView_GetItem(hwndLV, plvItem);
  1071. if (plvItem->state & LVIS_SELECTED)
  1072. fSel = TRUE;
  1073. }
  1074. // Cache was wrong
  1075. if (!fSel)
  1076. {
  1077. int iCount = ListView_GetItemCount(hwndLV);
  1078. for (int i=0; (i < iCount) && !fSel; ++i)
  1079. {
  1080. plvItem->iItem = i;
  1081. ListView_GetItem(hwndLV, plvItem);
  1082. if (plvItem->state & LVIS_SELECTED)
  1083. fSel = TRUE;
  1084. }
  1085. if (fSel)
  1086. _iLVSel = i;
  1087. }
  1088. return fSel;
  1089. }
  1090. HWND CFTPropDlg::_GetLVHWND()
  1091. {
  1092. return GetDlgItem(_hwnd, IDC_FT_PROP_LV_FILETYPES);
  1093. }
  1094. void CFTPropDlg::_SetAdvancedRestoreButtonHelpID(DWORD dwID)
  1095. {
  1096. for (int i = 0; i < ARRAYSIZE(s_rgdwHelpIDsArray); i += 2)
  1097. {
  1098. if (IDC_FT_PROP_EDITTYPEOFFILE == s_rgdwHelpIDsArray[i])
  1099. {
  1100. if (i + 1 < ARRAYSIZE(s_rgdwHelpIDsArray))
  1101. s_rgdwHelpIDsArray[i + 1] = dwID;
  1102. break;
  1103. }
  1104. }
  1105. }
  1106. ///////////////////////////////////////////////////////////////////////////////
  1107. // Windows boiler plate code
  1108. LRESULT CFTPropDlg::OnNotifyListView(UINT uCode, LPNMHDR pNMHDR)
  1109. {
  1110. LRESULT lRes = FALSE;
  1111. switch(uCode)
  1112. {
  1113. case LVN_GETINFOTIP:
  1114. {
  1115. NMLVGETINFOTIP* plvn = (NMLVGETINFOTIP*)pNMHDR;
  1116. break;
  1117. }
  1118. case LVN_ITEMCHANGED:
  1119. {
  1120. NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;
  1121. // Is a new item being selected?
  1122. if ((pNMLV->uChanged & LVIF_STATE) &&
  1123. (pNMLV->uNewState & (LVIS_SELECTED | LVIS_FOCUSED)))
  1124. {
  1125. // Yes
  1126. OnListViewSelItem(pNMLV->iItem, pNMLV->lParam);
  1127. }
  1128. break;
  1129. }
  1130. case LVN_COLUMNCLICK:
  1131. {
  1132. NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;
  1133. OnListViewColumnClick(pNMLV->iSubItem);
  1134. break;
  1135. }
  1136. case NM_DBLCLK:
  1137. if (IsWindowEnabled(GetDlgItem(_hwnd, IDC_FT_PROP_EDIT)))
  1138. PostMessage(_hwnd, WM_COMMAND, (WPARAM)IDC_FT_PROP_EDIT, 0);
  1139. break;
  1140. }
  1141. return lRes;
  1142. }
  1143. LRESULT CFTPropDlg::OnCommand(WPARAM wParam, LPARAM lParam)
  1144. {
  1145. LRESULT lRes = FALSE;
  1146. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1147. {
  1148. case IDC_FT_PROP_NEW:
  1149. lRes = OnNewButton(GET_WM_COMMAND_CMD(wParam, lParam));
  1150. break;
  1151. case IDC_FT_PROP_REMOVE:
  1152. lRes = OnDeleteButton(GET_WM_COMMAND_CMD(wParam, lParam));
  1153. break;
  1154. case IDC_FT_PROP_EDITTYPEOFFILE:
  1155. lRes = OnAdvancedButton(GET_WM_COMMAND_CMD(wParam, lParam));
  1156. break;
  1157. case IDC_FT_PROP_CHANGEOPENSWITH:
  1158. lRes = OnChangeButton(GET_WM_COMMAND_CMD(wParam, lParam));
  1159. break;
  1160. default:
  1161. lRes = CFTDlg::OnCommand(wParam, lParam);
  1162. break;
  1163. }
  1164. return lRes;
  1165. }
  1166. LRESULT CFTPropDlg::OnNotify(WPARAM wParam, LPARAM lParam)
  1167. {
  1168. LRESULT lRes = FALSE;
  1169. LPNMHDR pNMHDR = (LPNMHDR)lParam;
  1170. UINT_PTR idFrom = pNMHDR->idFrom;
  1171. UINT uCode = pNMHDR->code;
  1172. //GET_WM_COMMAND_CMD
  1173. switch(idFrom)
  1174. {
  1175. case IDC_FT_PROP_LV_FILETYPES:
  1176. lRes = OnNotifyListView(uCode, pNMHDR);
  1177. break;
  1178. default:
  1179. lRes = CFTDlg::OnNotify(wParam, lParam);
  1180. break;
  1181. }
  1182. return lRes;
  1183. }
  1184. LRESULT CFTPropDlg::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  1185. {
  1186. LRESULT lRes = FALSE;
  1187. switch(uMsg)
  1188. {
  1189. case WM_CTLCOLORSTATIC:
  1190. lRes = OnCtlColorStatic(wParam, lParam);
  1191. break;
  1192. case WM_FINISHFILLLISTVIEW:
  1193. lRes = OnFinishInitDialog();
  1194. break;
  1195. default:
  1196. lRes = CFTDlg::WndProc(uMsg, wParam, lParam);
  1197. break;
  1198. }
  1199. return lRes;
  1200. }