ftadv.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 40k
Category:

Windows Kernel

Development Platform:

Visual C++

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