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.

1625 lines
42 KiB

  1. #include "shellprv.h"
  2. #include "ids.h"
  3. #include "help.h"
  4. #include "apithk.h"
  5. #include "ascstr.h"
  6. #include "filetype.h"
  7. #include "ftdlg.h"
  8. #include "ftadv.h"
  9. #include "ftaction.h"
  10. const static DWORD cs_rgdwHelpIDsArray[] =
  11. { // Context Help IDs
  12. IDC_NO_HELP_1, NO_HELP,
  13. IDC_FT_EDIT_DOCICON, IDH_FCAB_FT_EDIT_DOCICON,
  14. IDC_FT_EDIT_DESC, IDH_FCAB_FT_EDIT_DESC,
  15. IDC_FT_EDIT_CHANGEICON, IDH_FCAB_FT_EDIT_CHANGEICON,
  16. IDC_FT_EDIT_LV_CMDSTEXT, IDH_FCAB_FT_EDIT_LV_CMDS,
  17. IDC_FT_EDIT_LV_CMDS, IDH_FCAB_FT_EDIT_LV_CMDS,
  18. IDC_FT_EDIT_NEW, IDH_FCAB_FT_EDIT_NEW,
  19. IDC_FT_EDIT_EDIT, IDH_FCAB_FT_EDIT_EDIT,
  20. IDC_FT_EDIT_REMOVE, IDH_FCAB_FT_EDIT_REMOVE,
  21. IDC_FT_EDIT_DEFAULT, IDH_FCAB_FT_EDIT_DEFAULT,
  22. IDC_FT_EDIT_CONFIRM_OPEN, IDH_CONFIRM_OPEN,
  23. IDC_FT_EDIT_SHOWEXT, IDH_FCAB_FT_EDIT_SHOWEXT,
  24. IDC_FT_EDIT_BROWSEINPLACE, IDH_SAME_WINDOW,
  25. 0, 0
  26. };
  27. struct LV_ADDDATA
  28. {
  29. BOOL fDefaultAction;
  30. TCHAR szActionReg[MAX_ACTION];
  31. };
  32. #define ADDDATA_ACTIONREG(plvItem) (((LV_ADDDATA*)((plvItem)->lParam))->szActionReg)
  33. #define ADDDATA_DEFAULTACTION(plvItem) (((LV_ADDDATA*)((plvItem)->lParam))->fDefaultAction)
  34. ///////////////////////////////////////////////////////////////////////////////
  35. ///////////////////////////////////////////////////////////////////////////////
  36. CFTAdvDlg::CFTAdvDlg(LPTSTR pszProgID, LPTSTR pszExt) :
  37. CFTDlg((ULONG_PTR)cs_rgdwHelpIDsArray),
  38. _iDefaultAction(-1), _iLVSel(-1)
  39. {
  40. _szProgID[0] = NULL;
  41. if (pszProgID)
  42. StrCpyN(_szProgID, pszProgID, ARRAYSIZE(_szProgID));
  43. _szExt[0] = NULL;
  44. if (pszExt && (*pszExt != NULL))
  45. {
  46. wnsprintf(_szExt, ARRAYSIZE(_szExt), TEXT(".%s"), pszExt);
  47. }
  48. _hdpaActions = DPA_Create(4);
  49. _hdpaRemovedActions = DPA_Create(1);
  50. }
  51. static int _DeleteLocalAllocCB(void *pItem, void *pData)
  52. {
  53. LocalFree((HLOCAL)pItem);
  54. return 1;
  55. }
  56. CFTAdvDlg::~CFTAdvDlg()
  57. {
  58. if (_hIcon)
  59. DeleteObject(_hIcon);
  60. if (_hfontReg)
  61. DeleteObject(_hfontReg);
  62. if (_hfontBold)
  63. DeleteObject(_hfontBold);
  64. if (_hdpaActions)
  65. DPA_DestroyCallback(_hdpaActions, _DeleteLocalAllocCB, NULL);
  66. if (_hdpaRemovedActions)
  67. DPA_DestroyCallback(_hdpaRemovedActions, _DeleteLocalAllocCB, NULL);
  68. }
  69. ///////////////////////////////////////////////////////////////////////////////
  70. // Logic specific to our problem
  71. LRESULT CFTAdvDlg::OnInitDialog(WPARAM wParam, LPARAM lParam)
  72. {
  73. HRESULT hres = _InitAssocStore();
  74. DECLAREWAITCURSOR;
  75. SetWaitCursor();
  76. if (SUCCEEDED(hres))
  77. {
  78. _InitListView();
  79. _InitDefaultActionFont();
  80. // FTEdit_AreDefaultViewersInstalled ????
  81. if (*_szProgID)
  82. {
  83. _SetDocIcon();
  84. _InitDescription();
  85. _FillListView();
  86. _InitDefaultAction();
  87. _SelectListViewItem(0);
  88. _InitChangeIconButton();
  89. _UpdateCheckBoxes();
  90. }
  91. }
  92. else
  93. EndDialog(_hwnd, -1);
  94. ResetWaitCursor();
  95. // Return TRUE so that system set focus
  96. return TRUE;
  97. }
  98. int CFTAdvDlg::_GetIconIndex()
  99. {
  100. // check under the file progid
  101. int iImageIndex = -1;
  102. IAssocInfo* pAI = NULL;
  103. HRESULT hr = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
  104. if (SUCCEEDED(hr))
  105. {
  106. hr = pAI->GetDWORD(AIDWORD_DOCLARGEICON, (DWORD*)&iImageIndex);
  107. pAI->Release();
  108. }
  109. return iImageIndex;
  110. }
  111. HRESULT CFTAdvDlg::_SetDocIcon(int iIndex)
  112. {
  113. HRESULT hres = E_FAIL;
  114. if (-1 == iIndex)
  115. {
  116. iIndex = _GetIconIndex();
  117. }
  118. if (-1 != iIndex)
  119. {
  120. HIMAGELIST hIL = NULL;
  121. Shell_GetImageLists(&hIL, NULL);
  122. if (_hIcon)
  123. {
  124. DeleteObject(_hIcon);
  125. _hIcon = NULL;
  126. }
  127. if (hIL)
  128. {
  129. _hIcon = ImageList_ExtractIcon(g_hinst, hIL, iIndex);
  130. _hIcon = (HICON)CopyImage(_hIcon, IMAGE_ICON, 32, 32, LR_COPYDELETEORG);
  131. HICON hiOld = (HICON)SendDlgItemMessage(_hwnd, IDC_FT_EDIT_DOCICON, STM_SETIMAGE, IMAGE_ICON,
  132. (LPARAM)_hIcon);
  133. if (hiOld)
  134. DestroyIcon(hiOld);
  135. }
  136. }
  137. return hres;
  138. }
  139. LRESULT CFTAdvDlg::OnListViewSelItem(int iItem, LPARAM lParam)
  140. {
  141. _UpdateActionButtons();
  142. return TRUE;
  143. }
  144. LRESULT CFTAdvDlg::OnMeasureItem(WPARAM wParam, LPARAM lParam)
  145. {
  146. TEXTMETRIC tm = {0};
  147. RECT rect;
  148. LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam;
  149. HDC hdc = GetDC(NULL);
  150. HFONT hfontOld = (HFONT)SelectObject(hdc, _hfontBold);
  151. GetTextMetrics(hdc, &tm);
  152. GetClientRect(_GetLVHWND(), &rect);
  153. lpmis->itemWidth = rect.right;
  154. lpmis->itemHeight = tm.tmHeight;
  155. SelectObject(hdc, hfontOld);
  156. ReleaseDC(NULL, hdc);
  157. return TRUE;
  158. }
  159. LRESULT CFTAdvDlg::OnDrawItem(WPARAM wParam, LPARAM lParam)
  160. {
  161. LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
  162. LRESULT lRet = FALSE;
  163. if (ODT_LISTVIEW == lpDIS->CtlType)
  164. {
  165. HWND hwndLV = _GetLVHWND();
  166. LVITEM lvItem = {0};
  167. HFONT hfontOld = NULL;
  168. BOOL fSel = FALSE;
  169. BOOL fListFocus = FALSE;
  170. TCHAR szAction[MAX_ACTION];
  171. COLORREF crBkgd = 0;
  172. COLORREF crOldText = 0;
  173. lvItem.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
  174. lvItem.iItem = lpDIS->itemID;
  175. lvItem.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
  176. lvItem.pszText = szAction;
  177. lvItem.cchTextMax = ARRAYSIZE(szAction);
  178. ListView_GetItem(hwndLV, &lvItem);
  179. fSel = (lvItem.state & LVIS_SELECTED);
  180. fListFocus = (GetFocus() == hwndLV);
  181. crBkgd = (fSel ? (fListFocus ? COLOR_HIGHLIGHT : COLOR_3DFACE) : COLOR_WINDOW);
  182. SetBkColor(lpDIS->hDC, GetSysColor(crBkgd));
  183. FillRect(lpDIS->hDC, &lpDIS->rcItem, (HBRUSH)IntToPtr(crBkgd + 1));
  184. crOldText = SetTextColor(lpDIS->hDC,
  185. GetSysColor(fSel ? (fListFocus ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT) :
  186. COLOR_WINDOWTEXT));
  187. // Use Bold font for default action
  188. hfontOld = (HFONT)SelectObject(lpDIS->hDC,
  189. _IsDefaultAction(ADDDATA_ACTIONREG(&lvItem)) ? _hfontBold : _hfontReg);
  190. int iOldBkMode = SetBkMode(lpDIS->hDC, OPAQUE);
  191. DrawText(lpDIS->hDC, szAction, lstrlen(szAction), &lpDIS->rcItem, 0);
  192. SetBkMode(lpDIS->hDC, iOldBkMode);
  193. SetTextColor(lpDIS->hDC, crOldText);
  194. SelectObject(lpDIS->hDC, hfontOld);
  195. if(fListFocus && (lvItem.state & LVIS_FOCUSED))
  196. DrawFocusRect(lpDIS->hDC, &lpDIS->rcItem);
  197. lRet = TRUE;
  198. }
  199. return lRet;
  200. }
  201. HRESULT CFTAdvDlg::_InitDefaultActionFont()
  202. {
  203. HFONT hfontDlg = GetWindowFont(_hwnd);
  204. LOGFONT lf = {0};
  205. LOGFONT lfDlg = {0};
  206. GetObject(hfontDlg, sizeof(LOGFONT), &lfDlg);
  207. SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
  208. // Normal font
  209. lf.lfWeight = FW_NORMAL;
  210. lf.lfHeight = lfDlg.lfHeight;
  211. _hfontReg = CreateFontIndirect(&lf);
  212. // Bold font
  213. lf.lfWeight = FW_BOLD;
  214. _hfontBold = CreateFontIndirect(&lf);
  215. return (_hfontReg && _hfontBold) ? S_OK : E_FAIL;
  216. }
  217. HRESULT CFTAdvDlg::_SelectListViewItem(int i)
  218. {
  219. LVITEM lvItem = {0};
  220. lvItem.iItem = i;
  221. lvItem.mask = LVIF_STATE;
  222. lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  223. lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
  224. ListView_SetItem(_GetLVHWND(), &lvItem);
  225. return S_OK;
  226. }
  227. // pszText and cchTextMax needs to be set
  228. BOOL CFTAdvDlg::_FindActionLVITEM(LPTSTR pszActionReg, LVITEM* plvItem)
  229. {
  230. HWND hwndLV = _GetLVHWND();
  231. int iCount = ListView_GetItemCount(hwndLV);
  232. BOOL fRet = FALSE;
  233. plvItem->mask = LVIF_TEXT | LVIF_PARAM;
  234. for (int i = 0; i < iCount; ++i)
  235. {
  236. plvItem->iItem = i;
  237. if (ListView_GetItem(hwndLV, plvItem))
  238. {
  239. if (!lstrcmpi(pszActionReg, ADDDATA_ACTIONREG(plvItem)))
  240. {
  241. fRet = TRUE;
  242. break;
  243. }
  244. }
  245. }
  246. return fRet;
  247. }
  248. HRESULT CFTAdvDlg::_InitDefaultAction()
  249. {
  250. // Get it from the classstore
  251. IAssocInfo* pAI = NULL;
  252. HRESULT hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
  253. if (SUCCEEDED(hres))
  254. {
  255. TCHAR szActionReg[MAX_ACTION];
  256. DWORD cchActionReg = ARRAYSIZE(szActionReg);
  257. HWND hwndLV = _GetLVHWND();
  258. int iIndex = -1;
  259. hres = pAI->GetString(AISTR_PROGIDDEFAULTACTION, szActionReg, &cchActionReg);
  260. if (SUCCEEDED(hres))
  261. {
  262. TCHAR szActionLVI[MAX_ACTION];
  263. LVITEM lvItem = {0};
  264. lvItem.pszText = szActionLVI;
  265. lvItem.cchTextMax = ARRAYSIZE(szActionLVI);
  266. if (_FindActionLVITEM(szActionReg, &lvItem))
  267. hres = _SetDefaultAction(lvItem.iItem);
  268. else
  269. hres = S_OK;
  270. }
  271. pAI->Release();
  272. }
  273. return hres;
  274. }
  275. BOOL CFTAdvDlg::_GetDefaultAction(LPTSTR pszActionReg, DWORD cchActionReg)
  276. {
  277. BOOL fRet = FALSE;
  278. HWND hwndLV = _GetLVHWND();
  279. LVITEM lvItem = {0};
  280. int iCount = ListView_GetItemCount(hwndLV);
  281. TCHAR szActionRegLocal[MAX_ACTION];
  282. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  283. lvItem.pszText = szActionRegLocal;
  284. lvItem.cchTextMax = ARRAYSIZE(szActionRegLocal);
  285. for (int i = 0; i < iCount; ++i)
  286. {
  287. lvItem.iItem = i;
  288. if (ListView_GetItem(hwndLV, &lvItem))
  289. {
  290. if (ADDDATA_DEFAULTACTION(&lvItem))
  291. {
  292. StrCpyN(pszActionReg, ADDDATA_ACTIONREG(&lvItem), cchActionReg);
  293. fRet = TRUE;
  294. break;
  295. }
  296. }
  297. }
  298. return fRet;
  299. }
  300. BOOL CFTAdvDlg::_IsDefaultAction(LPTSTR pszActionReg)
  301. {
  302. BOOL fRet = FALSE;
  303. TCHAR szActionReg[MAX_ACTION];
  304. if (_GetDefaultAction(szActionReg, ARRAYSIZE(szActionReg)))
  305. {
  306. if (!lstrcmpi(szActionReg, pszActionReg))
  307. fRet = TRUE;
  308. }
  309. return fRet;
  310. }
  311. void CFTAdvDlg::_CheckDefaultAction()
  312. {
  313. HWND hwndLV = _GetLVHWND();
  314. // Is there only one elem?
  315. if (1 == ListView_GetItemCount(hwndLV))
  316. {
  317. _SetDefaultActionHelper(0, TRUE);
  318. }
  319. }
  320. HRESULT CFTAdvDlg::_SetDefaultAction(int iIndex)
  321. {
  322. HWND hwndLV = _GetLVHWND();
  323. // Remove previous default if any
  324. if (-1 != _iDefaultAction)
  325. {
  326. _SetDefaultActionHelper(_iDefaultAction, FALSE);
  327. ListView_RedrawItems(hwndLV, _iDefaultAction, _iDefaultAction);
  328. }
  329. // Set new
  330. _iDefaultAction = iIndex;
  331. // iIndex == -1 means no default
  332. if (iIndex >= 0)
  333. {
  334. _SetDefaultActionHelper(_iDefaultAction, TRUE);
  335. ListView_RedrawItems(hwndLV, _iDefaultAction, _iDefaultAction);
  336. }
  337. return S_OK;
  338. }
  339. void CFTAdvDlg::_SetDefaultActionHelper(int iIndex, BOOL fDefault)
  340. {
  341. HWND hwndLV = _GetLVHWND();
  342. LVITEM lvItem = {0};
  343. lvItem.mask = LVIF_PARAM;
  344. lvItem.iItem = iIndex;
  345. _iDefaultAction = -1;
  346. if (ListView_GetItem(hwndLV, &lvItem))
  347. {
  348. ADDDATA_DEFAULTACTION(&lvItem) = fDefault;
  349. _iDefaultAction = iIndex;
  350. }
  351. }
  352. HRESULT CFTAdvDlg::_InitListView()
  353. {
  354. LVCOLUMN lvColumn = {0};
  355. HWND hwndLV = _GetLVHWND();
  356. RECT rc = {0};
  357. {
  358. // What's this?
  359. // We need to handle the WM_MEASUREITEM message from the listview. This msg
  360. // is sent before we receive the WM_INITDIALOG and thus before we connect the
  361. // this C++ obj to the HWND. By changing the style here we receive the msg
  362. // after the C++ obj and the HWND are connected.
  363. LONG lStyle = GetWindowLong(hwndLV, GWL_STYLE);
  364. lStyle &= ~LVS_LIST;
  365. SetWindowLong(hwndLV, GWL_STYLE, lStyle | LVS_REPORT);
  366. }
  367. //
  368. // Set the columns
  369. //
  370. GetClientRect(hwndLV, &rc);
  371. lvColumn.mask = LVCF_SUBITEM|LVCF_WIDTH;
  372. lvColumn.cx = rc.right - GetSystemMetrics(SM_CXBORDER);
  373. lvColumn.iSubItem = 0;
  374. ListView_InsertColumn(hwndLV, 0, &lvColumn);
  375. return S_OK;
  376. }
  377. HRESULT CFTAdvDlg::_UpdateActionButtons()
  378. {
  379. HRESULT hres = E_FAIL;
  380. TCHAR szAction[MAX_ACTION];
  381. BOOL bRet = FALSE;
  382. LVITEM lvItem = {0};
  383. lvItem.pszText = szAction;
  384. lvItem.cchTextMax = ARRAYSIZE(szAction);
  385. bRet = _GetListViewSelectedItem(LVIF_TEXT | LVIF_PARAM, 0, &lvItem);
  386. // If we don't have a selected item Or we don't have any text for that item.
  387. if (!bRet || !(*(lvItem.pszText)))
  388. {
  389. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_EDIT), FALSE);
  390. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_REMOVE), FALSE);
  391. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_DEFAULT), TRUE);
  392. hres = S_OK;
  393. }
  394. else
  395. {
  396. if (_IsNewPROGIDACTION(lvItem.pszText))
  397. {
  398. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_EDIT), TRUE);
  399. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_REMOVE), TRUE);
  400. hres = S_OK;
  401. }
  402. else
  403. {
  404. IAssocInfo* pAI = NULL;
  405. hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
  406. if (SUCCEEDED(hres))
  407. {
  408. DWORD dwAttributes;
  409. HWND hwndLV = _GetLVHWND();
  410. // REARCHITECT: This code should be in ftassoc.cpp, and we should have
  411. // more AIBOOL_ flags for this
  412. hres = pAI->GetDWORD(AIDWORD_PROGIDEDITFLAGS, &dwAttributes);
  413. if (FAILED(hres))
  414. {
  415. // It failed, probably there is no EditFlags value for this progID, let's
  416. // set some default value for dwAttributes
  417. dwAttributes = 0;
  418. }
  419. // REARCHITECT (end)
  420. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_EDIT),
  421. !((dwAttributes & FTA_NoEditVerb) &&
  422. !(dwAttributes & FTAV_UserDefVerb)));
  423. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_REMOVE),
  424. !((dwAttributes & FTA_NoRemoveVerb) &&
  425. !(dwAttributes & FTAV_UserDefVerb)));
  426. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_DEFAULT),
  427. !(dwAttributes & FTA_NoEditDflt));
  428. // Enable the default button only if the action is not already
  429. // the default action
  430. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_DEFAULT),
  431. !_IsDefaultAction(ADDDATA_ACTIONREG(&lvItem)));
  432. pAI->Release();
  433. }
  434. }
  435. }
  436. return hres;
  437. }
  438. HRESULT CFTAdvDlg::_UpdateCheckBoxes()
  439. {
  440. BOOL fBool;
  441. IAssocInfo* pAI = NULL;
  442. HRESULT hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
  443. if (SUCCEEDED(hres))
  444. {
  445. hres = pAI->GetBOOL(AIBOOL_CONFIRMOPEN, &fBool);
  446. if (SUCCEEDED(hres))
  447. CheckDlgButton(_hwnd, IDC_FT_EDIT_CONFIRM_OPEN, !fBool);
  448. hres = pAI->GetBOOL(AIBOOL_ALWAYSSHOWEXT, &fBool);
  449. if (SUCCEEDED(hres))
  450. CheckDlgButton(_hwnd, IDC_FT_EDIT_SHOWEXT, fBool);
  451. hres = pAI->GetBOOL(AIBOOL_BROWSEINPLACEENABLED, &fBool);
  452. if (SUCCEEDED(hres))
  453. {
  454. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_BROWSEINPLACE), fBool);
  455. if (fBool)
  456. {
  457. hres = pAI->GetBOOL(AIBOOL_BROWSEINPLACE, &fBool);
  458. if (SUCCEEDED(hres))
  459. CheckDlgButton(_hwnd, IDC_FT_EDIT_BROWSEINPLACE, fBool);
  460. }
  461. else
  462. CheckDlgButton(_hwnd, IDC_FT_EDIT_BROWSEINPLACE, FALSE);
  463. }
  464. pAI->Release();
  465. }
  466. return hres;
  467. }
  468. HRESULT CFTAdvDlg::_InitChangeIconButton()
  469. {
  470. HRESULT hres = E_FAIL;
  471. BOOL fChangeIcon = TRUE;
  472. IAssocInfo* pAI = NULL;
  473. hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
  474. if (SUCCEEDED(hres))
  475. {
  476. hres = pAI->GetBOOL(AIBOOL_EDITDOCICON, &fChangeIcon);
  477. if (SUCCEEDED(hres))
  478. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_CHANGEICON), fChangeIcon);
  479. pAI->Release();
  480. }
  481. return hres;
  482. }
  483. HRESULT CFTAdvDlg::_InitDescription()
  484. {
  485. HRESULT hres = E_FAIL;
  486. BOOL fEditDescr = TRUE;
  487. IAssocInfo* pAI = NULL;
  488. hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
  489. if (SUCCEEDED(hres))
  490. {
  491. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  492. DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr);
  493. hres = pAI->GetString(AISTR_PROGIDDESCR, szProgIDDescr, &cchProgIDDescr);
  494. if (SUCCEEDED(hres))
  495. SetDlgItemText(_hwnd, IDC_FT_EDIT_DESC, szProgIDDescr);
  496. hres = pAI->GetBOOL(AIBOOL_EDITDESCR, &fEditDescr);
  497. EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_DESC), fEditDescr);
  498. pAI->Release();
  499. Edit_LimitText(GetDlgItem(_hwnd, IDC_FT_EDIT_DESC), MAX_PROGIDDESCR - 1);
  500. }
  501. return hres;
  502. }
  503. HRESULT CFTAdvDlg::_FillListView()
  504. {
  505. HRESULT hres = E_FAIL;
  506. IEnumAssocInfo* pEnum = NULL;
  507. hres = _pAssocStore->EnumAssocInfo(ASENUM_ACTION, _szProgID, AIINIT_PROGID, &pEnum);
  508. if (SUCCEEDED(hres))
  509. {
  510. int iItem = 0;
  511. IAssocInfo* pAI = NULL;
  512. while (S_OK == pEnum->Next(&pAI))
  513. {
  514. TCHAR szActionReg[MAX_ACTION];
  515. DWORD cchActionReg = ARRAYSIZE(szActionReg);
  516. hres = pAI->GetString(AISTR_ACTION, szActionReg, &cchActionReg);
  517. if (SUCCEEDED(hres))
  518. {
  519. TCHAR szActionFN[MAX_ACTION];
  520. DWORD cchActionFN = ARRAYSIZE(szActionFN);
  521. hres = pAI->GetString(AISTR_ACTIONFRIENDLY, szActionFN, &cchActionFN);
  522. if (SUCCEEDED(hres))
  523. {
  524. if (S_FALSE == hres)
  525. {
  526. lstrcpy(szActionFN, szActionReg);
  527. }
  528. if (-1 != _InsertListViewItem(iItem, szActionReg, szActionFN))
  529. {
  530. ++iItem;
  531. }
  532. }
  533. }
  534. pAI->Release();
  535. }
  536. pEnum->Release();
  537. }
  538. return hres;
  539. }
  540. LRESULT CFTAdvDlg::OnChangeIcon(WORD wNotif)
  541. {
  542. IAssocInfo* pAI;
  543. HRESULT hr = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
  544. if (SUCCEEDED(hr))
  545. {
  546. DWORD cchIconLoc = ARRAYSIZE(_szOldIconLoc);
  547. hr = pAI->GetString(AISTR_ICONLOCATION, _szOldIconLoc, &cchIconLoc);
  548. pAI->Release();
  549. _iOldIcon = PathParseIconLocation(_szOldIconLoc);
  550. }
  551. if (FAILED(hr))
  552. {
  553. StrCpyN(_szOldIconLoc, TEXT("shell32.dll"), ARRAYSIZE(_szOldIconLoc));
  554. _iOldIcon = -(IDI_SYSFILE);
  555. hr = S_OK;
  556. }
  557. if (SUCCEEDED(hr))
  558. {
  559. // setup the in params
  560. int iIcon = _iOldIcon;
  561. StrCpyN(_szIconLoc, _szOldIconLoc, ARRAYSIZE(_szIconLoc));
  562. if (PickIconDlg(_hwnd, _szIconLoc, ARRAYSIZE(_szIconLoc), &iIcon))
  563. {
  564. _SetDocIcon(Shell_GetCachedImageIndex(_szIconLoc, iIcon, 0));
  565. // Format the _szIconLoc
  566. int iLen = lstrlen(_szIconLoc);
  567. wnsprintf(_szIconLoc + iLen, ARRAYSIZE(_szIconLoc) - iLen, TEXT(",%d"), iIcon);
  568. }
  569. else
  570. {
  571. _szIconLoc[0] = 0;
  572. }
  573. }
  574. return FALSE;
  575. }
  576. // Return value:
  577. // TRUE: Check succeeded, everything is OK
  578. // FALSE: Check failed
  579. BOOL CFTAdvDlg::_CheckForDuplicateNewAction(LPTSTR pszActionReg, LPTSTR pszActionFN)
  580. {
  581. // we just go through the listview content
  582. HWND hwndLV = _GetLVHWND();
  583. int cItem = ListView_GetItemCount(hwndLV);
  584. BOOL fRet = TRUE;
  585. for (int i = 0; (i < cItem) && fRet; ++i)
  586. {
  587. TCHAR szActionFN[MAX_ACTION];
  588. LVITEM lvItem = {0};
  589. lvItem.mask = LVIF_PARAM | LVIF_TEXT;
  590. lvItem.iItem = i;
  591. lvItem.pszText = szActionFN;
  592. lvItem.cchTextMax = ARRAYSIZE(szActionFN);
  593. ListView_GetItem(hwndLV, &lvItem);
  594. if (!lstrcmpi(lvItem.pszText, pszActionFN))
  595. {
  596. fRet = FALSE;
  597. }
  598. else
  599. {
  600. if (!lstrcmpi(ADDDATA_ACTIONREG(&lvItem), pszActionReg))
  601. {
  602. fRet = FALSE;
  603. }
  604. }
  605. }
  606. return fRet;
  607. }
  608. // Return value:
  609. // TRUE: Check succeeded, everything is OK
  610. // FALSE: Check failed
  611. BOOL CFTAdvDlg::_CheckForDuplicateEditAction(LPTSTR pszActionRegOriginal, LPTSTR pszActionReg,
  612. LPTSTR pszActionFNOriginal, LPTSTR pszActionFN)
  613. {
  614. // we just go through the listview content
  615. HWND hwndLV = _GetLVHWND();
  616. int cItem = ListView_GetItemCount(hwndLV);
  617. BOOL fRet = TRUE;
  618. for (int i = 0; (i < cItem) && fRet; ++i)
  619. {
  620. TCHAR szActionFN[MAX_ACTION];
  621. LVITEM lvItem = {0};
  622. lvItem.mask = LVIF_PARAM | LVIF_TEXT;
  623. lvItem.iItem = i;
  624. lvItem.pszText = szActionFN;
  625. lvItem.cchTextMax = ARRAYSIZE(szActionFN);
  626. ListView_GetItem(hwndLV, &lvItem);
  627. if (!lstrcmpi(lvItem.pszText, pszActionFN))
  628. {
  629. // they are the same, this can happen if this is the Action we were editing
  630. // and we did not change the action name
  631. // Is this the original one we were editing?
  632. if (lstrcmpi(szActionFN, pszActionFNOriginal))
  633. {
  634. // No, it's not the original, we have a dup
  635. fRet = FALSE;
  636. }
  637. }
  638. else
  639. {
  640. if (!lstrcmpi(ADDDATA_ACTIONREG(&lvItem), pszActionReg))
  641. {
  642. // they are the same, this can happen if this is the Action we were editing
  643. // and we did not change the action name
  644. // Is this the original one we were editing?
  645. if (lstrcmpi(ADDDATA_ACTIONREG(&lvItem), pszActionRegOriginal))
  646. {
  647. // No, it's not the original, we have a dup
  648. fRet = FALSE;
  649. }
  650. }
  651. }
  652. }
  653. return fRet;
  654. }
  655. LRESULT CFTAdvDlg::OnNewButton(WORD wNotif)
  656. {
  657. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  658. PROGIDACTION pida = {0};
  659. CFTActionDlg* pActionDlg = NULL;
  660. pida.fNew = TRUE;
  661. GetDlgItemText(_hwnd, IDC_FT_EDIT_DESC, szProgIDDescr, ARRAYSIZE(szProgIDDescr));
  662. // FALSE: New (not-Edit)
  663. pActionDlg = new CFTActionDlg(&pida, szProgIDDescr, FALSE);
  664. if (pActionDlg)
  665. {
  666. BOOL fShowAgain;
  667. do
  668. {
  669. fShowAgain = FALSE;
  670. if (IDOK == pActionDlg->DoModal(g_hinst, MAKEINTRESOURCE(DLG_FILETYPEOPTIONSCMD), _hwnd))
  671. {
  672. // Do we have duplicate actions?
  673. if (_CheckForDuplicateNewAction(pida.szActionReg, pida.szAction))
  674. {
  675. // No
  676. HRESULT hres = _AppendPROGIDACTION(&pida);
  677. if (SUCCEEDED(hres))
  678. {
  679. int iItem = _InsertListViewItem(0, pida.szActionReg, pida.szAction);
  680. hres = S_OK;
  681. if (-1 != iItem)
  682. _SelectListViewItem(iItem);
  683. }
  684. }
  685. else
  686. {
  687. // Yes
  688. fShowAgain = TRUE;
  689. pActionDlg->SetShowAgain();
  690. }
  691. }
  692. if (fShowAgain)
  693. {
  694. ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_FT_MB_EXISTINGACTION),
  695. MAKEINTRESOURCE(IDS_FT), MB_OK | MB_ICONSTOP, pida.szAction);
  696. }
  697. } while (fShowAgain);
  698. pActionDlg->Release();
  699. }
  700. _CheckDefaultAction();
  701. return FALSE;
  702. }
  703. LRESULT CFTAdvDlg::OnEditButton(WORD wNotif)
  704. {
  705. TCHAR szAction[MAX_ACTION];
  706. HRESULT hres = E_FAIL;
  707. LONG lRes = 0;
  708. LVITEM lvItem = {0};
  709. // lvItem.iSubItem = 0;
  710. lvItem.pszText = szAction;
  711. lvItem.cchTextMax = ARRAYSIZE(szAction);
  712. if (_GetListViewSelectedItem(LVIF_TEXT, 0, &lvItem))
  713. {
  714. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  715. PROGIDACTION* pPIDA = NULL;
  716. PROGIDACTION pida = {0};
  717. GetDlgItemText(_hwnd, IDC_FT_EDIT_DESC, szProgIDDescr, ARRAYSIZE(szProgIDDescr));
  718. BOOL fNewOrEdit = SUCCEEDED(_GetPROGIDACTION(lvItem.pszText, &pPIDA));
  719. if (!fNewOrEdit)
  720. {
  721. hres = _FillPROGIDACTION(&pida, ADDDATA_ACTIONREG(&lvItem), szAction);
  722. pPIDA = &pida;
  723. }
  724. else
  725. {
  726. hres = S_OK;
  727. }
  728. if (SUCCEEDED(hres))
  729. {
  730. // TRUE: Edit
  731. CFTActionDlg* pActionDlg = new CFTActionDlg(pPIDA, szProgIDDescr, TRUE);
  732. if (pActionDlg)
  733. {
  734. BOOL fShowAgain;
  735. do
  736. {
  737. fShowAgain = FALSE;
  738. if (IDOK == pActionDlg->DoModal(g_hinst, MAKEINTRESOURCE(DLG_FILETYPEOPTIONSCMD), _hwnd))
  739. {
  740. // Do we have duplicate actions?
  741. if (_CheckForDuplicateEditAction(ADDDATA_ACTIONREG(&lvItem), pPIDA->szActionReg,
  742. lvItem.pszText, pPIDA->szAction))
  743. {
  744. // No
  745. if (!fNewOrEdit)
  746. {
  747. hres = _AppendPROGIDACTION(pPIDA);
  748. }
  749. else
  750. {
  751. hres = S_OK;
  752. }
  753. if (SUCCEEDED(hres))
  754. {
  755. // Replace the current item text
  756. StrCpyN(lvItem.pszText, pPIDA->szAction, ARRAYSIZE(pPIDA->szAction));
  757. ListView_SetItem(_GetLVHWND(), &lvItem);
  758. }
  759. }
  760. else
  761. {
  762. // Yes
  763. fShowAgain = TRUE;
  764. pActionDlg->SetShowAgain();
  765. }
  766. }
  767. if (fShowAgain)
  768. {
  769. ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_FT_MB_EXISTINGACTION),
  770. MAKEINTRESOURCE(IDS_FT), MB_OK | MB_ICONSTOP, pPIDA->szAction);
  771. }
  772. } while (fShowAgain);
  773. pActionDlg->Release();
  774. }
  775. }
  776. }
  777. return FALSE;
  778. }
  779. LRESULT CFTAdvDlg::OnSetDefault(WORD wNotif)
  780. {
  781. BOOL bRet;
  782. LVITEM lvItem = {0};
  783. // lvItem.iSubItem = 0;
  784. bRet = _GetListViewSelectedItem(0, 0, &lvItem);
  785. if (bRet)
  786. _SetDefaultAction(lvItem.iItem);
  787. else
  788. _SetDefaultAction(-1);
  789. return FALSE;
  790. }
  791. LRESULT CFTAdvDlg::OnRemoveButton(WORD wNotif)
  792. {
  793. TCHAR szExt[MAX_EXT];
  794. HRESULT hres = E_FAIL;
  795. LONG lRes = 0;
  796. LVITEM lvItem = {0};
  797. // lvItem.iSubItem = 0;
  798. lvItem.pszText = szExt;
  799. lvItem.cchTextMax = ARRAYSIZE(szExt);
  800. if (_GetListViewSelectedItem(LVIF_TEXT, 0, &lvItem))
  801. {
  802. if (IDYES == ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_FT_MB_REMOVEACTION),
  803. MAKEINTRESOURCE(IDS_FT), MB_YESNO | MB_ICONQUESTION))
  804. {
  805. //
  806. // First take care of data side
  807. //
  808. // Yes. Is this a new Action?
  809. PROGIDACTION* pPIDA = NULL;
  810. if (SUCCEEDED(_GetPROGIDACTION(lvItem.pszText, &pPIDA)) && pPIDA->fNew)
  811. {
  812. // Yes, we'll just remove it from the DPA
  813. hres = _RemovePROGIDACTION(pPIDA);
  814. }
  815. else
  816. {
  817. // No, add its name to the list to delete if user press OK
  818. DWORD cchSize = ARRAYSIZE(ADDDATA_ACTIONREG(&lvItem));
  819. LPTSTR pszActionToRemove = (LPTSTR)LocalAlloc(LPTR,
  820. cchSize * sizeof(TCHAR));
  821. hres = E_OUTOFMEMORY;
  822. if (pszActionToRemove)
  823. {
  824. StrCpyN(pszActionToRemove, ADDDATA_ACTIONREG(&lvItem), cchSize);
  825. if (-1 != DPA_AppendPtr(_hdpaRemovedActions, pszActionToRemove))
  826. hres = S_OK;
  827. else
  828. LocalFree((HLOCAL)pszActionToRemove);
  829. }
  830. if (E_OUTOFMEMORY == hres)
  831. {
  832. //Out of memory
  833. ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_ERROR +
  834. ERROR_NOT_ENOUGH_MEMORY), MAKEINTRESOURCE(IDS_FT),
  835. MB_OK | MB_ICONSTOP);
  836. }
  837. }
  838. //
  839. // Then update UI, I/A
  840. //
  841. if (SUCCEEDED(hres))
  842. {
  843. HWND hwndLV = _GetLVHWND();
  844. int iCount = ListView_GetItemCount(hwndLV);
  845. int iNextSel = -1;
  846. ListView_DeleteItem(hwndLV, lvItem.iItem);
  847. if (iCount > lvItem.iItem)
  848. iNextSel = lvItem.iItem;
  849. else
  850. if (lvItem.iItem > 0)
  851. iNextSel = lvItem.iItem - 1;
  852. if (-1 != iNextSel)
  853. _SelectListViewItem(iNextSel);
  854. }
  855. }
  856. else
  857. hres = S_FALSE;
  858. }
  859. _CheckDefaultAction();
  860. return FALSE;
  861. }
  862. LRESULT CFTAdvDlg::OnOK(WORD wNotif)
  863. {
  864. BOOL fChecksPassed = FALSE;
  865. // Yes, we need to:
  866. // - remove "removed" items, modify "edited" ones,
  867. // and add "New" ones
  868. // - update checkboxes related stuff
  869. // - set the default action
  870. // - set the icon
  871. // - set the description
  872. {
  873. int n = DPA_GetPtrCount(_hdpaRemovedActions);
  874. if (n)
  875. {
  876. IAssocInfo* pAI;
  877. HRESULT hres = E_FAIL;
  878. for (int i = 0; i < n; ++i)
  879. {
  880. LPTSTR pszActionToRemove = (LPTSTR)DPA_GetPtr(_hdpaRemovedActions, i);
  881. if (pszActionToRemove && *pszActionToRemove)
  882. {
  883. hres = _pAssocStore->GetComplexAssocInfo(_szProgID, AIINIT_PROGID,
  884. pszActionToRemove, AIINIT_ACTION, &pAI);
  885. if (SUCCEEDED(hres))
  886. {
  887. pAI->Delete(AIALL_NONE);
  888. pAI->Release();
  889. }
  890. LocalFree((HLOCAL)pszActionToRemove);
  891. DPA_DeletePtr(_hdpaRemovedActions, i);
  892. }
  893. }
  894. }
  895. }
  896. {
  897. int n = DPA_GetPtrCount(_hdpaActions);
  898. if (n)
  899. {
  900. IAssocInfo* pAI = NULL;
  901. HRESULT hres = E_FAIL;
  902. for (int i = n - 1; i >= 0; --i)
  903. {
  904. PROGIDACTION* pPIDAFromList = (PROGIDACTION*)DPA_GetPtr(_hdpaActions, i);
  905. if (pPIDAFromList)
  906. {
  907. // Is it an Edited one?
  908. if (!pPIDAFromList->fNew)
  909. {
  910. // Yes, remove the old one first
  911. hres = _pAssocStore->GetComplexAssocInfo(_szProgID, AIINIT_PROGID,
  912. pPIDAFromList->szOldActionReg, AIINIT_ACTION, &pAI);
  913. if (SUCCEEDED(hres))
  914. {
  915. pAI->Delete(AIALL_NONE);
  916. pAI->Release();
  917. }
  918. }
  919. // Add new data
  920. hres = _pAssocStore->GetComplexAssocInfo(_szProgID, AIINIT_PROGID,
  921. pPIDAFromList->szActionReg, AIINIT_ACTION, &pAI);
  922. if (SUCCEEDED(hres))
  923. {
  924. hres = pAI->SetData(AIDATA_PROGIDACTION, (PBYTE)pPIDAFromList,
  925. sizeof(*pPIDAFromList));
  926. pAI->Release();
  927. }
  928. // Clean up DPA
  929. _DeletePROGIDACTION(pPIDAFromList);
  930. DPA_DeletePtr(_hdpaActions, i);
  931. }
  932. }
  933. }
  934. }
  935. {
  936. IAssocInfo* pAI = NULL;
  937. HWND hwndLV = _GetLVHWND();
  938. LVFINDINFO lvFindInfo = {0};
  939. int iIndex = -1;
  940. HRESULT hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
  941. if (SUCCEEDED(hres))
  942. {
  943. TCHAR szActionReg[MAX_ACTION];
  944. hres = pAI->SetBOOL(AIBOOL_CONFIRMOPEN,
  945. !IsDlgButtonChecked(_hwnd, IDC_FT_EDIT_CONFIRM_OPEN));
  946. hres = pAI->SetBOOL(AIBOOL_ALWAYSSHOWEXT,
  947. IsDlgButtonChecked(_hwnd, IDC_FT_EDIT_SHOWEXT));
  948. hres = pAI->SetBOOL(AIBOOL_BROWSEINPLACE,
  949. IsDlgButtonChecked(_hwnd, IDC_FT_EDIT_BROWSEINPLACE));
  950. // Set the default action, if any
  951. if (_GetDefaultAction(szActionReg, ARRAYSIZE(szActionReg)))
  952. {
  953. hres = pAI->SetString(AISTR_PROGIDDEFAULTACTION, szActionReg);
  954. }
  955. else
  956. {
  957. hres = pAI->SetString(AISTR_PROGIDDEFAULTACTION, TEXT(""));
  958. }
  959. // Set the icon, if changed
  960. if (_szIconLoc[0])
  961. {
  962. // Set it in the registry
  963. hres = pAI->SetString(AISTR_ICONLOCATION, _szIconLoc);
  964. if (_szOldIconLoc[0])
  965. {
  966. int iIconIndex = Shell_GetCachedImageIndex(_szOldIconLoc, _iOldIcon, 0);
  967. SHUpdateImage(_szOldIconLoc, _iOldIcon, 0, iIconIndex);
  968. }
  969. }
  970. // Set the description
  971. {
  972. TCHAR szProgIDDescr[MAX_PROGIDDESCR];
  973. GetDlgItemText(_hwnd, IDC_FT_EDIT_DESC, szProgIDDescr,
  974. ARRAYSIZE(szProgIDDescr));
  975. hres = pAI->SetString(AISTR_PROGIDDESCR, szProgIDDescr);
  976. }
  977. pAI->Release();
  978. }
  979. }
  980. EndDialog(_hwnd, IDOK);
  981. return FALSE;
  982. }
  983. LRESULT CFTAdvDlg::OnNotifyListView(UINT uCode, LPNMHDR pNMHDR)
  984. {
  985. HWND hwndLV = _GetLVHWND();
  986. LRESULT lres = FALSE;
  987. switch(uCode)
  988. {
  989. case NM_DBLCLK:
  990. if (IsWindowEnabled(GetDlgItem(_hwnd, IDC_FT_EDIT_EDIT)))
  991. PostMessage(_hwnd, WM_COMMAND, (WPARAM)IDC_FT_EDIT_EDIT, 0);
  992. break;
  993. //review: do I really need to do this?
  994. case NM_SETFOCUS:
  995. case NM_KILLFOCUS:
  996. // update list view
  997. ListView_RedrawItems(hwndLV, 0, ListView_GetItemCount(hwndLV));
  998. UpdateWindow(hwndLV);
  999. break;
  1000. case LVN_DELETEITEM:
  1001. {
  1002. NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;
  1003. if (pNMLV->lParam)
  1004. {
  1005. LocalFree((HLOCAL)(pNMLV->lParam));
  1006. }
  1007. break;
  1008. }
  1009. case LVN_ITEMCHANGED:
  1010. {
  1011. NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;
  1012. // Is a new item being selected/unselected?
  1013. if (pNMLV->uChanged & LVIF_STATE)
  1014. {
  1015. // Yes
  1016. OnListViewSelItem(pNMLV->iItem, NULL);
  1017. }
  1018. break;
  1019. }
  1020. }
  1021. return lres;
  1022. }
  1023. LRESULT CFTAdvDlg::OnCancel(WORD wNotif)
  1024. {
  1025. EndDialog(_hwnd, IDCANCEL);
  1026. return FALSE;
  1027. }
  1028. LRESULT CFTAdvDlg::OnDestroy(WPARAM wParam, LPARAM lParam)
  1029. {
  1030. CFTDlg::OnDestroy(wParam, lParam);
  1031. return FALSE;
  1032. }
  1033. BOOL CFTAdvDlg::_GetListViewSelectedItem(UINT uMask, UINT uStateMask, LVITEM* plvItem)
  1034. {
  1035. BOOL fSel = FALSE;
  1036. HWND hwndLV = _GetLVHWND();
  1037. plvItem->mask = uMask | LVIF_STATE | LVIF_PARAM;
  1038. plvItem->stateMask = uStateMask | LVIS_SELECTED;
  1039. // Do we have the selection cached?
  1040. if (-1 != _iLVSel)
  1041. {
  1042. // Yes, make sure it's valid
  1043. plvItem->iItem = _iLVSel;
  1044. ListView_GetItem(hwndLV, plvItem);
  1045. if (plvItem->state & LVIS_SELECTED)
  1046. fSel = TRUE;
  1047. }
  1048. // Cache was wrong
  1049. if (!fSel)
  1050. {
  1051. int iCount = ListView_GetItemCount(hwndLV);
  1052. for (int i=0; (i < iCount) && !fSel; ++i)
  1053. {
  1054. plvItem->iItem = i;
  1055. ListView_GetItem(hwndLV, plvItem);
  1056. if (plvItem->state & LVIS_SELECTED)
  1057. fSel = TRUE;
  1058. }
  1059. if (fSel)
  1060. _iLVSel = i;
  1061. }
  1062. return fSel;
  1063. }
  1064. int CFTAdvDlg::_InsertListViewItem(int iItem, LPTSTR pszActionReg, LPTSTR pszActionFN)
  1065. {
  1066. int iRet = -1;
  1067. HWND hwndLV = _GetLVHWND();
  1068. LVITEM lvItem = {0};
  1069. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  1070. // Extension
  1071. lvItem.iItem = iItem;
  1072. lvItem.pszText = pszActionFN;
  1073. lvItem.cchTextMax = lstrlen(pszActionFN);
  1074. LV_ADDDATA* plvadddata = (LV_ADDDATA*)LocalAlloc(LPTR, sizeof(LV_ADDDATA));
  1075. if (plvadddata)
  1076. {
  1077. lvItem.lParam = (LPARAM)plvadddata;
  1078. StrCpyN(ADDDATA_ACTIONREG(&lvItem), pszActionReg, ARRAYSIZE(ADDDATA_ACTIONREG(&lvItem)));
  1079. ADDDATA_DEFAULTACTION(&lvItem) = 0;
  1080. iRet = ListView_InsertItem(hwndLV, &lvItem);
  1081. }
  1082. return iRet;
  1083. }
  1084. HWND CFTAdvDlg::_GetLVHWND()
  1085. {
  1086. return GetDlgItem(_hwnd, IDC_FT_EDIT_LV_CMDS);
  1087. }
  1088. void CFTAdvDlg::_DeletePROGIDACTION(PROGIDACTION* pPIDA)
  1089. {
  1090. if (pPIDA)
  1091. LocalFree((HLOCAL)pPIDA);
  1092. }
  1093. HRESULT CFTAdvDlg::_RemovePROGIDACTION(PROGIDACTION* pPIDA)
  1094. {
  1095. HRESULT hres = E_FAIL;
  1096. int n = DPA_GetPtrCount(_hdpaActions);
  1097. for (int i = 0; (i < n) && FAILED(hres); ++i)
  1098. {
  1099. PROGIDACTION* pPIDAFromList = (PROGIDACTION*)DPA_GetPtr(_hdpaActions, i);
  1100. if (pPIDAFromList == pPIDA)
  1101. {
  1102. _DeletePROGIDACTION(pPIDAFromList);
  1103. DPA_DeletePtr(_hdpaActions, i);
  1104. hres = S_OK;
  1105. }
  1106. }
  1107. return hres;
  1108. }
  1109. HRESULT CFTAdvDlg::_CreatePROGIDACTION(PROGIDACTION** ppPIDA)
  1110. {
  1111. HRESULT hres = E_OUTOFMEMORY;
  1112. *ppPIDA = (PROGIDACTION*)LocalAlloc(LPTR, sizeof(PROGIDACTION));
  1113. if (*ppPIDA)
  1114. hres = S_OK;
  1115. return hres;
  1116. }
  1117. HRESULT CFTAdvDlg::_CopyPROGIDACTION(PROGIDACTION* pPIDADest, PROGIDACTION* pPIDASrc)
  1118. {
  1119. memcpy(pPIDADest, pPIDASrc, sizeof(PROGIDACTION));
  1120. return S_OK;
  1121. }
  1122. HRESULT CFTAdvDlg::_GetPROGIDACTION(LPTSTR pszActionFN, PROGIDACTION** ppPIDA)
  1123. {
  1124. HRESULT hres = E_FAIL;
  1125. *ppPIDA = NULL;
  1126. if (pszActionFN && *pszActionFN)
  1127. {
  1128. int n = DPA_GetPtrCount(_hdpaActions);
  1129. for (int i = 0; (i < n) && FAILED(hres); ++i)
  1130. {
  1131. *ppPIDA = (PROGIDACTION*)DPA_GetPtr(_hdpaActions, i);
  1132. if (!StrCmpN((*ppPIDA)->szAction, pszActionFN, ARRAYSIZE((*ppPIDA)->szAction)))
  1133. hres = S_OK;
  1134. }
  1135. }
  1136. if (FAILED(hres))
  1137. *ppPIDA = NULL;
  1138. return hres;
  1139. }
  1140. HRESULT CFTAdvDlg::_AppendPROGIDACTION(PROGIDACTION* pPIDA)
  1141. {
  1142. PROGIDACTION* pPIDANew = NULL;
  1143. HRESULT hres = _CreatePROGIDACTION(&pPIDANew);
  1144. if (SUCCEEDED(hres))
  1145. {
  1146. _CopyPROGIDACTION(pPIDANew, pPIDA);
  1147. if (-1 != DPA_AppendPtr(_hdpaActions, pPIDANew))
  1148. {
  1149. hres = S_OK;
  1150. }
  1151. else
  1152. {
  1153. _DeletePROGIDACTION(pPIDANew);
  1154. hres = E_OUTOFMEMORY;
  1155. }
  1156. }
  1157. if (E_OUTOFMEMORY == hres)
  1158. {
  1159. //Out of memory
  1160. ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_ERROR +
  1161. ERROR_NOT_ENOUGH_MEMORY), MAKEINTRESOURCE(IDS_FT),
  1162. MB_OK | MB_ICONSTOP);
  1163. }
  1164. return hres;
  1165. }
  1166. BOOL CFTAdvDlg::_IsNewPROGIDACTION(LPTSTR pszActionFN)
  1167. {
  1168. BOOL fRet = FALSE;
  1169. PROGIDACTION* pPIDA = NULL;
  1170. HRESULT hres = _GetPROGIDACTION(pszActionFN, &pPIDA);
  1171. if (SUCCEEDED(hres))
  1172. if (pPIDA->fNew)
  1173. fRet = TRUE;
  1174. return fRet;
  1175. }
  1176. HRESULT CFTAdvDlg::_FillPROGIDACTION(PROGIDACTION* pPIDA, LPTSTR pszActionReg,
  1177. LPTSTR pszActionFN)
  1178. {
  1179. PROGIDACTION* pPIDAList = NULL;
  1180. HRESULT hres = _GetPROGIDACTION(pszActionFN, &pPIDAList);
  1181. if (SUCCEEDED(hres))
  1182. {
  1183. _CopyPROGIDACTION(pPIDA, pPIDAList);
  1184. }
  1185. else
  1186. {
  1187. IAssocInfo* pAI = NULL;
  1188. hres = _pAssocStore->GetComplexAssocInfo(_szProgID, AIINIT_PROGID,
  1189. pszActionReg, AIINIT_ACTION, &pAI);
  1190. if (SUCCEEDED(hres))
  1191. {
  1192. DWORD cbPIDA = sizeof(*pPIDA);
  1193. hres = pAI->GetData(AIDATA_PROGIDACTION, (PBYTE)pPIDA, &cbPIDA);
  1194. pAI->Release();
  1195. }
  1196. }
  1197. return hres;
  1198. }
  1199. ///////////////////////////////////////////////////////////////////////////////
  1200. // Windows boiler plate code
  1201. LRESULT CFTAdvDlg::OnCommand(WPARAM wParam, LPARAM lParam)
  1202. {
  1203. LRESULT lRes = FALSE;
  1204. switch(GET_WM_COMMAND_ID(wParam, lParam))
  1205. {
  1206. case IDC_FT_EDIT_NEW:
  1207. lRes = OnNewButton(GET_WM_COMMAND_CMD(wParam, lParam));
  1208. break;
  1209. case IDC_FT_EDIT_REMOVE:
  1210. lRes = OnRemoveButton(GET_WM_COMMAND_CMD(wParam, lParam));
  1211. break;
  1212. case IDC_FT_EDIT_EDIT:
  1213. lRes = OnEditButton(GET_WM_COMMAND_CMD(wParam, lParam));
  1214. break;
  1215. case IDC_FT_EDIT_CHANGEICON:
  1216. lRes = OnChangeIcon(GET_WM_COMMAND_CMD(wParam, lParam));
  1217. break;
  1218. case IDC_FT_EDIT_DEFAULT:
  1219. lRes = OnSetDefault(GET_WM_COMMAND_CMD(wParam, lParam));
  1220. break;
  1221. default:
  1222. lRes = CFTDlg::OnCommand(wParam, lParam);
  1223. break;
  1224. }
  1225. return lRes;
  1226. }
  1227. LRESULT CFTAdvDlg::OnNotify(WPARAM wParam, LPARAM lParam)
  1228. {
  1229. LRESULT lRes = FALSE;
  1230. LPNMHDR pNMHDR = (LPNMHDR)lParam;
  1231. UINT_PTR idFrom = pNMHDR->idFrom;
  1232. UINT uCode = pNMHDR->code;
  1233. //GET_WM_COMMAND_CMD
  1234. switch(idFrom)
  1235. {
  1236. case IDC_FT_EDIT_LV_CMDS:
  1237. OnNotifyListView(uCode, pNMHDR);
  1238. lRes = CFTDlg::OnNotify(wParam, lParam);
  1239. break;
  1240. default:
  1241. lRes = CFTDlg::OnNotify(wParam, lParam);
  1242. break;
  1243. }
  1244. return lRes;
  1245. }
  1246. LRESULT CFTAdvDlg::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  1247. {
  1248. LRESULT lRes = FALSE;
  1249. switch(uMsg)
  1250. {
  1251. case WM_DRAWITEM:
  1252. lRes = OnDrawItem(wParam, lParam);
  1253. break;
  1254. case WM_MEASUREITEM:
  1255. lRes = OnMeasureItem(wParam, lParam);
  1256. break;
  1257. default:
  1258. lRes = CFTDlg::WndProc(uMsg, wParam, lParam);
  1259. break;
  1260. }
  1261. return lRes;
  1262. }