Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
9.7 KiB

  1. /*++
  2. Module Name:
  3. mvEdit.cpp
  4. Abstract:
  5. This module contains the declaration of the CMultiValuedStringEdit.
  6. This class displays the dialog to edit multi-valued string.
  7. */
  8. #include "stdafx.h"
  9. #include "mvEdit.h"
  10. #include "utils.h"
  11. #include "dfshelp.h"
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CMultiValuedStringEdit
  14. CMultiValuedStringEdit::CMultiValuedStringEdit(int nDlgTitle, int nText, UINT uiStringLengthLimit) :
  15. m_nDlgTitle(nDlgTitle),
  16. m_nText(nText)
  17. {
  18. m_uiStringLengthLimit = ((0 == uiStringLengthLimit || MAX_PATH <= uiStringLengthLimit) ? (MAX_PATH - 1) : uiStringLengthLimit);
  19. }
  20. CMultiValuedStringEdit::~CMultiValuedStringEdit()
  21. {
  22. }
  23. HRESULT CMultiValuedStringEdit::put_Strings(
  24. IN BSTR i_bstrValues,
  25. IN BSTR i_bstrSeparators
  26. )
  27. {
  28. if (!i_bstrSeparators || 1 != lstrlen(i_bstrSeparators))
  29. return E_INVALIDARG;
  30. m_bstrValues.Empty();
  31. if (i_bstrValues)
  32. {
  33. m_bstrValues = i_bstrValues;
  34. RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrValues);
  35. }
  36. m_bstrSeparators = i_bstrSeparators;
  37. RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrSeparators);
  38. if ((BSTR)m_bstrValues)
  39. _tcslwr((BSTR)m_bstrValues);
  40. _tcslwr((BSTR)m_bstrSeparators);
  41. return S_OK;
  42. }
  43. HRESULT CMultiValuedStringEdit::get_Strings
  44. (
  45. BSTR *o_pbstrValues
  46. )
  47. {
  48. RETURN_INVALIDARG_IF_NULL(o_pbstrValues);
  49. *o_pbstrValues = NULL;
  50. if ((BSTR)m_bstrValues)
  51. GET_BSTR(m_bstrValues, o_pbstrValues);
  52. }
  53. LRESULT CMultiValuedStringEdit::OnInitDialog
  54. (
  55. UINT uMsg,
  56. WPARAM wParam,
  57. LPARAM lParam,
  58. BOOL& bHandled
  59. )
  60. {
  61. HWND hwnd = GetDlgItem(IDC_MVSTRINGEDIT_LIST);
  62. RECT rect = {0};
  63. ::GetWindowRect(hwnd, &rect);
  64. int nControlWidth = rect.right - rect.left;
  65. int nVScrollbarWidth = GetSystemMetrics(SM_CXVSCROLL);
  66. int nBorderWidth = GetSystemMetrics(SM_CXBORDER);
  67. int nControlNetWidth = nControlWidth - 4 * nBorderWidth;
  68. LVCOLUMN lvColumn = {0};
  69. lvColumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH;
  70. lvColumn.fmt = LVCFMT_LEFT;
  71. lvColumn.iSubItem = 0;
  72. lvColumn.cx = nControlNetWidth;
  73. ListView_InsertColumn(hwnd, 0, &lvColumn);
  74. ::EnableWindow(GetDlgItem(IDC_MVSTRINGEDIT_ADD), FALSE);
  75. ::EnableWindow(GetDlgItem(IDC_MVSTRINGEDIT_REMOVE), FALSE);
  76. if (m_nDlgTitle)
  77. {
  78. CComBSTR bstrTitle;
  79. LoadStringFromResource(m_nDlgTitle, &bstrTitle);
  80. SetWindowText(bstrTitle);
  81. }
  82. if (m_nText)
  83. {
  84. CComBSTR bstrText;
  85. LoadStringFromResource(m_nText, &bstrText);
  86. SetDlgItemText(IDC_MVSTRINGEDIT_TEXT, bstrText);
  87. }
  88. SendDlgItemMessage(IDC_MVSTRINGEDIT_STRING, EM_LIMITTEXT, m_uiStringLengthLimit, 0);
  89. if (!m_bstrValues || !*m_bstrValues)
  90. return TRUE;
  91. CComBSTR bstrToken;
  92. int index = 0;
  93. HRESULT hr = mystrtok(m_bstrValues, &index, m_bstrSeparators, &bstrToken);
  94. while (SUCCEEDED(hr) && (BSTR)bstrToken)
  95. {
  96. _tcslwr((BSTR)bstrToken);
  97. LVITEM lvItem = {0};
  98. lvItem.mask = LVIF_TEXT;
  99. lvItem.pszText = bstrToken;
  100. ListView_InsertItem(hwnd, &lvItem);
  101. bstrToken.Empty();
  102. hr = mystrtok(m_bstrValues, &index, m_bstrSeparators, &bstrToken);;
  103. }
  104. return TRUE; // Let the system set the focus
  105. }
  106. /*++
  107. This function is called when a user clicks the ? in the top right of a property sheet
  108. and then clciks a control, or when they hit F1 in a control.
  109. --*/
  110. LRESULT CMultiValuedStringEdit::OnCtxHelp(
  111. IN UINT i_uMsg,
  112. IN WPARAM i_wParam,
  113. IN LPARAM i_lParam,
  114. IN OUT BOOL& io_bHandled
  115. )
  116. {
  117. LPHELPINFO lphi = (LPHELPINFO) i_lParam;
  118. if (!lphi || lphi->iContextType != HELPINFO_WINDOW || lphi->iCtrlId < 0)
  119. return FALSE;
  120. ::WinHelp((HWND)(lphi->hItemHandle),
  121. DFS_CTX_HELP_FILE,
  122. HELP_WM_HELP,
  123. (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_MVSTRINGEDIT);
  124. return TRUE;
  125. }
  126. /*++
  127. This function handles "What's This" help when a user right clicks the control
  128. --*/
  129. LRESULT CMultiValuedStringEdit::OnCtxMenuHelp(
  130. IN UINT i_uMsg,
  131. IN WPARAM i_wParam,
  132. IN LPARAM i_lParam,
  133. IN OUT BOOL& io_bHandled
  134. )
  135. {
  136. ::WinHelp((HWND)i_wParam,
  137. DFS_CTX_HELP_FILE,
  138. HELP_CONTEXTMENU,
  139. (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_MVSTRINGEDIT);
  140. return TRUE;
  141. }
  142. LRESULT CMultiValuedStringEdit::OnString
  143. (
  144. WORD wNotifyCode,
  145. WORD wID,
  146. HWND hWndCtl,
  147. BOOL& bHandled
  148. )
  149. {
  150. ::EnableWindow(GetDlgItem(IDC_MVSTRINGEDIT_ADD),
  151. (0 < ::GetWindowTextLength(GetDlgItem(IDC_MVSTRINGEDIT_STRING))));
  152. return TRUE;
  153. }
  154. LRESULT CMultiValuedStringEdit::OnNotify
  155. (
  156. IN UINT i_uMsg,
  157. IN WPARAM i_wParam,
  158. IN LPARAM i_lParam,
  159. IN OUT BOOL& io_bHandled
  160. )
  161. {
  162. NMHDR* pNMHDR = (NMHDR*)i_lParam;
  163. if (IDC_MVSTRINGEDIT_LIST == pNMHDR->idFrom)
  164. {
  165. if (LVN_ITEMCHANGED == pNMHDR->code)
  166. {
  167. int nCount = ListView_GetSelectedCount(GetDlgItem(IDC_MVSTRINGEDIT_LIST));
  168. ::EnableWindow(GetDlgItem(IDC_MVSTRINGEDIT_REMOVE), (nCount >= 1));
  169. }
  170. }
  171. return FALSE;
  172. }
  173. LRESULT CMultiValuedStringEdit::OnAdd
  174. (
  175. WORD wNotifyCode,
  176. WORD wID,
  177. HWND hWndCtl,
  178. BOOL& bHandled
  179. )
  180. {
  181. CComBSTR bstr;
  182. DWORD dwTextLength = 0;
  183. HRESULT hr = GetInputText(GetDlgItem(IDC_MVSTRINGEDIT_STRING), &bstr, &dwTextLength);
  184. if (FAILED(hr))
  185. {
  186. DisplayMessageBoxForHR(hr);
  187. } else if (0 < dwTextLength)
  188. {
  189. _tcslwr((BSTR)bstr);
  190. if (!_tcschr(bstr, *m_bstrSeparators))
  191. {
  192. LVFINDINFO lvInfo = {0};
  193. lvInfo.flags = LVFI_STRING;
  194. lvInfo.psz = bstr;
  195. HWND hwnd = GetDlgItem(IDC_MVSTRINGEDIT_LIST);
  196. if (-1 == ListView_FindItem(hwnd, -1, &lvInfo))
  197. {
  198. LVITEM lvItem = {0};
  199. lvItem.mask = LVIF_TEXT;
  200. lvItem.pszText = bstr;
  201. ListView_InsertItem(hwnd, &lvItem);
  202. }
  203. SetDlgItemText(IDC_MVSTRINGEDIT_STRING, _T(""));
  204. } else
  205. {
  206. DisplayMessageBox(hWndCtl, MB_OK, 0, IDS_MVSTRINGEDIT_STRING_INVALID, m_bstrSeparators);
  207. }
  208. }
  209. ::SetFocus(GetDlgItem(IDC_MVSTRINGEDIT_STRING));
  210. return TRUE;
  211. }
  212. LRESULT CMultiValuedStringEdit::OnRemove
  213. (
  214. WORD wNotifyCode,
  215. WORD wID,
  216. HWND hWndCtl,
  217. BOOL& bHandled
  218. )
  219. {
  220. HWND hwnd = GetDlgItem(IDC_MVSTRINGEDIT_LIST);
  221. int nIndex = -1;
  222. while (-1 != (nIndex = ListView_GetNextItem(hwnd, -1, LVNI_SELECTED)))
  223. ListView_DeleteItem(hwnd, nIndex);
  224. return TRUE;
  225. }
  226. LRESULT CMultiValuedStringEdit::OnOK
  227. (
  228. WORD wNotifyCode,
  229. WORD wID,
  230. HWND hWndCtl,
  231. BOOL& bHandled
  232. )
  233. {
  234. m_bstrValues.Empty();
  235. HRESULT hr = S_OK;
  236. HWND hwnd = GetDlgItem(IDC_MVSTRINGEDIT_LIST);
  237. if (0 < ListView_GetItemCount(hwnd))
  238. {
  239. PTSTR pszText = (PTSTR)calloc(m_uiStringLengthLimit+1, sizeof(TCHAR));
  240. if (pszText)
  241. {
  242. int nIndex = -1;
  243. while (-1 != (nIndex = ListView_GetNextItem(hwnd, nIndex, LVNI_ALL)))
  244. {
  245. ListView_GetItemText(hwnd, nIndex, 0, pszText, m_uiStringLengthLimit+1);
  246. if (!m_bstrValues || !*m_bstrValues)
  247. {
  248. m_bstrValues = pszText;
  249. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrValues, &hr);
  250. } else
  251. {
  252. m_bstrValues += m_bstrSeparators;
  253. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrValues, &hr);
  254. m_bstrValues += pszText;
  255. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrValues, &hr);
  256. }
  257. }
  258. free(pszText);
  259. } else
  260. {
  261. hr = E_OUTOFMEMORY;
  262. }
  263. }
  264. if (FAILED(hr))
  265. {
  266. DisplayMessageBoxForHR(hr);
  267. ::SetFocus(GetDlgItem(IDC_MVSTRINGEDIT_STRING));
  268. return FALSE;
  269. }
  270. EndDialog(S_OK);
  271. return TRUE;
  272. }
  273. LRESULT CMultiValuedStringEdit::OnCancel
  274. (
  275. WORD wNotifyCode,
  276. WORD wID,
  277. HWND hWndCtl,
  278. BOOL& bHandled
  279. )
  280. {
  281. /*++
  282. Routine Description:
  283. Called OnCancel. Ends the dialog with S_FALSE;
  284. */
  285. EndDialog(S_FALSE);
  286. return TRUE;
  287. }
  288. //
  289. // Invoke the dialog.
  290. //
  291. // S_OK: io_pbstr contains the new string
  292. // S_FALSE: dlg cancelled, or string unchanged
  293. // others: error occurred and reported
  294. //
  295. HRESULT InvokeMultiValuedStringEditDlg(
  296. IN BSTR* io_pbstr,
  297. IN BSTR i_bstrSeparators,
  298. IN int i_nDlgTitle,
  299. IN int i_nText,
  300. IN UINT i_uiStringLengthLimit
  301. )
  302. {
  303. HRESULT hr = S_OK;
  304. CMultiValuedStringEdit editDlg(i_nDlgTitle, i_nText, i_uiStringLengthLimit);
  305. do {
  306. if (!io_pbstr)
  307. {
  308. hr = E_INVALIDARG;
  309. break;
  310. }
  311. hr = editDlg.put_Strings(*io_pbstr, i_bstrSeparators);
  312. BREAK_IF_FAILED(hr);
  313. if (S_OK == editDlg.DoModal())
  314. {
  315. CComBSTR bstr;
  316. hr = editDlg.get_Strings(&bstr);
  317. BREAK_IF_FAILED(hr);
  318. if (!*io_pbstr && (BSTR)bstr ||
  319. *io_pbstr && !bstr ||
  320. 0 != lstrcmpi(*io_pbstr, bstr))
  321. {
  322. SysFreeString(*io_pbstr);
  323. *io_pbstr = bstr.Detach();
  324. hr = S_OK;
  325. } else
  326. {
  327. hr = S_FALSE; // string unchanged
  328. }
  329. }
  330. } while (0);
  331. if (FAILED(hr))
  332. DisplayMessageBoxForHR(hr);
  333. return hr;
  334. }