#include "shellprv.h" #include "ids.h" #include "help.h" #include "ascstr.h" #include "ftdlg.h" #include "ftedit.h" #include "ftcmmn.h" #define ID_TIMER 2222 const static DWORD cs_rgdwHelpIDsArray[] = { // Context Help IDs IDC_FT_EDIT_EXT_EDIT_TEXT, IDH_FCAB_FT_NE_FILEEXT, IDC_FT_EDIT_EXT_EDIT, IDH_FCAB_FT_NE_FILEEXT, IDC_FT_EDIT_PID_COMBO_TEXT, IDH_FCAB_FT_NE_FILETYPE, IDC_FT_EDIT_PID_COMBO, IDH_FCAB_FT_NE_FILETYPE, IDC_FT_EDIT_ADVANCED, IDH_FCAB_FT_NE_ADV_BUT, IDC_NO_HELP_1, NO_HELP, 0, 0 }; CFTEditDlg::CFTEditDlg(FTEDITPARAM* pftEditParam) : CFTDlg((ULONG_PTR)cs_rgdwHelpIDsArray), _pftEditParam(pftEditParam), _iLVSel(-1) { } CFTEditDlg::~CFTEditDlg() { } /////////////////////////////////////////////////////////////////////////////// // Logic specific to our problem LRESULT CFTEditDlg::OnInitDialog(WPARAM wParam, LPARAM lParam) { HRESULT hres = E_FAIL; if (_pftEditParam) { hres = _InitAssocStore(); if (SUCCEEDED(hres)) { _hHeapProgID = HeapCreate(0, 8 * 1024, 0); if (!_hHeapProgID) hres = E_OUTOFMEMORY; } if (SUCCEEDED(hres)) SetDlgItemText(_hwnd, IDC_FT_EDIT_EXT_EDIT, TEXT("")); } if (FAILED(hres)) EndDialog(_hwnd, -1); else Edit_LimitText(GetDlgItem(_hwnd, IDC_FT_EDIT_EXT_EDIT), MAX_EXT - 1); // Return TRUE so that system set focus return TRUE; } LRESULT CFTEditDlg::OnEdit(WORD wNotif) { if (_fAdvanced) { if (EN_CHANGE == wNotif) { if (_nTimer) { KillTimer(_hwnd, _nTimer); _nTimer = 0; } _nTimer = SetTimer(_hwnd, ID_TIMER, 400, NULL); } } return FALSE; } LRESULT CFTEditDlg::OnTimer(UINT nTimer) { // Kill the timer KillTimer(_hwnd, _nTimer); _nTimer = 0; _ProgIDComboHelper(); return TRUE; } HRESULT CFTEditDlg::_ProgIDComboHelper() { TCHAR szExt[MAX_EXT]; TCHAR szProgIDDescr[MAX_PROGIDDESCR]; DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr); HRESULT hres = E_FAIL; GetDlgItemText(_hwnd, IDC_FT_EDIT_EXT_EDIT, szExt, ARRAYSIZE(szExt)); hres = _GetProgIDDescrFromExt(szExt, szProgIDDescr, &cchProgIDDescr); if (SUCCEEDED(hres)) _SelectProgIDDescr(szProgIDDescr); return hres; } HRESULT CFTEditDlg::_GetProgIDDescrFromExt(LPTSTR pszExt, LPTSTR pszProgIDDescr, DWORD* pcchProgIDDescr) { IAssocInfo* pAI = NULL; HRESULT hres = _pAssocStore->GetAssocInfo(pszExt, AIINIT_EXT, &pAI); if (SUCCEEDED(hres)) { hres = pAI->GetString(AISTR_PROGIDDESCR, pszProgIDDescr, pcchProgIDDescr); pAI->Release(); } return hres; } LRESULT CFTEditDlg::OnAdvancedButton(WORD wNotif) { DECLAREWAITCURSOR; TCHAR szAdvBtnText[50]; SetWaitCursor(); _fAdvanced = !_fAdvanced; LoadString(g_hinst, _fAdvanced ? IDS_FT_ADVBTNTEXTEXPAND : IDS_FT_ADVBTNTEXTCOLLAPS, szAdvBtnText, ARRAYSIZE(szAdvBtnText)); SetWindowText(GetDlgItem(_hwnd, IDC_FT_EDIT_ADVANCED), szAdvBtnText); _ConfigureDlg(); UpdateWindow(_hwnd); if (_fAdvanced) { HWND hwndCombo = GetDlgItem(_hwnd, IDC_FT_EDIT_PID_COMBO); // Is the combobox filled yet? if (!ComboBox_GetCount(hwndCombo)) { _FillProgIDDescrCombo(); // Select the item if (FAILED(_ProgIDComboHelper())) { TCHAR szNew[20]; if (LoadString(g_hinst, IDS_FT_NEW, szNew, ARRAYSIZE(szNew))) { int iIndex = ComboBox_FindStringExact(hwndCombo, -1, szNew); if (CB_ERR != iIndex) ComboBox_SetCurSel(hwndCombo, iIndex); } } } } ResetWaitCursor(); return FALSE; } void CFTEditDlg::_ConfigureDlg() { // Need to: // - position OK and Cancel // - resize dlg // - Show/hide Combo and its text RECT rcControl; RECT rcDialog; RECT rcCancel; RECT rcOK; int iStdMargins = 0; int iStdSpaceBetweenControls = 0; GetWindowRect(_hwnd, &rcDialog); GetWindowRect(GetDlgItem(_hwnd, IDC_FT_EDIT_PID_COMBO_TEXT), &rcControl); // Calculate the folowing (cannot be fixed, varies with dialog font) // [msadek]; screen coordinates. need to consider the mirrored case if(IS_WINDOW_RTL_MIRRORED(_hwnd)) { iStdMargins = rcDialog.right - rcControl.right; } else { iStdMargins = rcControl.left - rcDialog.left; } iStdSpaceBetweenControls = MulDiv(4, iStdMargins, 7); // Move Cancel and OK button GetWindowRect(GetDlgItem(_hwnd, _fAdvanced ? IDC_FT_EDIT_PID_COMBO : IDC_FT_EDIT_EXT_EDIT), &rcControl); MapWindowRect(HWND_DESKTOP, _hwnd, &rcControl); GetWindowRect(GetDlgItem(_hwnd, IDCANCEL), &rcCancel); MapWindowRect(HWND_DESKTOP, _hwnd, &rcCancel); OffsetRect(&rcCancel, 0, -rcCancel.top); GetWindowRect(GetDlgItem(_hwnd, IDOK), &rcOK); MapWindowRect(HWND_DESKTOP, _hwnd, &rcOK); OffsetRect(&rcOK, 0, -rcOK.top); OffsetRect(&rcCancel, 0, rcControl.bottom + iStdSpaceBetweenControls); OffsetRect(&rcOK, 0, rcControl.bottom + iStdSpaceBetweenControls); SetWindowPos(GetDlgItem(_hwnd, IDOK), NULL, rcOK.left, rcOK.top, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOZORDER); SetWindowPos(GetDlgItem(_hwnd, IDCANCEL), NULL, rcCancel.left, rcCancel.top, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOZORDER); // Resize Dlg ClientToScreen(_hwnd, ((POINT*)&rcCancel) + 1); rcDialog.bottom = rcCancel.bottom + iStdMargins; SetWindowPos(_hwnd, NULL, 0, 0, rcDialog.right - rcDialog.left, rcDialog.bottom - rcDialog.top, SWP_NOMOVE|SWP_SHOWWINDOW|SWP_NOZORDER); // Show/Hide Combo and its text ShowWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_PID_COMBO_TEXT), _fAdvanced); ShowWindow(GetDlgItem(_hwnd, IDC_FT_EDIT_PID_COMBO), _fAdvanced); // Set focus to combo SetFocus(GetDlgItem(_hwnd, IDC_FT_EDIT_PID_COMBO)); } LRESULT CFTEditDlg::OnOK(WORD wNotif) { HRESULT hres = S_FALSE; // Pick up the extension GetDlgItemText(_hwnd, IDC_FT_EDIT_EXT_EDIT, _pftEditParam->szExt, _pftEditParam->dwExt); // Is it empty? if (0 != (*_pftEditParam->szExt)) { // No, that's good // FEATURE: do some check for valid extension name IAssocInfo* pAI = NULL; hres = _pAssocStore->GetAssocInfo(_pftEditParam->szExt, AIINIT_EXT, &pAI); if (SUCCEEDED(hres)) { BOOL fExist = FALSE; hres = pAI->GetBOOL(AIBOOL_EXTEXIST, &fExist); // Is this extension already existing? if (SUCCEEDED(hres) && !fExist) { // No, create it // Check for spaces in the ext name LPTSTR pszExt = _pftEditParam->szExt; while (*pszExt && (S_FALSE != hres)) { if (TEXT(' ') == *pszExt) { hres = S_FALSE; ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_FT_MB_NOSPACEINEXT), MAKEINTRESOURCE(IDS_FT), MB_OK | MB_ICONSTOP); // Set focus to Ext combo PostMessage(_hwnd, WM_CTRL_SETFOCUS, (WPARAM)0, (LPARAM)GetDlgItem(_hwnd, IDC_FT_EDIT_EXT_EDIT)); } ++pszExt; } if (S_OK==hres) hres = pAI->Create(); } if (S_OK==hres) hres = _HandleProgIDAssoc(pAI, _pftEditParam->szExt, fExist); pAI->Release(); } } else { ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_FT_MB_NOEXT), MAKEINTRESOURCE(IDS_FT), MB_OK | MB_ICONSTOP); // Set focus to Ext combo PostMessage(_hwnd, WM_CTRL_SETFOCUS, (WPARAM)0, (LPARAM)GetDlgItem(_hwnd, IDC_FT_EDIT_EXT_EDIT)); } // If we fail, we are in serious trouble, so we just close the dialog ASSERT(SUCCEEDED(hres)); if (S_FALSE != hres) EndDialog(_hwnd, IDOK); return FALSE; } HRESULT CFTEditDlg::_GetProgIDInfo(IAssocInfo* pAI, LPTSTR pszProgID, DWORD* pcchProgID, BOOL* pfNewProgID, BOOL* pfExplicitNew) { HWND hwndCombo = GetDlgItem(_hwnd, IDC_FT_EDIT_PID_COMBO); HRESULT hr = S_OK; *pfNewProgID = FALSE; *pfExplicitNew = FALSE; if (ComboBox_GetCount(hwndCombo)) { int iSel = ComboBox_GetCurSel(hwndCombo); if (CB_ERR != iSel) { LPTSTR pszTmpProgID = (LPTSTR)ComboBox_GetItemData(hwndCombo, iSel); // Is this the "" item (the only one with a ProgID == NULL)? if (!pszTmpProgID) { // Yes *pfNewProgID = TRUE; *pfExplicitNew = TRUE; } else { // No hr = StringCchCopy(pszProgID, *pcchProgID, pszTmpProgID); } } } else { *pfNewProgID = TRUE; } return hr; } HRESULT CFTEditDlg::_HandleProgIDAssoc(IAssocInfo* pAI, LPTSTR pszExt, BOOL fExtExist) { TCHAR szProgID[MAX_PROGID]; DWORD cchProgID = ARRAYSIZE(szProgID); BOOL fNewProgID = FALSE; BOOL fExplicitNew = FALSE; *szProgID = 0; HRESULT hres = _GetProgIDInfo(pAI, szProgID, &cchProgID, &fNewProgID, &fExplicitNew); if (SUCCEEDED(hres)) { // Is this Extension already existing? if (fExtExist) { // // First make sure it's not the exact same ext - progID assoc // TCHAR szTmpProgID[MAX_PROGID]; DWORD cchTmpProgID = ARRAYSIZE(szTmpProgID); hres = pAI->GetString(AISTR_PROGID, szTmpProgID, &cchTmpProgID); // Did we got a progID? if (SUCCEEDED(hres)) { // Yes // Are they the same? if (0 == lstrcmpi(szTmpProgID, szProgID)) { // Yes, fail, nothing more to do hres = E_FAIL; } else { // No, go on hres = S_OK; } } else { // No, there probably is no ProgID, go on hres = S_OK; } // // Unless the user chose explicitly ask if he wants to break the assoc // // Did the user explicitly chose (and we did not failed already)? if (!fExplicitNew && SUCCEEDED(hres)) { // We need to warn user that he will break existing assoc TCHAR szProgIDDescr[MAX_PROGIDDESCR]; DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr); hres = pAI->GetString(AISTR_PROGIDDESCR, szProgIDDescr, &cchProgIDDescr); if (SUCCEEDED(hres)) { if (IDNO == ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_FT_EDIT_ALREADYASSOC), MAKEINTRESOURCE(IDS_FT_EDIT_ALRASSOCTITLE), MB_YESNO | MB_ICONEXCLAMATION, pszExt, szProgIDDescr, pszExt, szProgIDDescr)) { // S_FALSE means user does not want to go on hres = S_FALSE; } } else { // no progIDDescr... Check if we have a progID TCHAR szProgID[MAX_PROGID]; DWORD cchProgID = ARRAYSIZE(szProgID); hres = pAI->GetString(AISTR_PROGID, szProgID, &cchProgID); if (FAILED(hres)) { // no progID, set hres to S_OK so that we go on and create one hres = S_OK; } } } } // Should we go on and create new progID? if (S_OK==hres && fNewProgID) { // Yes, create it IAssocInfo* pAIProgID = NULL; hres = _pAssocStore->GetAssocInfo(NULL, AIINIT_PROGID, &pAIProgID); if (SUCCEEDED(hres)) { hres = pAIProgID->Create(); if (SUCCEEDED(hres)) { TCHAR szExt[MAX_EXT]; DWORD cchExt = ARRAYSIZE(szExt); TCHAR szProgIDDescr[MAX_PROGIDDESCR]; HRESULT hresTmp = pAI->GetString(AISTR_EXT, szExt, &cchExt); if (SUCCEEDED(hresTmp) && *szExt) { MakeDefaultProgIDDescrFromExt(szProgIDDescr, ARRAYSIZE(szProgIDDescr), szExt); hresTmp = pAIProgID->SetString(AISTR_PROGIDDESCR, szProgIDDescr); } // Get the ProgID for later use pAIProgID->GetString(AISTR_PROGID, szProgID, &cchProgID); } pAIProgID->Release(); } } if (S_OK==hres) { // Set the new extension progID hres = pAI->SetString(AISTR_PROGID, szProgID); if (SUCCEEDED(hres)) { // Get the description pAI->GetString(AISTR_PROGIDDESCR, _pftEditParam->szProgIDDescr, &(_pftEditParam->dwProgIDDescr)); } } } return hres; } LRESULT CFTEditDlg::OnCancel(WORD wNotif) { EndDialog(_hwnd, IDCANCEL); return FALSE; } HRESULT CFTEditDlg::_FillProgIDDescrCombo() { HWND hwndCombo = GetDlgItem(_hwnd, IDC_FT_EDIT_PID_COMBO); // Data stuff IEnumAssocInfo* pEnum = NULL; HRESULT hres = _pAssocStore->EnumAssocInfo( ASENUM_PROGID | ASENUM_ASSOC_ALL, NULL, AIINIT_NONE, &pEnum); if (SUCCEEDED(hres)) { IAssocInfo* pAI = NULL; while ((E_OUTOFMEMORY != hres) && (S_OK == pEnum->Next(&pAI))) { TCHAR szProgIDDescr[MAX_PROGIDDESCR]; DWORD cchProgIDDescr = ARRAYSIZE(szProgIDDescr); hres = pAI->GetString(AISTR_PROGIDDESCR, szProgIDDescr, &cchProgIDDescr); if (SUCCEEDED(hres)) { int iIndex = CB_ERR; if (*szProgIDDescr) { if (CB_ERR == ComboBox_FindStringExact(hwndCombo, -1, szProgIDDescr)) iIndex = ComboBox_AddString(hwndCombo, szProgIDDescr); } if ((CB_ERR != iIndex) && (CB_ERRSPACE != iIndex)) { TCHAR szProgID[MAX_PROGID]; DWORD cchProgID = ARRAYSIZE(szProgID); hres = pAI->GetString(AISTR_PROGID, szProgID, &cchProgID); if (SUCCEEDED(hres)) { LPTSTR pszProgID = _AddProgID(szProgID); // allocate and copy ID if(pszProgID) { ComboBox_SetItemData(hwndCombo, iIndex, pszProgID); } else { hres = E_OUTOFMEMORY; ShellMessageBox(g_hinst, _hwnd, MAKEINTRESOURCE(IDS_ERROR + ERROR_NOT_ENOUGH_MEMORY), MAKEINTRESOURCE(IDS_FT), MB_OK | MB_ICONSTOP); // Already allocated mem will be cleaned-up in OnDestroy } } } } pAI->Release(); } pEnum->Release(); if (SUCCEEDED(hres)) { TCHAR szNew[20]; if (LoadString(g_hinst, IDS_FT_NEW, szNew, ARRAYSIZE(szNew))) { int iIndex = ComboBox_InsertString(hwndCombo, 0, szNew); if (CB_ERR != iIndex) ComboBox_SetItemData(hwndCombo, iIndex, NULL); } } } return hres; } BOOL CFTEditDlg::_SelectProgIDDescr(LPTSTR pszProgIDDescr) { int iIndex = ComboBox_SelectString(GetDlgItem(_hwnd, IDC_FT_EDIT_PID_COMBO), -1, pszProgIDDescr); return ((CB_ERR != iIndex) ? TRUE : FALSE); } LRESULT CFTEditDlg::OnDestroy(WPARAM wParam, LPARAM lParam) { _CleanupProgIDs(); CFTDlg::OnDestroy(wParam, lParam); return FALSE; } // Clone a progID LPTSTR CFTEditDlg::_AddProgID(LPTSTR pszProgID) { ASSERT(_hHeapProgID); DWORD dwStrBufferLen = lstrlen(pszProgID) + 1; LPTSTR pNewID = (LPTSTR) HeapAlloc(_hHeapProgID, 0, dwStrBufferLen * sizeof(TCHAR)); if(pNewID) { StringCchCopy(pNewID, dwStrBufferLen, pszProgID); } return pNewID; } void CFTEditDlg::_CleanupProgIDs() { if (_hHeapProgID) HeapDestroy(_hHeapProgID); } /////////////////////////////////////////////////////////////////////////////// // Windows boiler plate code LRESULT CFTEditDlg::OnCommand(WPARAM wParam, LPARAM lParam) { LRESULT lRes = FALSE; switch(GET_WM_COMMAND_ID(wParam, lParam)) { case IDC_FT_EDIT_ADVANCED: lRes = OnAdvancedButton(GET_WM_COMMAND_CMD(wParam, lParam)); break; case IDC_FT_EDIT_EXT_EDIT: lRes = OnEdit(GET_WM_COMMAND_CMD(wParam, lParam)); break; default: lRes = CFTDlg::OnCommand(wParam, lParam); break; } return lRes; } LRESULT CFTEditDlg::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRes = FALSE; switch(uMsg) { case WM_TIMER: if (ID_TIMER == wParam) lRes = OnTimer((UINT)wParam); else lRes = CFTDlg::WndProc(uMsg, wParam, lParam); break; default: lRes = CFTDlg::WndProc(uMsg, wParam, lParam); break; } return lRes; }