Source code of Windows XP (NT5)
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.

484 lines
8.7 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name :
  4. ddxv.cpp
  5. Abstract:
  6. DDX/DDV Routines
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "common.h"
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char BASED_CODE THIS_FILE[] = __FILE__;
  21. #endif
  22. #define new DEBUG_NEW
  23. //
  24. // Prototype for external function
  25. //
  26. void AFXAPI AfxSetWindowText(HWND hWndCtrl, LPCTSTR lpszNew);
  27. //
  28. // Numeric strings cannot be longer than 32 digits
  29. //
  30. #define NUMERIC_BUFF_SIZE (32)
  31. //
  32. // Dummy password used for display purposes
  33. //
  34. LPCTSTR g_lpszDummyPassword = _T("**********");
  35. extern HINSTANCE hDLLInstance;
  36. void
  37. AFXAPI DDV_MinChars(
  38. IN CDataExchange * pDX,
  39. IN CString const & value,
  40. IN int nChars
  41. )
  42. /*++
  43. Routine Description:
  44. Validate CString using a minimum string length
  45. Arguments:
  46. CDataExchange * pDX : Data exchange structure
  47. CString const & value : String to be validated
  48. int nChars : Minimum length of string
  49. Return Value:
  50. None
  51. --*/
  52. {
  53. if (pDX->m_bSaveAndValidate && value.GetLength() < nChars)
  54. {
  55. TCHAR szT[NUMERIC_BUFF_SIZE + 1];
  56. wsprintf(szT, _T("%d"), nChars);
  57. CString prompt;
  58. ::AfxFormatString1(prompt, IDS_DDX_MINIMUM, szT);
  59. ::AfxMessageBox(prompt, MB_ICONEXCLAMATION, IDS_DDX_MINIMUM);
  60. //
  61. // exception prep
  62. //
  63. prompt.Empty();
  64. pDX->Fail();
  65. }
  66. }
  67. void
  68. AFXAPI DDV_MinMaxChars(
  69. IN CDataExchange * pDX,
  70. IN CString const & value,
  71. IN int nMinChars,
  72. IN int nMaxChars
  73. )
  74. /*++
  75. Routine Description:
  76. Validate CString using a minimum and maximum string length.
  77. Arguments:
  78. CDataExchange * pDX : Data exchange structure
  79. CString const & value : String to be validated
  80. int nMinChars : Minimum length of string
  81. int nMaxChars : Maximum length of string
  82. Return Value:
  83. None
  84. --*/
  85. {
  86. if (pDX->m_bSaveAndValidate)
  87. {
  88. UINT nID;
  89. TCHAR szT[NUMERIC_BUFF_SIZE + 1];
  90. if (value.GetLength() < nMinChars)
  91. {
  92. nID = IDS_DDX_MINIMUM;
  93. ::wsprintf(szT, _T("%d"), nMinChars);
  94. }
  95. else if (value.GetLength() > nMaxChars)
  96. {
  97. nID = AFX_IDP_PARSE_STRING_SIZE;
  98. ::wsprintf(szT, _T("%d"), nMaxChars);
  99. }
  100. else
  101. {
  102. //
  103. // Passes both our tests, it's ok.
  104. //
  105. return;
  106. }
  107. CString prompt;
  108. ::AfxFormatString1(prompt, nID, szT);
  109. ::AfxMessageBox(prompt, MB_ICONEXCLAMATION, nID);
  110. //
  111. // exception prep
  112. //
  113. prompt.Empty();
  114. pDX->Fail();
  115. }
  116. else if (pDX->m_hWndLastControl != NULL && pDX->m_bEditLastControl)
  117. {
  118. //
  119. // limit the control max-chars automatically
  120. //
  121. ::SendMessage(pDX->m_hWndLastControl, EM_LIMITTEXT, nMaxChars, 0);
  122. }
  123. }
  124. void
  125. AFXAPI DDX_Spin(
  126. IN CDataExchange * pDX,
  127. IN int nIDC,
  128. IN OUT int & value
  129. )
  130. /*++
  131. Routine Description:
  132. Save/store data from spinbutton control
  133. Arguments:
  134. CDataExchange * pDX : Data exchange structure
  135. int nIDC : Control ID of the spinbutton control
  136. int & value : Value to be saved or stored
  137. Return Value:
  138. None
  139. --*/
  140. {
  141. HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
  142. if (pDX->m_bSaveAndValidate)
  143. {
  144. value = (int)LOWORD(::SendMessage(hWndCtrl, UDM_GETPOS, 0, 0L));
  145. }
  146. else
  147. {
  148. ::SendMessage(hWndCtrl, UDM_SETPOS, 0, MAKELPARAM(value, 0));
  149. }
  150. }
  151. void
  152. AFXAPI DDV_MinMaxSpin(
  153. IN CDataExchange * pDX,
  154. IN HWND hWndControl,
  155. IN int minVal,
  156. IN int maxVal
  157. )
  158. /*++
  159. Routine Description:
  160. Enforce minimum/maximum spin button range
  161. Arguments:
  162. CDataExchange * pDX : Data exchange structure
  163. HWND hWndControl : Control window handle
  164. int minVal : Minimum value
  165. int maxVal : Maximum value
  166. Return Value:
  167. None
  168. Note:
  169. Unlike most data validation routines, this one
  170. MUST be used prior to an accompanying DDX_Spin()
  171. function. This is because spinbox controls have a
  172. native limit of 0-100. Also, this function requires
  173. a window handle to the child control. The
  174. CONTROL_HWND macro can be used for this.
  175. --*/
  176. {
  177. ASSERT(minVal <= maxVal);
  178. if (!pDX->m_bSaveAndValidate && hWndControl != NULL)
  179. {
  180. //
  181. // limit the control range automatically
  182. //
  183. ::SendMessage(hWndControl, UDM_SETRANGE, 0, MAKELPARAM(maxVal, minVal));
  184. }
  185. }
  186. void
  187. AFXAPI DDX_Password(
  188. IN CDataExchange * pDX,
  189. IN int nIDC,
  190. IN OUT CString & value,
  191. IN LPCTSTR lpszDummy
  192. )
  193. /*++
  194. Routine Description:
  195. DDX_Text for passwords. Always display a dummy string
  196. instead of the real password, and ask for confirmation
  197. if the password has changed
  198. Arguments:
  199. CDataExchange * pDX : Data exchange structure
  200. int nIDC : Control ID
  201. CString & value : value
  202. LPCTSTR lpszDummy : Dummy password string to be displayed
  203. Return Value:
  204. None
  205. --*/
  206. {
  207. HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
  208. if (pDX->m_bSaveAndValidate)
  209. {
  210. if (!::SendMessage(hWndCtrl, EM_GETMODIFY, 0, 0))
  211. {
  212. TRACEEOLID("No changes -- skipping");
  213. return;
  214. }
  215. CString strNew;
  216. int nLen = ::GetWindowTextLength(hWndCtrl);
  217. ::GetWindowText(hWndCtrl, strNew.GetBufferSetLength(nLen), nLen + 1);
  218. strNew.ReleaseBuffer();
  219. /*
  220. if (strNew == value)
  221. {
  222. TRACEEOLID("Password already matches -- skipping");
  223. return;
  224. }
  225. */
  226. //
  227. // Password has changed -- ask for confirmation
  228. //
  229. HINSTANCE hOld = AfxGetResourceHandle();
  230. AfxSetResourceHandle(hDLLInstance);
  231. CConfirmDlg dlg;
  232. if (dlg.DoModal() == IDOK)
  233. {
  234. if (strNew.Compare(dlg.GetPassword()) == 0)
  235. {
  236. //
  237. // Password ok, pass it on
  238. //
  239. value = strNew;
  240. return;
  241. }
  242. else
  243. {
  244. //
  245. // No match, bad password
  246. //
  247. ::AfxMessageBox(IDS_PASSWORD_NO_MATCH);
  248. }
  249. }
  250. AfxSetResourceHandle(hOld);
  251. //
  252. // throw exception
  253. //
  254. pDX->Fail();
  255. }
  256. else
  257. {
  258. //
  259. // Put the dummy password string in the edit control
  260. //
  261. if (!value.IsEmpty())
  262. {
  263. ::AfxSetWindowText(hWndCtrl, lpszDummy);
  264. }
  265. }
  266. }
  267. void
  268. AFXAPI DDX_Text(
  269. IN CDataExchange * pDX,
  270. IN int nIDC,
  271. IN OUT CILong & value
  272. )
  273. /*++
  274. Routine Description:
  275. DDX_Text for CILong class. CILong takes care of all the dirty
  276. work for output and input.
  277. Arguments:
  278. CDataExchange * pDX : Data exchange structure
  279. int nIDC : Control ID code
  280. CILong & value : value
  281. Return Value:
  282. None
  283. --*/
  284. {
  285. HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
  286. pDX->m_bEditLastControl = TRUE;
  287. TCHAR szT[NUMERIC_BUFF_SIZE + 1];
  288. if (pDX->m_bSaveAndValidate)
  289. {
  290. LONG l;
  291. ::GetWindowText(hWndCtrl, szT, NUMERIC_BUFF_SIZE);
  292. if (CINumber::ConvertStringToLong(szT, l))
  293. {
  294. value = l;
  295. }
  296. else
  297. {
  298. HINSTANCE hOld = AfxGetResourceHandle();
  299. AfxSetResourceHandle(hDLLInstance);
  300. ::AfxMessageBox(IDS_INVALID_NUMBER);
  301. AfxSetResourceHandle(hOld);
  302. //
  303. // Throw exception
  304. //
  305. pDX->Fail();
  306. }
  307. }
  308. else
  309. {
  310. ::wsprintf(szT, _T("%s"), (LPCTSTR)value);
  311. ::AfxSetWindowText(hWndCtrl, szT);
  312. }
  313. }
  314. CConfirmDlg::CConfirmDlg(
  315. IN CWnd * pParent OPTIONAL
  316. )
  317. /*++
  318. Routine Description:
  319. Constructor for the confirmation dialog -- brought up by the password ddx
  320. whenever password confirmation is necessary.
  321. Arguments:
  322. CWnd * pParent : Optional parent window
  323. Return Value:
  324. None
  325. --*/
  326. : CDialog(CConfirmDlg::IDD, pParent)
  327. {
  328. //{{AFX_DATA_INIT(CConfirmDlg)
  329. m_strPassword = _T("");
  330. //}}AFX_DATA_INIT
  331. }
  332. void
  333. CConfirmDlg::DoDataExchange(
  334. IN CDataExchange * pDX
  335. )
  336. /*++
  337. Routine Description:
  338. Initialise/Store control data
  339. Arguments:
  340. CDataExchange* pDX - DDX/DDV control structure
  341. Return Value:
  342. N/A
  343. --*/
  344. {
  345. CDialog::DoDataExchange(pDX);
  346. //{{AFX_DATA_MAP(CConfirmDlg)
  347. DDX_Text(pDX, IDC_EDIT_CONFIRM_PASSWORD, m_strPassword);
  348. //}}AFX_DATA_MAP
  349. }
  350. //
  351. // Message Handlers
  352. //
  353. BEGIN_MESSAGE_MAP(CConfirmDlg, CDialog)
  354. //{{AFX_MSG_MAP(CConfirmDlg)
  355. //}}AFX_MSG_MAP
  356. END_MESSAGE_MAP()