1626 lines
42 KiB
C++
1626 lines
42 KiB
C++
|
#include "shellprv.h"
|
||
|
#include "ids.h"
|
||
|
#include "help.h"
|
||
|
|
||
|
#include "apithk.h"
|
||
|
#include "ascstr.h"
|
||
|
#include "filetype.h"
|
||
|
#include "ftdlg.h"
|
||
|
#include "ftadv.h"
|
||
|
#include "ftaction.h"
|
||
|
|
||
|
const static DWORD cs_rgdwHelpIDsArray[] =
|
||
|
{ // Context Help IDs
|
||
|
IDC_NO_HELP_1, NO_HELP,
|
||
|
IDC_FT_EDIT_DOCICON, IDH_FCAB_FT_EDIT_DOCICON,
|
||
|
IDC_FT_EDIT_DESC, IDH_FCAB_FT_EDIT_DESC,
|
||
|
IDC_FT_EDIT_CHANGEICON, IDH_FCAB_FT_EDIT_CHANGEICON,
|
||
|
IDC_FT_EDIT_LV_CMDSTEXT, IDH_FCAB_FT_EDIT_LV_CMDS,
|
||
|
IDC_FT_EDIT_LV_CMDS, IDH_FCAB_FT_EDIT_LV_CMDS,
|
||
|
IDC_FT_EDIT_NEW, IDH_FCAB_FT_EDIT_NEW,
|
||
|
IDC_FT_EDIT_EDIT, IDH_FCAB_FT_EDIT_EDIT,
|
||
|
IDC_FT_EDIT_REMOVE, IDH_FCAB_FT_EDIT_REMOVE,
|
||
|
IDC_FT_EDIT_DEFAULT, IDH_FCAB_FT_EDIT_DEFAULT,
|
||
|
IDC_FT_EDIT_CONFIRM_OPEN, IDH_CONFIRM_OPEN,
|
||
|
IDC_FT_EDIT_SHOWEXT, IDH_FCAB_FT_EDIT_SHOWEXT,
|
||
|
IDC_FT_EDIT_BROWSEINPLACE, IDH_SAME_WINDOW,
|
||
|
0, 0
|
||
|
};
|
||
|
|
||
|
struct LV_ADDDATA
|
||
|
{
|
||
|
BOOL fDefaultAction;
|
||
|
TCHAR szActionReg[MAX_ACTION];
|
||
|
};
|
||
|
|
||
|
#define ADDDATA_ACTIONREG(plvItem) (((LV_ADDDATA*)((plvItem)->lParam))->szActionReg)
|
||
|
#define ADDDATA_DEFAULTACTION(plvItem) (((LV_ADDDATA*)((plvItem)->lParam))->fDefaultAction)
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
CFTAdvDlg::CFTAdvDlg(LPTSTR pszProgID, LPTSTR pszExt) :
|
||
|
CFTDlg((ULONG_PTR)cs_rgdwHelpIDsArray),
|
||
|
_iDefaultAction(-1), _iLVSel(-1)
|
||
|
{
|
||
|
_szProgID[0] = NULL;
|
||
|
if (pszProgID)
|
||
|
StrCpyN(_szProgID, pszProgID, ARRAYSIZE(_szProgID));
|
||
|
|
||
|
_szExt[0] = NULL;
|
||
|
if (pszExt && (*pszExt != NULL))
|
||
|
{
|
||
|
wnsprintf(_szExt, ARRAYSIZE(_szExt), TEXT(".%s"), pszExt);
|
||
|
}
|
||
|
|
||
|
_hdpaActions = DPA_Create(4);
|
||
|
_hdpaRemovedActions = DPA_Create(1);
|
||
|
}
|
||
|
|
||
|
static int _DeleteLocalAllocCB(void *pItem, void *pData)
|
||
|
{
|
||
|
LocalFree((HLOCAL)pItem);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
CFTAdvDlg::~CFTAdvDlg()
|
||
|
{
|
||
|
if (_hIcon)
|
||
|
DeleteObject(_hIcon);
|
||
|
|
||
|
if (_hfontReg)
|
||
|
DeleteObject(_hfontReg);
|
||
|
|
||
|
if (_hfontBold)
|
||
|
DeleteObject(_hfontBold);
|
||
|
|
||
|
if (_hdpaActions)
|
||
|
DPA_DestroyCallback(_hdpaActions, _DeleteLocalAllocCB, NULL);
|
||
|
|
||
|
if (_hdpaRemovedActions)
|
||
|
DPA_DestroyCallback(_hdpaRemovedActions, _DeleteLocalAllocCB, NULL);
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Logic specific to our problem
|
||
|
LRESULT CFTAdvDlg::OnInitDialog(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
HRESULT hres = _InitAssocStore();
|
||
|
DECLAREWAITCURSOR;
|
||
|
|
||
|
SetWaitCursor();
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
_InitListView();
|
||
|
|
||
|
_InitDefaultActionFont();
|
||
|
|
||
|
// FTEdit_AreDefaultViewersInstalled ????
|
||
|
|
||
|
if (*_szProgID)
|
||
|
{
|
||
|
_SetDocIcon();
|
||
|
|
||
|
_InitDescription();
|
||
|
|
||
|
_FillListView();
|
||
|
|
||
|
_InitDefaultAction();
|
||
|
|
||
|
_SelectListViewItem(0);
|
||
|
|
||
|
_InitChangeIconButton();
|
||
|
|
||
|
_UpdateCheckBoxes();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
EndDialog(_hwnd, -1);
|
||
|
|
||
|
ResetWaitCursor();
|
||
|
|
||
|
// Return TRUE so that system set focus
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
int CFTAdvDlg::_GetIconIndex()
|
||
|
{
|
||
|
// check under the file progid
|
||
|
int iImageIndex = -1;
|
||
|
IAssocInfo* pAI = NULL;
|
||
|
HRESULT hr = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = pAI->GetDWORD(AIDWORD_DOCLARGEICON, (DWORD*)&iImageIndex);
|
||
|
pAI->Release();
|
||
|
}
|
||
|
return iImageIndex;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_SetDocIcon(int iIndex)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
if (-1 == iIndex)
|
||
|
{
|
||
|
iIndex = _GetIconIndex();
|
||
|
}
|
||
|
|
||
|
if (-1 != iIndex)
|
||
|
{
|
||
|
HIMAGELIST hIL = NULL;
|
||
|
|
||
|
Shell_GetImageLists(&hIL, NULL);
|
||
|
|
||
|
if (_hIcon)
|
||
|
{
|
||
|
DeleteObject(_hIcon);
|
||
|
_hIcon = NULL;
|
||
|
}
|
||
|
|
||
|
if (hIL)
|
||
|
{
|
||
|
_hIcon = ImageList_ExtractIcon(g_hinst, hIL, iIndex);
|
||
|
|
||
|
_hIcon = (HICON)CopyImage(_hIcon, IMAGE_ICON, 32, 32, LR_COPYDELETEORG);
|
||
|
|
||
|
HICON hiOld = (HICON)SendDlgItemMessage(_hwnd, IDC_FT_EDIT_DOCICON, STM_SETIMAGE, IMAGE_ICON,
|
||
|
(LPARAM)_hIcon);
|
||
|
|
||
|
if (hiOld)
|
||
|
DestroyIcon(hiOld);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnListViewSelItem(int iItem, LPARAM lParam)
|
||
|
{
|
||
|
_UpdateActionButtons();
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnMeasureItem(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
TEXTMETRIC tm = {0};
|
||
|
RECT rect;
|
||
|
LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam;
|
||
|
|
||
|
HDC hdc = GetDC(NULL);
|
||
|
HFONT hfontOld = (HFONT)SelectObject(hdc, _hfontBold);
|
||
|
|
||
|
GetTextMetrics(hdc, &tm);
|
||
|
|
||
|
GetClientRect(_GetLVHWND(), &rect);
|
||
|
|
||
|
lpmis->itemWidth = rect.right;
|
||
|
lpmis->itemHeight = tm.tmHeight;
|
||
|
|
||
|
SelectObject(hdc, hfontOld);
|
||
|
|
||
|
ReleaseDC(NULL, hdc);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnDrawItem(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
|
||
|
LRESULT lRet = FALSE;
|
||
|
|
||
|
if (ODT_LISTVIEW == lpDIS->CtlType)
|
||
|
{
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
LVITEM lvItem = {0};
|
||
|
HFONT hfontOld = NULL;
|
||
|
BOOL fSel = FALSE;
|
||
|
BOOL fListFocus = FALSE;
|
||
|
TCHAR szAction[MAX_ACTION];
|
||
|
COLORREF crBkgd = 0;
|
||
|
COLORREF crOldText = 0;
|
||
|
|
||
|
lvItem.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
|
||
|
lvItem.iItem = lpDIS->itemID;
|
||
|
lvItem.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
|
||
|
lvItem.pszText = szAction;
|
||
|
lvItem.cchTextMax = ARRAYSIZE(szAction);
|
||
|
|
||
|
ListView_GetItem(hwndLV, &lvItem);
|
||
|
|
||
|
fSel = (lvItem.state & LVIS_SELECTED);
|
||
|
fListFocus = (GetFocus() == hwndLV);
|
||
|
|
||
|
crBkgd = (fSel ? (fListFocus ? COLOR_HIGHLIGHT : COLOR_3DFACE) : COLOR_WINDOW);
|
||
|
|
||
|
SetBkColor(lpDIS->hDC, GetSysColor(crBkgd));
|
||
|
|
||
|
FillRect(lpDIS->hDC, &lpDIS->rcItem, (HBRUSH)IntToPtr(crBkgd + 1));
|
||
|
|
||
|
crOldText = SetTextColor(lpDIS->hDC,
|
||
|
GetSysColor(fSel ? (fListFocus ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT) :
|
||
|
COLOR_WINDOWTEXT));
|
||
|
|
||
|
// Use Bold font for default action
|
||
|
hfontOld = (HFONT)SelectObject(lpDIS->hDC,
|
||
|
_IsDefaultAction(ADDDATA_ACTIONREG(&lvItem)) ? _hfontBold : _hfontReg);
|
||
|
|
||
|
int iOldBkMode = SetBkMode(lpDIS->hDC, OPAQUE);
|
||
|
|
||
|
DrawText(lpDIS->hDC, szAction, lstrlen(szAction), &lpDIS->rcItem, 0);
|
||
|
|
||
|
SetBkMode(lpDIS->hDC, iOldBkMode);
|
||
|
|
||
|
SetTextColor(lpDIS->hDC, crOldText);
|
||
|
|
||
|
SelectObject(lpDIS->hDC, hfontOld);
|
||
|
|
||
|
if(fListFocus && (lvItem.state & LVIS_FOCUSED))
|
||
|
DrawFocusRect(lpDIS->hDC, &lpDIS->rcItem);
|
||
|
|
||
|
lRet = TRUE;
|
||
|
}
|
||
|
|
||
|
return lRet;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_InitDefaultActionFont()
|
||
|
{
|
||
|
HFONT hfontDlg = GetWindowFont(_hwnd);
|
||
|
LOGFONT lf = {0};
|
||
|
|
||
|
LOGFONT lfDlg = {0};
|
||
|
GetObject(hfontDlg, sizeof(LOGFONT), &lfDlg);
|
||
|
|
||
|
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
|
||
|
|
||
|
// Normal font
|
||
|
lf.lfWeight = FW_NORMAL;
|
||
|
lf.lfHeight = lfDlg.lfHeight;
|
||
|
_hfontReg = CreateFontIndirect(&lf);
|
||
|
|
||
|
// Bold font
|
||
|
lf.lfWeight = FW_BOLD;
|
||
|
_hfontBold = CreateFontIndirect(&lf);
|
||
|
|
||
|
return (_hfontReg && _hfontBold) ? S_OK : E_FAIL;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_SelectListViewItem(int i)
|
||
|
{
|
||
|
LVITEM lvItem = {0};
|
||
|
|
||
|
lvItem.iItem = i;
|
||
|
lvItem.mask = LVIF_STATE;
|
||
|
lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
|
||
|
lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
|
||
|
|
||
|
ListView_SetItem(_GetLVHWND(), &lvItem);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// pszText and cchTextMax needs to be set
|
||
|
BOOL CFTAdvDlg::_FindActionLVITEM(LPTSTR pszActionReg, LVITEM* plvItem)
|
||
|
{
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
int iCount = ListView_GetItemCount(hwndLV);
|
||
|
BOOL fRet = FALSE;
|
||
|
|
||
|
plvItem->mask = LVIF_TEXT | LVIF_PARAM;
|
||
|
|
||
|
for (int i = 0; i < iCount; ++i)
|
||
|
{
|
||
|
plvItem->iItem = i;
|
||
|
|
||
|
if (ListView_GetItem(hwndLV, plvItem))
|
||
|
{
|
||
|
if (!lstrcmpi(pszActionReg, ADDDATA_ACTIONREG(plvItem)))
|
||
|
{
|
||
|
fRet = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_InitDefaultAction()
|
||
|
{
|
||
|
// Get it from the classstore
|
||
|
IAssocInfo* pAI = NULL;
|
||
|
HRESULT hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
TCHAR szActionReg[MAX_ACTION];
|
||
|
DWORD cchActionReg = ARRAYSIZE(szActionReg);
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
int iIndex = -1;
|
||
|
|
||
|
hres = pAI->GetString(AISTR_PROGIDDEFAULTACTION, szActionReg, &cchActionReg);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
TCHAR szActionLVI[MAX_ACTION];
|
||
|
LVITEM lvItem = {0};
|
||
|
|
||
|
lvItem.pszText = szActionLVI;
|
||
|
lvItem.cchTextMax = ARRAYSIZE(szActionLVI);
|
||
|
|
||
|
if (_FindActionLVITEM(szActionReg, &lvItem))
|
||
|
hres = _SetDefaultAction(lvItem.iItem);
|
||
|
else
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
|
||
|
pAI->Release();
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
BOOL CFTAdvDlg::_GetDefaultAction(LPTSTR pszActionReg, DWORD cchActionReg)
|
||
|
{
|
||
|
BOOL fRet = FALSE;
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
LVITEM lvItem = {0};
|
||
|
int iCount = ListView_GetItemCount(hwndLV);
|
||
|
TCHAR szActionRegLocal[MAX_ACTION];
|
||
|
|
||
|
lvItem.mask = LVIF_TEXT | LVIF_PARAM;
|
||
|
lvItem.pszText = szActionRegLocal;
|
||
|
lvItem.cchTextMax = ARRAYSIZE(szActionRegLocal);
|
||
|
|
||
|
for (int i = 0; i < iCount; ++i)
|
||
|
{
|
||
|
lvItem.iItem = i;
|
||
|
|
||
|
if (ListView_GetItem(hwndLV, &lvItem))
|
||
|
{
|
||
|
if (ADDDATA_DEFAULTACTION(&lvItem))
|
||
|
{
|
||
|
StrCpyN(pszActionReg, ADDDATA_ACTIONREG(&lvItem), cchActionReg);
|
||
|
fRet = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
BOOL CFTAdvDlg::_IsDefaultAction(LPTSTR pszActionReg)
|
||
|
{
|
||
|
BOOL fRet = FALSE;
|
||
|
TCHAR szActionReg[MAX_ACTION];
|
||
|
|
||
|
if (_GetDefaultAction(szActionReg, ARRAYSIZE(szActionReg)))
|
||
|
{
|
||
|
if (!lstrcmpi(szActionReg, pszActionReg))
|
||
|
fRet = TRUE;
|
||
|
}
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
void CFTAdvDlg::_CheckDefaultAction()
|
||
|
{
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
// Is there only one elem?
|
||
|
if (1 == ListView_GetItemCount(hwndLV))
|
||
|
{
|
||
|
_SetDefaultActionHelper(0, TRUE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_SetDefaultAction(int iIndex)
|
||
|
{
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
// Remove previous default if any
|
||
|
|
||
|
if (-1 != _iDefaultAction)
|
||
|
{
|
||
|
_SetDefaultActionHelper(_iDefaultAction, FALSE);
|
||
|
|
||
|
ListView_RedrawItems(hwndLV, _iDefaultAction, _iDefaultAction);
|
||
|
}
|
||
|
|
||
|
// Set new
|
||
|
_iDefaultAction = iIndex;
|
||
|
|
||
|
// iIndex == -1 means no default
|
||
|
if (iIndex >= 0)
|
||
|
{
|
||
|
_SetDefaultActionHelper(_iDefaultAction, TRUE);
|
||
|
|
||
|
ListView_RedrawItems(hwndLV, _iDefaultAction, _iDefaultAction);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
void CFTAdvDlg::_SetDefaultActionHelper(int iIndex, BOOL fDefault)
|
||
|
{
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
LVITEM lvItem = {0};
|
||
|
lvItem.mask = LVIF_PARAM;
|
||
|
lvItem.iItem = iIndex;
|
||
|
|
||
|
_iDefaultAction = -1;
|
||
|
|
||
|
if (ListView_GetItem(hwndLV, &lvItem))
|
||
|
{
|
||
|
ADDDATA_DEFAULTACTION(&lvItem) = fDefault;
|
||
|
_iDefaultAction = iIndex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_InitListView()
|
||
|
{
|
||
|
LVCOLUMN lvColumn = {0};
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
RECT rc = {0};
|
||
|
|
||
|
{
|
||
|
// What's this?
|
||
|
// We need to handle the WM_MEASUREITEM message from the listview. This msg
|
||
|
// is sent before we receive the WM_INITDIALOG and thus before we connect the
|
||
|
// this C++ obj to the HWND. By changing the style here we receive the msg
|
||
|
// after the C++ obj and the HWND are connected.
|
||
|
LONG lStyle = GetWindowLong(hwndLV, GWL_STYLE);
|
||
|
|
||
|
lStyle &= ~LVS_LIST;
|
||
|
|
||
|
SetWindowLong(hwndLV, GWL_STYLE, lStyle | LVS_REPORT);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set the columns
|
||
|
//
|
||
|
GetClientRect(hwndLV, &rc);
|
||
|
|
||
|
lvColumn.mask = LVCF_SUBITEM|LVCF_WIDTH;
|
||
|
lvColumn.cx = rc.right - GetSystemMetrics(SM_CXBORDER);
|
||
|
lvColumn.iSubItem = 0;
|
||
|
|
||
|
ListView_InsertColumn(hwndLV, 0, &lvColumn);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_UpdateActionButtons()
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
TCHAR szAction[MAX_ACTION];
|
||
|
BOOL bRet = FALSE;
|
||
|
|
||
|
LVITEM lvItem = {0};
|
||
|
lvItem.pszText = szAction;
|
||
|
lvItem.cchTextMax = ARRAYSIZE(szAction);
|
||
|
|
||
|
bRet = _GetListViewSelectedItem(LVIF_TEXT | LVIF_PARAM, 0, &lvItem);
|
||
|
|
||
|
// If we don't have a selected item Or we don't have any text for that item.
|
||
|
if (!bRet || !(*(lvItem.pszText)))
|
||
|
{
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_EDIT), FALSE);
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_REMOVE), FALSE);
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_DEFAULT), TRUE);
|
||
|
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (_IsNewPROGIDACTION(lvItem.pszText))
|
||
|
{
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_EDIT), TRUE);
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_REMOVE), TRUE);
|
||
|
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
IAssocInfo* pAI = NULL;
|
||
|
|
||
|
hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
DWORD dwAttributes;
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
|
||
|
// REARCHITECT: This code should be in ftassoc.cpp, and we should have
|
||
|
// more AIBOOL_ flags for this
|
||
|
hres = pAI->GetDWORD(AIDWORD_PROGIDEDITFLAGS, &dwAttributes);
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
{
|
||
|
// It failed, probably there is no EditFlags value for this progID, let's
|
||
|
// set some default value for dwAttributes
|
||
|
dwAttributes = 0;
|
||
|
}
|
||
|
// REARCHITECT (end)
|
||
|
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_EDIT),
|
||
|
!((dwAttributes & FTA_NoEditVerb) &&
|
||
|
!(dwAttributes & FTAV_UserDefVerb)));
|
||
|
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_REMOVE),
|
||
|
!((dwAttributes & FTA_NoRemoveVerb) &&
|
||
|
!(dwAttributes & FTAV_UserDefVerb)));
|
||
|
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_DEFAULT),
|
||
|
!(dwAttributes & FTA_NoEditDflt));
|
||
|
|
||
|
// Enable the default button only if the action is not already
|
||
|
// the default action
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_DEFAULT),
|
||
|
!_IsDefaultAction(ADDDATA_ACTIONREG(&lvItem)));
|
||
|
|
||
|
pAI->Release();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_UpdateCheckBoxes()
|
||
|
{
|
||
|
BOOL fBool;
|
||
|
|
||
|
IAssocInfo* pAI = NULL;
|
||
|
|
||
|
HRESULT hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
hres = pAI->GetBOOL(AIBOOL_CONFIRMOPEN, &fBool);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
CheckDlgButton(_hwnd, IDC_FT_EDIT_CONFIRM_OPEN, !fBool);
|
||
|
|
||
|
hres = pAI->GetBOOL(AIBOOL_ALWAYSSHOWEXT, &fBool);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
CheckDlgButton(_hwnd, IDC_FT_EDIT_SHOWEXT, fBool);
|
||
|
|
||
|
hres = pAI->GetBOOL(AIBOOL_BROWSEINPLACEENABLED, &fBool);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_BROWSEINPLACE), fBool);
|
||
|
|
||
|
if (fBool)
|
||
|
{
|
||
|
hres = pAI->GetBOOL(AIBOOL_BROWSEINPLACE, &fBool);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
CheckDlgButton(_hwnd, IDC_FT_EDIT_BROWSEINPLACE, fBool);
|
||
|
}
|
||
|
else
|
||
|
CheckDlgButton(_hwnd, IDC_FT_EDIT_BROWSEINPLACE, FALSE);
|
||
|
}
|
||
|
pAI->Release();
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_InitChangeIconButton()
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
BOOL fChangeIcon = TRUE;
|
||
|
|
||
|
IAssocInfo* pAI = NULL;
|
||
|
|
||
|
hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
hres = pAI->GetBOOL(AIBOOL_EDITDOCICON, &fChangeIcon);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_CHANGEICON), fChangeIcon);
|
||
|
|
||
|
pAI->Release();
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_InitDescription()
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
BOOL fEditDescr = TRUE;
|
||
|
|
||
|
IAssocInfo* pAI = NULL;
|
||
|
|
||
|
hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
TCHAR szProgIDDescr[MAX_PROGIDDESCR];
|
||
|
DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr);
|
||
|
|
||
|
hres = pAI->GetString(AISTR_PROGIDDESCR, szProgIDDescr, &cchProgIDDescr);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
SetDlgItemText(_hwnd, IDC_FT_EDIT_DESC, szProgIDDescr);
|
||
|
|
||
|
hres = pAI->GetBOOL(AIBOOL_EDITDESCR, &fEditDescr);
|
||
|
|
||
|
EnableWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_DESC), fEditDescr);
|
||
|
|
||
|
pAI->Release();
|
||
|
|
||
|
Edit_LimitText(GetDlgItem(_hwnd, IDC_FT_EDIT_DESC), MAX_PROGIDDESCR - 1);
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_FillListView()
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
IEnumAssocInfo* pEnum = NULL;
|
||
|
|
||
|
hres = _pAssocStore->EnumAssocInfo(ASENUM_ACTION, _szProgID, AIINIT_PROGID, &pEnum);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
int iItem = 0;
|
||
|
IAssocInfo* pAI = NULL;
|
||
|
|
||
|
while (S_OK == pEnum->Next(&pAI))
|
||
|
{
|
||
|
TCHAR szActionReg[MAX_ACTION];
|
||
|
DWORD cchActionReg = ARRAYSIZE(szActionReg);
|
||
|
|
||
|
hres = pAI->GetString(AISTR_ACTION, szActionReg, &cchActionReg);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
TCHAR szActionFN[MAX_ACTION];
|
||
|
DWORD cchActionFN = ARRAYSIZE(szActionFN);
|
||
|
|
||
|
hres = pAI->GetString(AISTR_ACTIONFRIENDLY, szActionFN, &cchActionFN);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
if (S_FALSE == hres)
|
||
|
{
|
||
|
lstrcpy(szActionFN, szActionReg);
|
||
|
}
|
||
|
|
||
|
if (-1 != _InsertListViewItem(iItem, szActionReg, szActionFN))
|
||
|
{
|
||
|
++iItem;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pAI->Release();
|
||
|
}
|
||
|
|
||
|
pEnum->Release();
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnChangeIcon(WORD wNotif)
|
||
|
{
|
||
|
IAssocInfo* pAI;
|
||
|
HRESULT hr = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
DWORD cchIconLoc = ARRAYSIZE(_szOldIconLoc);
|
||
|
hr = pAI->GetString(AISTR_ICONLOCATION, _szOldIconLoc, &cchIconLoc);
|
||
|
pAI->Release();
|
||
|
|
||
|
_iOldIcon = PathParseIconLocation(_szOldIconLoc);
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
StrCpyN(_szOldIconLoc, TEXT("shell32.dll"), ARRAYSIZE(_szOldIconLoc));
|
||
|
_iOldIcon = -(IDI_SYSFILE);
|
||
|
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
// setup the in params
|
||
|
int iIcon = _iOldIcon;
|
||
|
StrCpyN(_szIconLoc, _szOldIconLoc, ARRAYSIZE(_szIconLoc));
|
||
|
|
||
|
if (PickIconDlg(_hwnd, _szIconLoc, ARRAYSIZE(_szIconLoc), &iIcon))
|
||
|
{
|
||
|
_SetDocIcon(Shell_GetCachedImageIndex(_szIconLoc, iIcon, 0));
|
||
|
|
||
|
// Format the _szIconLoc
|
||
|
int iLen = lstrlen(_szIconLoc);
|
||
|
|
||
|
wnsprintf(_szIconLoc + iLen, ARRAYSIZE(_szIconLoc) - iLen, TEXT(",%d"), iIcon);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_szIconLoc[0] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Return value:
|
||
|
// TRUE: Check succeeded, everything is OK
|
||
|
// FALSE: Check failed
|
||
|
BOOL CFTAdvDlg::_CheckForDuplicateNewAction(LPTSTR pszActionReg, LPTSTR pszActionFN)
|
||
|
{
|
||
|
// we just go through the listview content
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
int cItem = ListView_GetItemCount(hwndLV);
|
||
|
BOOL fRet = TRUE;
|
||
|
|
||
|
for (int i = 0; (i < cItem) && fRet; ++i)
|
||
|
{
|
||
|
TCHAR szActionFN[MAX_ACTION];
|
||
|
LVITEM lvItem = {0};
|
||
|
|
||
|
lvItem.mask = LVIF_PARAM | LVIF_TEXT;
|
||
|
lvItem.iItem = i;
|
||
|
lvItem.pszText = szActionFN;
|
||
|
lvItem.cchTextMax = ARRAYSIZE(szActionFN);
|
||
|
|
||
|
ListView_GetItem(hwndLV, &lvItem);
|
||
|
|
||
|
if (!lstrcmpi(lvItem.pszText, pszActionFN))
|
||
|
{
|
||
|
fRet = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!lstrcmpi(ADDDATA_ACTIONREG(&lvItem), pszActionReg))
|
||
|
{
|
||
|
fRet = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
// Return value:
|
||
|
// TRUE: Check succeeded, everything is OK
|
||
|
// FALSE: Check failed
|
||
|
BOOL CFTAdvDlg::_CheckForDuplicateEditAction(LPTSTR pszActionRegOriginal, LPTSTR pszActionReg,
|
||
|
LPTSTR pszActionFNOriginal, LPTSTR pszActionFN)
|
||
|
{
|
||
|
// we just go through the listview content
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
int cItem = ListView_GetItemCount(hwndLV);
|
||
|
BOOL fRet = TRUE;
|
||
|
|
||
|
for (int i = 0; (i < cItem) && fRet; ++i)
|
||
|
{
|
||
|
TCHAR szActionFN[MAX_ACTION];
|
||
|
LVITEM lvItem = {0};
|
||
|
|
||
|
lvItem.mask = LVIF_PARAM | LVIF_TEXT;
|
||
|
lvItem.iItem = i;
|
||
|
lvItem.pszText = szActionFN;
|
||
|
lvItem.cchTextMax = ARRAYSIZE(szActionFN);
|
||
|
|
||
|
ListView_GetItem(hwndLV, &lvItem);
|
||
|
|
||
|
if (!lstrcmpi(lvItem.pszText, pszActionFN))
|
||
|
{
|
||
|
// they are the same, this can happen if this is the Action we were editing
|
||
|
// and we did not change the action name
|
||
|
|
||
|
// Is this the original one we were editing?
|
||
|
if (lstrcmpi(szActionFN, pszActionFNOriginal))
|
||
|
{
|
||
|
// No, it's not the original, we have a dup
|
||
|
fRet = FALSE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!lstrcmpi(ADDDATA_ACTIONREG(&lvItem), pszActionReg))
|
||
|
{
|
||
|
// they are the same, this can happen if this is the Action we were editing
|
||
|
// and we did not change the action name
|
||
|
|
||
|
// Is this the original one we were editing?
|
||
|
if (lstrcmpi(ADDDATA_ACTIONREG(&lvItem), pszActionRegOriginal))
|
||
|
{
|
||
|
// No, it's not the original, we have a dup
|
||
|
fRet = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnNewButton(WORD wNotif)
|
||
|
{
|
||
|
TCHAR szProgIDDescr[MAX_PROGIDDESCR];
|
||
|
PROGIDACTION pida = {0};
|
||
|
CFTActionDlg* pActionDlg = NULL;
|
||
|
|
||
|
pida.fNew = TRUE;
|
||
|
|
||
|
GetDlgItemText(_hwnd, IDC_FT_EDIT_DESC, szProgIDDescr, ARRAYSIZE(szProgIDDescr));
|
||
|
|
||
|
// FALSE: New (not-Edit)
|
||
|
pActionDlg = new CFTActionDlg(&pida, szProgIDDescr, FALSE);
|
||
|
|
||
|
if (pActionDlg)
|
||
|
{
|
||
|
BOOL fShowAgain;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
fShowAgain = FALSE;
|
||
|
|
||
|
if (IDOK == pActionDlg->DoModal(g_hinst, MAKEINTRESOURCE(DLG_FILETYPEOPTIONSCMD), _hwnd))
|
||
|
{
|
||
|
// Do we have duplicate actions?
|
||
|
if (_CheckForDuplicateNewAction(pida.szActionReg, pida.szAction))
|
||
|
{
|
||
|
// No
|
||
|
HRESULT hres = _AppendPROGIDACTION(&pida);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
int iItem = _InsertListViewItem(0, pida.szActionReg, pida.szAction);
|
||
|
|
||
|
hres = S_OK;
|
||
|
|
||
|
if (-1 != iItem)
|
||
|
_SelectListViewItem(iItem);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Yes
|
||
|
fShowAgain = TRUE;
|
||
|
|
||
|
pActionDlg->SetShowAgain();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fShowAgain)
|
||
|
{
|
||
|
ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_FT_MB_EXISTINGACTION),
|
||
|
MAKEINTRESOURCE(IDS_FT), MB_OK | MB_ICONSTOP, pida.szAction);
|
||
|
}
|
||
|
|
||
|
} while (fShowAgain);
|
||
|
|
||
|
pActionDlg->Release();
|
||
|
}
|
||
|
|
||
|
_CheckDefaultAction();
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnEditButton(WORD wNotif)
|
||
|
{
|
||
|
TCHAR szAction[MAX_ACTION];
|
||
|
HRESULT hres = E_FAIL;
|
||
|
LONG lRes = 0;
|
||
|
|
||
|
LVITEM lvItem = {0};
|
||
|
// lvItem.iSubItem = 0;
|
||
|
lvItem.pszText = szAction;
|
||
|
lvItem.cchTextMax = ARRAYSIZE(szAction);
|
||
|
|
||
|
if (_GetListViewSelectedItem(LVIF_TEXT, 0, &lvItem))
|
||
|
{
|
||
|
TCHAR szProgIDDescr[MAX_PROGIDDESCR];
|
||
|
PROGIDACTION* pPIDA = NULL;
|
||
|
PROGIDACTION pida = {0};
|
||
|
|
||
|
GetDlgItemText(_hwnd, IDC_FT_EDIT_DESC, szProgIDDescr, ARRAYSIZE(szProgIDDescr));
|
||
|
|
||
|
BOOL fNewOrEdit = SUCCEEDED(_GetPROGIDACTION(lvItem.pszText, &pPIDA));
|
||
|
|
||
|
if (!fNewOrEdit)
|
||
|
{
|
||
|
hres = _FillPROGIDACTION(&pida, ADDDATA_ACTIONREG(&lvItem), szAction);
|
||
|
|
||
|
pPIDA = &pida;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
// TRUE: Edit
|
||
|
CFTActionDlg* pActionDlg = new CFTActionDlg(pPIDA, szProgIDDescr, TRUE);
|
||
|
|
||
|
if (pActionDlg)
|
||
|
{
|
||
|
BOOL fShowAgain;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
fShowAgain = FALSE;
|
||
|
|
||
|
if (IDOK == pActionDlg->DoModal(g_hinst, MAKEINTRESOURCE(DLG_FILETYPEOPTIONSCMD), _hwnd))
|
||
|
{
|
||
|
// Do we have duplicate actions?
|
||
|
if (_CheckForDuplicateEditAction(ADDDATA_ACTIONREG(&lvItem), pPIDA->szActionReg,
|
||
|
lvItem.pszText, pPIDA->szAction))
|
||
|
{
|
||
|
// No
|
||
|
if (!fNewOrEdit)
|
||
|
{
|
||
|
hres = _AppendPROGIDACTION(pPIDA);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
// Replace the current item text
|
||
|
StrCpyN(lvItem.pszText, pPIDA->szAction, ARRAYSIZE(pPIDA->szAction));
|
||
|
|
||
|
ListView_SetItem(_GetLVHWND(), &lvItem);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Yes
|
||
|
fShowAgain = TRUE;
|
||
|
|
||
|
pActionDlg->SetShowAgain();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fShowAgain)
|
||
|
{
|
||
|
ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_FT_MB_EXISTINGACTION),
|
||
|
MAKEINTRESOURCE(IDS_FT), MB_OK | MB_ICONSTOP, pPIDA->szAction);
|
||
|
}
|
||
|
|
||
|
} while (fShowAgain);
|
||
|
|
||
|
pActionDlg->Release();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnSetDefault(WORD wNotif)
|
||
|
{
|
||
|
BOOL bRet;
|
||
|
LVITEM lvItem = {0};
|
||
|
// lvItem.iSubItem = 0;
|
||
|
|
||
|
bRet = _GetListViewSelectedItem(0, 0, &lvItem);
|
||
|
|
||
|
if (bRet)
|
||
|
_SetDefaultAction(lvItem.iItem);
|
||
|
else
|
||
|
_SetDefaultAction(-1);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnRemoveButton(WORD wNotif)
|
||
|
{
|
||
|
TCHAR szExt[MAX_EXT];
|
||
|
HRESULT hres = E_FAIL;
|
||
|
LONG lRes = 0;
|
||
|
|
||
|
LVITEM lvItem = {0};
|
||
|
// lvItem.iSubItem = 0;
|
||
|
lvItem.pszText = szExt;
|
||
|
lvItem.cchTextMax = ARRAYSIZE(szExt);
|
||
|
|
||
|
if (_GetListViewSelectedItem(LVIF_TEXT, 0, &lvItem))
|
||
|
{
|
||
|
if (IDYES == ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_FT_MB_REMOVEACTION),
|
||
|
MAKEINTRESOURCE(IDS_FT), MB_YESNO | MB_ICONQUESTION))
|
||
|
{
|
||
|
//
|
||
|
// First take care of data side
|
||
|
//
|
||
|
|
||
|
// Yes. Is this a new Action?
|
||
|
PROGIDACTION* pPIDA = NULL;
|
||
|
if (SUCCEEDED(_GetPROGIDACTION(lvItem.pszText, &pPIDA)) && pPIDA->fNew)
|
||
|
{
|
||
|
// Yes, we'll just remove it from the DPA
|
||
|
hres = _RemovePROGIDACTION(pPIDA);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No, add its name to the list to delete if user press OK
|
||
|
DWORD cchSize = ARRAYSIZE(ADDDATA_ACTIONREG(&lvItem));
|
||
|
|
||
|
LPTSTR pszActionToRemove = (LPTSTR)LocalAlloc(LPTR,
|
||
|
cchSize * sizeof(TCHAR));
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
|
||
|
if (pszActionToRemove)
|
||
|
{
|
||
|
StrCpyN(pszActionToRemove, ADDDATA_ACTIONREG(&lvItem), cchSize);
|
||
|
|
||
|
if (-1 != DPA_AppendPtr(_hdpaRemovedActions, pszActionToRemove))
|
||
|
hres = S_OK;
|
||
|
else
|
||
|
LocalFree((HLOCAL)pszActionToRemove);
|
||
|
}
|
||
|
|
||
|
if (E_OUTOFMEMORY == hres)
|
||
|
{
|
||
|
//Out of memory
|
||
|
ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_ERROR +
|
||
|
ERROR_NOT_ENOUGH_MEMORY), MAKEINTRESOURCE(IDS_FT),
|
||
|
MB_OK | MB_ICONSTOP);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Then update UI, I/A
|
||
|
//
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
int iCount = ListView_GetItemCount(hwndLV);
|
||
|
int iNextSel = -1;
|
||
|
|
||
|
ListView_DeleteItem(hwndLV, lvItem.iItem);
|
||
|
|
||
|
if (iCount > lvItem.iItem)
|
||
|
iNextSel = lvItem.iItem;
|
||
|
else
|
||
|
if (lvItem.iItem > 0)
|
||
|
iNextSel = lvItem.iItem - 1;
|
||
|
|
||
|
if (-1 != iNextSel)
|
||
|
_SelectListViewItem(iNextSel);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hres = S_FALSE;
|
||
|
}
|
||
|
|
||
|
_CheckDefaultAction();
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnOK(WORD wNotif)
|
||
|
{
|
||
|
BOOL fChecksPassed = FALSE;
|
||
|
|
||
|
// Yes, we need to:
|
||
|
// - remove "removed" items, modify "edited" ones,
|
||
|
// and add "New" ones
|
||
|
// - update checkboxes related stuff
|
||
|
// - set the default action
|
||
|
// - set the icon
|
||
|
// - set the description
|
||
|
{
|
||
|
int n = DPA_GetPtrCount(_hdpaRemovedActions);
|
||
|
|
||
|
if (n)
|
||
|
{
|
||
|
IAssocInfo* pAI;
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
for (int i = 0; i < n; ++i)
|
||
|
{
|
||
|
LPTSTR pszActionToRemove = (LPTSTR)DPA_GetPtr(_hdpaRemovedActions, i);
|
||
|
|
||
|
if (pszActionToRemove && *pszActionToRemove)
|
||
|
{
|
||
|
hres = _pAssocStore->GetComplexAssocInfo(_szProgID, AIINIT_PROGID,
|
||
|
pszActionToRemove, AIINIT_ACTION, &pAI);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
pAI->Delete(AIALL_NONE);
|
||
|
pAI->Release();
|
||
|
}
|
||
|
|
||
|
LocalFree((HLOCAL)pszActionToRemove);
|
||
|
DPA_DeletePtr(_hdpaRemovedActions, i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
{
|
||
|
int n = DPA_GetPtrCount(_hdpaActions);
|
||
|
|
||
|
if (n)
|
||
|
{
|
||
|
IAssocInfo* pAI = NULL;
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
for (int i = n - 1; i >= 0; --i)
|
||
|
{
|
||
|
PROGIDACTION* pPIDAFromList = (PROGIDACTION*)DPA_GetPtr(_hdpaActions, i);
|
||
|
|
||
|
if (pPIDAFromList)
|
||
|
{
|
||
|
// Is it an Edited one?
|
||
|
if (!pPIDAFromList->fNew)
|
||
|
{
|
||
|
// Yes, remove the old one first
|
||
|
hres = _pAssocStore->GetComplexAssocInfo(_szProgID, AIINIT_PROGID,
|
||
|
pPIDAFromList->szOldActionReg, AIINIT_ACTION, &pAI);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
pAI->Delete(AIALL_NONE);
|
||
|
pAI->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add new data
|
||
|
hres = _pAssocStore->GetComplexAssocInfo(_szProgID, AIINIT_PROGID,
|
||
|
pPIDAFromList->szActionReg, AIINIT_ACTION, &pAI);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
hres = pAI->SetData(AIDATA_PROGIDACTION, (PBYTE)pPIDAFromList,
|
||
|
sizeof(*pPIDAFromList));
|
||
|
|
||
|
pAI->Release();
|
||
|
}
|
||
|
|
||
|
// Clean up DPA
|
||
|
_DeletePROGIDACTION(pPIDAFromList);
|
||
|
|
||
|
DPA_DeletePtr(_hdpaActions, i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
{
|
||
|
IAssocInfo* pAI = NULL;
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
LVFINDINFO lvFindInfo = {0};
|
||
|
int iIndex = -1;
|
||
|
HRESULT hres = _pAssocStore->GetAssocInfo(_szProgID, AIINIT_PROGID, &pAI);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
TCHAR szActionReg[MAX_ACTION];
|
||
|
|
||
|
hres = pAI->SetBOOL(AIBOOL_CONFIRMOPEN,
|
||
|
!IsDlgButtonChecked(_hwnd, IDC_FT_EDIT_CONFIRM_OPEN));
|
||
|
|
||
|
hres = pAI->SetBOOL(AIBOOL_ALWAYSSHOWEXT,
|
||
|
IsDlgButtonChecked(_hwnd, IDC_FT_EDIT_SHOWEXT));
|
||
|
|
||
|
hres = pAI->SetBOOL(AIBOOL_BROWSEINPLACE,
|
||
|
IsDlgButtonChecked(_hwnd, IDC_FT_EDIT_BROWSEINPLACE));
|
||
|
|
||
|
// Set the default action, if any
|
||
|
if (_GetDefaultAction(szActionReg, ARRAYSIZE(szActionReg)))
|
||
|
{
|
||
|
hres = pAI->SetString(AISTR_PROGIDDEFAULTACTION, szActionReg);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hres = pAI->SetString(AISTR_PROGIDDEFAULTACTION, TEXT(""));
|
||
|
}
|
||
|
|
||
|
// Set the icon, if changed
|
||
|
if (_szIconLoc[0])
|
||
|
{
|
||
|
// Set it in the registry
|
||
|
hres = pAI->SetString(AISTR_ICONLOCATION, _szIconLoc);
|
||
|
if (_szOldIconLoc[0])
|
||
|
{
|
||
|
int iIconIndex = Shell_GetCachedImageIndex(_szOldIconLoc, _iOldIcon, 0);
|
||
|
|
||
|
SHUpdateImage(_szOldIconLoc, _iOldIcon, 0, iIconIndex);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Set the description
|
||
|
{
|
||
|
TCHAR szProgIDDescr[MAX_PROGIDDESCR];
|
||
|
|
||
|
GetDlgItemText(_hwnd, IDC_FT_EDIT_DESC, szProgIDDescr,
|
||
|
ARRAYSIZE(szProgIDDescr));
|
||
|
|
||
|
hres = pAI->SetString(AISTR_PROGIDDESCR, szProgIDDescr);
|
||
|
}
|
||
|
|
||
|
pAI->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
EndDialog(_hwnd, IDOK);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnNotifyListView(UINT uCode, LPNMHDR pNMHDR)
|
||
|
{
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
LRESULT lres = FALSE;
|
||
|
|
||
|
switch(uCode)
|
||
|
{
|
||
|
case NM_DBLCLK:
|
||
|
if (IsWindowEnabled(GetDlgItem(_hwnd, IDC_FT_EDIT_EDIT)))
|
||
|
PostMessage(_hwnd, WM_COMMAND, (WPARAM)IDC_FT_EDIT_EDIT, 0);
|
||
|
|
||
|
break;
|
||
|
//review: do I really need to do this?
|
||
|
case NM_SETFOCUS:
|
||
|
case NM_KILLFOCUS:
|
||
|
// update list view
|
||
|
ListView_RedrawItems(hwndLV, 0, ListView_GetItemCount(hwndLV));
|
||
|
UpdateWindow(hwndLV);
|
||
|
break;
|
||
|
|
||
|
case LVN_DELETEITEM:
|
||
|
{
|
||
|
NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;
|
||
|
|
||
|
if (pNMLV->lParam)
|
||
|
{
|
||
|
LocalFree((HLOCAL)(pNMLV->lParam));
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case LVN_ITEMCHANGED:
|
||
|
{
|
||
|
NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;
|
||
|
|
||
|
// Is a new item being selected/unselected?
|
||
|
if (pNMLV->uChanged & LVIF_STATE)
|
||
|
{
|
||
|
// Yes
|
||
|
OnListViewSelItem(pNMLV->iItem, NULL);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return lres;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnCancel(WORD wNotif)
|
||
|
{
|
||
|
EndDialog(_hwnd, IDCANCEL);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnDestroy(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
CFTDlg::OnDestroy(wParam, lParam);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL CFTAdvDlg::_GetListViewSelectedItem(UINT uMask, UINT uStateMask, LVITEM* plvItem)
|
||
|
{
|
||
|
BOOL fSel = FALSE;
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
|
||
|
plvItem->mask = uMask | LVIF_STATE | LVIF_PARAM;
|
||
|
plvItem->stateMask = uStateMask | LVIS_SELECTED;
|
||
|
|
||
|
// Do we have the selection cached?
|
||
|
if (-1 != _iLVSel)
|
||
|
{
|
||
|
// Yes, make sure it's valid
|
||
|
plvItem->iItem = _iLVSel;
|
||
|
|
||
|
ListView_GetItem(hwndLV, plvItem);
|
||
|
|
||
|
if (plvItem->state & LVIS_SELECTED)
|
||
|
fSel = TRUE;
|
||
|
}
|
||
|
|
||
|
// Cache was wrong
|
||
|
if (!fSel)
|
||
|
{
|
||
|
int iCount = ListView_GetItemCount(hwndLV);
|
||
|
|
||
|
for (int i=0; (i < iCount) && !fSel; ++i)
|
||
|
{
|
||
|
plvItem->iItem = i;
|
||
|
ListView_GetItem(hwndLV, plvItem);
|
||
|
|
||
|
if (plvItem->state & LVIS_SELECTED)
|
||
|
fSel = TRUE;
|
||
|
}
|
||
|
|
||
|
if (fSel)
|
||
|
_iLVSel = i;
|
||
|
}
|
||
|
|
||
|
return fSel;
|
||
|
}
|
||
|
|
||
|
int CFTAdvDlg::_InsertListViewItem(int iItem, LPTSTR pszActionReg, LPTSTR pszActionFN)
|
||
|
{
|
||
|
int iRet = -1;
|
||
|
HWND hwndLV = _GetLVHWND();
|
||
|
LVITEM lvItem = {0};
|
||
|
lvItem.mask = LVIF_TEXT | LVIF_PARAM;
|
||
|
|
||
|
// Extension
|
||
|
lvItem.iItem = iItem;
|
||
|
lvItem.pszText = pszActionFN;
|
||
|
lvItem.cchTextMax = lstrlen(pszActionFN);
|
||
|
|
||
|
LV_ADDDATA* plvadddata = (LV_ADDDATA*)LocalAlloc(LPTR, sizeof(LV_ADDDATA));
|
||
|
|
||
|
if (plvadddata)
|
||
|
{
|
||
|
lvItem.lParam = (LPARAM)plvadddata;
|
||
|
StrCpyN(ADDDATA_ACTIONREG(&lvItem), pszActionReg, ARRAYSIZE(ADDDATA_ACTIONREG(&lvItem)));
|
||
|
ADDDATA_DEFAULTACTION(&lvItem) = 0;
|
||
|
|
||
|
iRet = ListView_InsertItem(hwndLV, &lvItem);
|
||
|
}
|
||
|
|
||
|
return iRet;
|
||
|
}
|
||
|
|
||
|
HWND CFTAdvDlg::_GetLVHWND()
|
||
|
{
|
||
|
return GetDlgItem(_hwnd, IDC_FT_EDIT_LV_CMDS);
|
||
|
}
|
||
|
|
||
|
void CFTAdvDlg::_DeletePROGIDACTION(PROGIDACTION* pPIDA)
|
||
|
{
|
||
|
if (pPIDA)
|
||
|
LocalFree((HLOCAL)pPIDA);
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_RemovePROGIDACTION(PROGIDACTION* pPIDA)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
int n = DPA_GetPtrCount(_hdpaActions);
|
||
|
|
||
|
for (int i = 0; (i < n) && FAILED(hres); ++i)
|
||
|
{
|
||
|
PROGIDACTION* pPIDAFromList = (PROGIDACTION*)DPA_GetPtr(_hdpaActions, i);
|
||
|
|
||
|
if (pPIDAFromList == pPIDA)
|
||
|
{
|
||
|
_DeletePROGIDACTION(pPIDAFromList);
|
||
|
|
||
|
DPA_DeletePtr(_hdpaActions, i);
|
||
|
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_CreatePROGIDACTION(PROGIDACTION** ppPIDA)
|
||
|
{
|
||
|
HRESULT hres = E_OUTOFMEMORY;
|
||
|
|
||
|
*ppPIDA = (PROGIDACTION*)LocalAlloc(LPTR, sizeof(PROGIDACTION));
|
||
|
|
||
|
if (*ppPIDA)
|
||
|
hres = S_OK;
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_CopyPROGIDACTION(PROGIDACTION* pPIDADest, PROGIDACTION* pPIDASrc)
|
||
|
{
|
||
|
memcpy(pPIDADest, pPIDASrc, sizeof(PROGIDACTION));
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_GetPROGIDACTION(LPTSTR pszActionFN, PROGIDACTION** ppPIDA)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
*ppPIDA = NULL;
|
||
|
|
||
|
if (pszActionFN && *pszActionFN)
|
||
|
{
|
||
|
int n = DPA_GetPtrCount(_hdpaActions);
|
||
|
|
||
|
for (int i = 0; (i < n) && FAILED(hres); ++i)
|
||
|
{
|
||
|
*ppPIDA = (PROGIDACTION*)DPA_GetPtr(_hdpaActions, i);
|
||
|
|
||
|
if (!StrCmpN((*ppPIDA)->szAction, pszActionFN, ARRAYSIZE((*ppPIDA)->szAction)))
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FAILED(hres))
|
||
|
*ppPIDA = NULL;
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_AppendPROGIDACTION(PROGIDACTION* pPIDA)
|
||
|
{
|
||
|
PROGIDACTION* pPIDANew = NULL;
|
||
|
|
||
|
HRESULT hres = _CreatePROGIDACTION(&pPIDANew);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
_CopyPROGIDACTION(pPIDANew, pPIDA);
|
||
|
|
||
|
if (-1 != DPA_AppendPtr(_hdpaActions, pPIDANew))
|
||
|
{
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_DeletePROGIDACTION(pPIDANew);
|
||
|
|
||
|
hres = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (E_OUTOFMEMORY == hres)
|
||
|
{
|
||
|
//Out of memory
|
||
|
ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_ERROR +
|
||
|
ERROR_NOT_ENOUGH_MEMORY), MAKEINTRESOURCE(IDS_FT),
|
||
|
MB_OK | MB_ICONSTOP);
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
BOOL CFTAdvDlg::_IsNewPROGIDACTION(LPTSTR pszActionFN)
|
||
|
{
|
||
|
BOOL fRet = FALSE;
|
||
|
PROGIDACTION* pPIDA = NULL;
|
||
|
|
||
|
HRESULT hres = _GetPROGIDACTION(pszActionFN, &pPIDA);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
if (pPIDA->fNew)
|
||
|
fRet = TRUE;
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
HRESULT CFTAdvDlg::_FillPROGIDACTION(PROGIDACTION* pPIDA, LPTSTR pszActionReg,
|
||
|
LPTSTR pszActionFN)
|
||
|
{
|
||
|
PROGIDACTION* pPIDAList = NULL;
|
||
|
HRESULT hres = _GetPROGIDACTION(pszActionFN, &pPIDAList);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
_CopyPROGIDACTION(pPIDA, pPIDAList);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
IAssocInfo* pAI = NULL;
|
||
|
|
||
|
hres = _pAssocStore->GetComplexAssocInfo(_szProgID, AIINIT_PROGID,
|
||
|
pszActionReg, AIINIT_ACTION, &pAI);
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
DWORD cbPIDA = sizeof(*pPIDA);
|
||
|
|
||
|
hres = pAI->GetData(AIDATA_PROGIDACTION, (PBYTE)pPIDA, &cbPIDA);
|
||
|
|
||
|
pAI->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Windows boiler plate code
|
||
|
LRESULT CFTAdvDlg::OnCommand(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
LRESULT lRes = FALSE;
|
||
|
|
||
|
switch(GET_WM_COMMAND_ID(wParam, lParam))
|
||
|
{
|
||
|
case IDC_FT_EDIT_NEW:
|
||
|
lRes = OnNewButton(GET_WM_COMMAND_CMD(wParam, lParam));
|
||
|
break;
|
||
|
|
||
|
case IDC_FT_EDIT_REMOVE:
|
||
|
lRes = OnRemoveButton(GET_WM_COMMAND_CMD(wParam, lParam));
|
||
|
break;
|
||
|
|
||
|
case IDC_FT_EDIT_EDIT:
|
||
|
lRes = OnEditButton(GET_WM_COMMAND_CMD(wParam, lParam));
|
||
|
break;
|
||
|
|
||
|
case IDC_FT_EDIT_CHANGEICON:
|
||
|
lRes = OnChangeIcon(GET_WM_COMMAND_CMD(wParam, lParam));
|
||
|
break;
|
||
|
|
||
|
case IDC_FT_EDIT_DEFAULT:
|
||
|
lRes = OnSetDefault(GET_WM_COMMAND_CMD(wParam, lParam));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
lRes = CFTDlg::OnCommand(wParam, lParam);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return lRes;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::OnNotify(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
LRESULT lRes = FALSE;
|
||
|
|
||
|
LPNMHDR pNMHDR = (LPNMHDR)lParam;
|
||
|
UINT_PTR idFrom = pNMHDR->idFrom;
|
||
|
UINT uCode = pNMHDR->code;
|
||
|
|
||
|
//GET_WM_COMMAND_CMD
|
||
|
switch(idFrom)
|
||
|
{
|
||
|
case IDC_FT_EDIT_LV_CMDS:
|
||
|
OnNotifyListView(uCode, pNMHDR);
|
||
|
lRes = CFTDlg::OnNotify(wParam, lParam);
|
||
|
break;
|
||
|
default:
|
||
|
lRes = CFTDlg::OnNotify(wParam, lParam);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return lRes;
|
||
|
}
|
||
|
|
||
|
LRESULT CFTAdvDlg::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
LRESULT lRes = FALSE;
|
||
|
|
||
|
switch(uMsg)
|
||
|
{
|
||
|
case WM_DRAWITEM:
|
||
|
lRes = OnDrawItem(wParam, lParam);
|
||
|
break;
|
||
|
|
||
|
case WM_MEASUREITEM:
|
||
|
lRes = OnMeasureItem(wParam, lParam);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
lRes = CFTDlg::WndProc(uMsg, wParam, lParam);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return lRes;
|
||
|
}
|
||
|
|