401 lines
9.2 KiB
C++
401 lines
9.2 KiB
C++
/*++
|
|
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;
|
|
}
|