/*++ Module Name: mvEdit.cpp Abstract: This module contains the declaration of the CMultiValuedStringEdit. This class displays the dialog to edit multi-valued string. */ #include "stdafx.h" #include "mvEdit.h" #include "utils.h" #include "dfshelp.h" ///////////////////////////////////////////////////////////////////////////// // CMultiValuedStringEdit CMultiValuedStringEdit::CMultiValuedStringEdit(int nDlgTitle, int nText, UINT uiStringLengthLimit) : m_nDlgTitle(nDlgTitle), m_nText(nText) { m_uiStringLengthLimit = ((0 == uiStringLengthLimit) ? MAX_PATH : uiStringLengthLimit); } CMultiValuedStringEdit::~CMultiValuedStringEdit() { } HRESULT CMultiValuedStringEdit::put_Strings( IN BSTR i_bstrValues, IN BSTR i_bstrSeparators ) { if (!i_bstrSeparators || 1 != lstrlen(i_bstrSeparators)) return E_INVALIDARG; m_bstrValues.Empty(); if (i_bstrValues) { m_bstrValues = i_bstrValues; RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrValues); } m_bstrSeparators = i_bstrSeparators; RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrSeparators); if ((BSTR)m_bstrValues) _tcslwr((BSTR)m_bstrValues); _tcslwr((BSTR)m_bstrSeparators); return S_OK; } HRESULT CMultiValuedStringEdit::get_Strings ( BSTR *o_pbstrValues ) { RETURN_INVALIDARG_IF_NULL(o_pbstrValues); *o_pbstrValues = NULL; if ((BSTR)m_bstrValues) GET_BSTR(m_bstrValues, o_pbstrValues); } LRESULT CMultiValuedStringEdit::OnInitDialog ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { HWND hwnd = GetDlgItem(IDC_MVSTRINGEDIT_LIST); RECT rect = {0}; ::GetWindowRect(hwnd, &rect); int nControlWidth = rect.right - rect.left; int nVScrollbarWidth = GetSystemMetrics(SM_CXVSCROLL); int nBorderWidth = GetSystemMetrics(SM_CXBORDER); int nControlNetWidth = nControlWidth - 4 * nBorderWidth; LVCOLUMN lvColumn = {0}; lvColumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH; lvColumn.fmt = LVCFMT_LEFT; lvColumn.iSubItem = 0; lvColumn.cx = nControlNetWidth; ListView_InsertColumn(hwnd, 0, &lvColumn); ::EnableWindow(GetDlgItem(IDC_MVSTRINGEDIT_ADD), FALSE); ::EnableWindow(GetDlgItem(IDC_MVSTRINGEDIT_REMOVE), FALSE); if (m_nDlgTitle) { CComBSTR bstrTitle; LoadStringFromResource(m_nDlgTitle, &bstrTitle); SetWindowText(bstrTitle); } if (m_nText) { CComBSTR bstrText; LoadStringFromResource(m_nText, &bstrText); SetDlgItemText(IDC_MVSTRINGEDIT_TEXT, bstrText); } SendDlgItemMessage(IDC_MVSTRINGEDIT_STRING, EM_LIMITTEXT, m_uiStringLengthLimit, 0); if (!m_bstrValues || !*m_bstrValues) return TRUE; CComBSTR bstrToken; int index = 0; HRESULT hr = mystrtok(m_bstrValues, &index, m_bstrSeparators, &bstrToken); while (SUCCEEDED(hr) && (BSTR)bstrToken) { _tcslwr((BSTR)bstrToken); LVITEM lvItem = {0}; lvItem.mask = LVIF_TEXT; lvItem.pszText = bstrToken; ListView_InsertItem(hwnd, &lvItem); bstrToken.Empty(); hr = mystrtok(m_bstrValues, &index, m_bstrSeparators, &bstrToken);; } return TRUE; // Let the system set the focus } /*++ This function is called when a user clicks the ? in the top right of a property sheet and then clciks a control, or when they hit F1 in a control. --*/ LRESULT CMultiValuedStringEdit::OnCtxHelp( IN UINT i_uMsg, IN WPARAM i_wParam, IN LPARAM i_lParam, IN OUT BOOL& io_bHandled ) { LPHELPINFO lphi = (LPHELPINFO) i_lParam; if (!lphi || lphi->iContextType != HELPINFO_WINDOW || lphi->iCtrlId < 0) return FALSE; ::WinHelp((HWND)(lphi->hItemHandle), DFS_CTX_HELP_FILE, HELP_WM_HELP, (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_MVSTRINGEDIT); return TRUE; } /*++ This function handles "What's This" help when a user right clicks the control --*/ LRESULT CMultiValuedStringEdit::OnCtxMenuHelp( IN UINT i_uMsg, IN WPARAM i_wParam, IN LPARAM i_lParam, IN OUT BOOL& io_bHandled ) { ::WinHelp((HWND)i_wParam, DFS_CTX_HELP_FILE, HELP_CONTEXTMENU, (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_MVSTRINGEDIT); return TRUE; } LRESULT CMultiValuedStringEdit::OnString ( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { ::EnableWindow(GetDlgItem(IDC_MVSTRINGEDIT_ADD), (0 < ::GetWindowTextLength(GetDlgItem(IDC_MVSTRINGEDIT_STRING)))); return TRUE; } LRESULT CMultiValuedStringEdit::OnNotify ( IN UINT i_uMsg, IN WPARAM i_wParam, IN LPARAM i_lParam, IN OUT BOOL& io_bHandled ) { NMHDR* pNMHDR = (NMHDR*)i_lParam; if (IDC_MVSTRINGEDIT_LIST == pNMHDR->idFrom) { if (LVN_ITEMCHANGED == pNMHDR->code) { int nCount = ListView_GetSelectedCount(GetDlgItem(IDC_MVSTRINGEDIT_LIST)); ::EnableWindow(GetDlgItem(IDC_MVSTRINGEDIT_REMOVE), (nCount >= 1)); } } return FALSE; } LRESULT CMultiValuedStringEdit::OnAdd ( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { CComBSTR bstr; DWORD dwTextLength = 0; HRESULT hr = GetInputText(GetDlgItem(IDC_MVSTRINGEDIT_STRING), &bstr, &dwTextLength); if (FAILED(hr)) { DisplayMessageBoxForHR(hr); } else if (0 < dwTextLength) { _tcslwr((BSTR)bstr); if (!_tcschr(bstr, *m_bstrSeparators)) { LVFINDINFO lvInfo = {0}; lvInfo.flags = LVFI_STRING; lvInfo.psz = bstr; HWND hwnd = GetDlgItem(IDC_MVSTRINGEDIT_LIST); if (-1 == ListView_FindItem(hwnd, -1, &lvInfo)) { LVITEM lvItem = {0}; lvItem.mask = LVIF_TEXT; lvItem.pszText = bstr; ListView_InsertItem(hwnd, &lvItem); } SetDlgItemText(IDC_MVSTRINGEDIT_STRING, _T("")); } else { DisplayMessageBox(hWndCtl, MB_OK, 0, IDS_MVSTRINGEDIT_STRING_INVALID, m_bstrSeparators); } } ::SetFocus(GetDlgItem(IDC_MVSTRINGEDIT_STRING)); return TRUE; } LRESULT CMultiValuedStringEdit::OnRemove ( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { HWND hwnd = GetDlgItem(IDC_MVSTRINGEDIT_LIST); int nIndex = -1; while (-1 != (nIndex = ListView_GetNextItem(hwnd, -1, LVNI_SELECTED))) ListView_DeleteItem(hwnd, nIndex); return TRUE; } LRESULT CMultiValuedStringEdit::OnOK ( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { m_bstrValues.Empty(); HRESULT hr = S_OK; HWND hwnd = GetDlgItem(IDC_MVSTRINGEDIT_LIST); if (0 < ListView_GetItemCount(hwnd)) { PTSTR pszText = (PTSTR)calloc(m_uiStringLengthLimit+1, sizeof(TCHAR)); if (pszText) { int nIndex = -1; while (-1 != (nIndex = ListView_GetNextItem(hwnd, nIndex, LVNI_ALL))) { ListView_GetItemText(hwnd, nIndex, 0, pszText, m_uiStringLengthLimit+1); if (!m_bstrValues || !*m_bstrValues) { m_bstrValues = pszText; BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrValues, &hr); } else { m_bstrValues += m_bstrSeparators; BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrValues, &hr); m_bstrValues += pszText; BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrValues, &hr); } } free(pszText); } else { hr = E_OUTOFMEMORY; } } if (FAILED(hr)) { DisplayMessageBoxForHR(hr); ::SetFocus(GetDlgItem(IDC_MVSTRINGEDIT_STRING)); return FALSE; } EndDialog(S_OK); return TRUE; } LRESULT CMultiValuedStringEdit::OnCancel ( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ) { /*++ Routine Description: Called OnCancel. Ends the dialog with S_FALSE; */ EndDialog(S_FALSE); return TRUE; } // // Invoke the dialog. // // S_OK: io_pbstr contains the new string // S_FALSE: dlg cancelled, or string unchanged // others: error occurred and reported // HRESULT InvokeMultiValuedStringEditDlg( IN BSTR* io_pbstr, IN BSTR i_bstrSeparators, IN int i_nDlgTitle, IN int i_nText, IN UINT i_uiStringLengthLimit ) { HRESULT hr = S_OK; CMultiValuedStringEdit editDlg(i_nDlgTitle, i_nText, i_uiStringLengthLimit); do { if (!io_pbstr) { hr = E_INVALIDARG; break; } hr = editDlg.put_Strings(*io_pbstr, i_bstrSeparators); BREAK_IF_FAILED(hr); if (S_OK == editDlg.DoModal()) { CComBSTR bstr; hr = editDlg.get_Strings(&bstr); BREAK_IF_FAILED(hr); if (!*io_pbstr && (BSTR)bstr || *io_pbstr && !bstr || 0 != lstrcmpi(*io_pbstr, bstr)) { SysFreeString(*io_pbstr); *io_pbstr = bstr.Detach(); hr = S_OK; } else { hr = S_FALSE; // string unchanged } } } while (0); if (FAILED(hr)) DisplayMessageBoxForHR(hr); return hr; }