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.

296 lines
7.0 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // DDxDDv.cpp
  7. //
  8. // Description:
  9. // Implementation of custom dialog data exchange/dialog data validation
  10. // routines.
  11. //
  12. // Author:
  13. // David Potter (DavidP) March 24, 1999
  14. //
  15. // Revision History:
  16. //
  17. // Notes:
  18. // The IDS_REQUIRED_FIELD_EMPTY string resource must be defined in
  19. // the resource file.
  20. //
  21. /////////////////////////////////////////////////////////////////////////////
  22. #include "stdafx.h"
  23. #include "DDxDDv.h"
  24. #include "resource.h"
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30. /////////////////////////////////////////////////////////////////////////////
  31. //++
  32. //
  33. // DDX_Number
  34. //
  35. // Description:
  36. // Do data exchange between the dialog and the class.
  37. //
  38. // Arguments:
  39. // pDX [IN OUT] Data exchange object
  40. // nIDC [IN] Control ID.
  41. // dwValue [IN OUT] Value to set or get.
  42. // dwMin [IN] Minimum value.
  43. // dwMax [IN] Maximum value.
  44. // bSigned [IN] TRUE = value is signed, FALSE = value is unsigned
  45. //
  46. // Return Value:
  47. // None.
  48. //
  49. //--
  50. /////////////////////////////////////////////////////////////////////////////
  51. void AFXAPI DDX_Number(
  52. IN OUT CDataExchange * pDX,
  53. IN int nIDC,
  54. IN OUT DWORD & rdwValue,
  55. IN DWORD dwMin,
  56. IN DWORD dwMax,
  57. IN BOOL bSigned
  58. )
  59. {
  60. HWND hwndCtrl;
  61. DWORD dwValue;
  62. ASSERT( pDX != NULL );
  63. #ifdef _DEBUG
  64. if ( bSigned )
  65. {
  66. ASSERT( static_cast< LONG >( dwMin ) < static_cast< LONG >( dwMax ) );
  67. }
  68. else
  69. {
  70. ASSERT( dwMin < dwMax );
  71. }
  72. #endif // _DEBUG
  73. AFX_MANAGE_STATE( AfxGetStaticModuleState() );
  74. // Get the control window handle.
  75. hwndCtrl = pDX->PrepareEditCtrl( nIDC );
  76. if ( pDX->m_bSaveAndValidate )
  77. {
  78. BOOL bTranslated;
  79. // Get the number from the control.
  80. dwValue = GetDlgItemInt( pDX->m_pDlgWnd->m_hWnd, nIDC, &bTranslated, bSigned );
  81. // If the retrival failed, it is a signed number, and the minimum
  82. // value is the smallest negative value possible, check the string itself.
  83. if ( ! bTranslated && bSigned && (dwMin == 0x80000000) )
  84. {
  85. UINT cch;
  86. TCHAR szNumber[ 20 ];
  87. // See if it is the smallest negative number.
  88. cch = GetDlgItemText( pDX->m_pDlgWnd->m_hWnd, nIDC, szNumber, sizeof( szNumber ) / sizeof( TCHAR ) );
  89. if ( (cch != 0) && (lstrcmp( szNumber, _T("-2147483648") ) == 0) )
  90. {
  91. dwValue = 0x80000000;
  92. bTranslated = TRUE;
  93. } // if: text retrieved successfully and is highest negative number
  94. } // if: error translating number and getting signed number
  95. // If the retrieval failed or the specified number is
  96. // out of range, display an error.
  97. if ( ! bTranslated
  98. || (bSigned
  99. && ( (static_cast< LONG >( dwValue ) < static_cast< LONG >( dwMin ))
  100. || (static_cast< LONG >( dwValue ) > static_cast< LONG >( dwMax ))
  101. )
  102. )
  103. || (! bSigned
  104. && ( (dwValue < dwMin)
  105. || (dwValue > dwMax)
  106. )
  107. )
  108. )
  109. {
  110. TCHAR szMin[ 32 ];
  111. TCHAR szMax[ 32 ];
  112. CString strPrompt;
  113. if ( bSigned )
  114. {
  115. wsprintf( szMin, _T("%d%"), dwMin );
  116. wsprintf( szMax, _T("%d%"), dwMax );
  117. } // if: signed number
  118. else
  119. {
  120. wsprintf( szMin, _T("%u%"), dwMin );
  121. wsprintf( szMax, _T("%u%"), dwMax );
  122. } // else: unsigned number
  123. AfxFormatString2( strPrompt, AFX_IDP_PARSE_INT_RANGE, szMin, szMax );
  124. AfxMessageBox( strPrompt, MB_ICONEXCLAMATION, AFX_IDP_PARSE_INT_RANGE );
  125. strPrompt.Empty(); // exception prep
  126. pDX->Fail();
  127. } // if: invalid string
  128. else
  129. {
  130. rdwValue = dwValue;
  131. } // if: number is in range
  132. } // if: saving data
  133. else
  134. {
  135. CString strMinValue;
  136. CString strMaxValue;
  137. UINT cchMax;
  138. // Set the maximum number of characters that can be entered.
  139. if ( bSigned )
  140. {
  141. strMinValue.Format( _T("%d"), dwMin );
  142. strMaxValue.Format( _T("%d"), dwMax );
  143. } // if: signed value
  144. else
  145. {
  146. strMinValue.Format( _T("%u"), dwMin );
  147. strMaxValue.Format( _T("%u"), dwMax );
  148. } // else: unsigned value
  149. cchMax = max( strMinValue.GetLength(), strMaxValue.GetLength() );
  150. SendMessage( hwndCtrl, EM_LIMITTEXT, cchMax, 0 );
  151. // Set the value into the control.
  152. if ( bSigned )
  153. {
  154. LONG lValue = static_cast< LONG >( rdwValue );
  155. DDX_Text( pDX, nIDC, lValue );
  156. } // if: signed value
  157. else
  158. DDX_Text( pDX, nIDC, rdwValue );
  159. } // else: setting data onto the dialog
  160. } //*** DDX_Number()
  161. /////////////////////////////////////////////////////////////////////////////
  162. //++
  163. //
  164. // DDV_RequiredText
  165. //
  166. // Description:
  167. // Validate that the dialog string is present.
  168. //
  169. // Arguments:
  170. // pDX [IN OUT] Data exchange object
  171. // nIDC [IN] Control ID.
  172. // nIDCLabel [IN] Label control ID.
  173. // rstrValue [IN] Value to set or get.
  174. //
  175. // Return Value:
  176. // None.
  177. //
  178. //--
  179. /////////////////////////////////////////////////////////////////////////////
  180. void AFXAPI DDV_RequiredText(
  181. IN OUT CDataExchange * pDX,
  182. IN int nIDC,
  183. IN int nIDCLabel,
  184. IN const CString & rstrValue
  185. )
  186. {
  187. ASSERT( pDX != NULL );
  188. AFX_MANAGE_STATE( AfxGetStaticModuleState() );
  189. if ( pDX->m_bSaveAndValidate )
  190. {
  191. if ( rstrValue.GetLength() == 0 )
  192. {
  193. HWND hwndLabel;
  194. TCHAR szLabel[ 1024 ];
  195. CString strPrompt;
  196. // Get the label window handle
  197. hwndLabel = pDX->PrepareEditCtrl( nIDCLabel );
  198. // Get the text of the label.
  199. GetWindowText( hwndLabel, szLabel, sizeof( szLabel ) / sizeof( TCHAR ) );
  200. // Remove ampersands (&) and colons (:).
  201. CleanupLabel( szLabel );
  202. // Format and display a message.
  203. strPrompt.FormatMessage( IDS_REQUIRED_FIELD_EMPTY, szLabel );
  204. AfxMessageBox( strPrompt, MB_ICONEXCLAMATION );
  205. // Do this so that the control receives focus.
  206. (void) pDX->PrepareEditCtrl( nIDC );
  207. // Fail the call.
  208. strPrompt.Empty(); // exception prep
  209. pDX->Fail();
  210. } // if: field not specified
  211. } // if: saving data
  212. } //*** DDV_RequiredText()
  213. /////////////////////////////////////////////////////////////////////////////
  214. //++
  215. //
  216. // CleanupLabel
  217. //
  218. // Description:
  219. // Prepare a label read from a dialog to be used as a string in a
  220. // message by removing ampersands (&) and colons (:).
  221. //
  222. // Arguments:
  223. // pszLabel [IN OUT] Label to be cleaned up.
  224. //
  225. // Return Value:
  226. // None.
  227. //
  228. //--
  229. /////////////////////////////////////////////////////////////////////////////
  230. void CleanupLabel( LPTSTR pszLabel )
  231. {
  232. LPTSTR pIn, pOut;
  233. LANGID langid;
  234. WORD primarylangid;
  235. BOOL bFELanguage;
  236. // Get the language ID.
  237. langid = GetUserDefaultLangID();
  238. primarylangid = static_cast< WORD >( PRIMARYLANGID( langid ) );
  239. bFELanguage = ((primarylangid == LANG_JAPANESE)
  240. || (primarylangid == LANG_CHINESE)
  241. || (primarylangid == LANG_KOREAN) );
  242. //
  243. // Copy the name sans '&' and ':' chars
  244. //
  245. pIn = pOut = pszLabel;
  246. do
  247. {
  248. //
  249. // Strip FE accelerators with parentheses. e.g. "foo(&F)" -> "foo"
  250. //
  251. if ( bFELanguage
  252. && (pIn[ 0 ] == _T('('))
  253. && (pIn[ 1 ] == _T('&'))
  254. && (pIn[ 2 ] != _T('\0'))
  255. && (pIn[ 3 ] == _T(')')) )
  256. {
  257. pIn += 3;
  258. } // if: Far East language with accelerator
  259. else if ( (*pIn != _T('&')) && (*pIn != _T(':')) )
  260. {
  261. *pOut++ = *pIn;
  262. } // else if: accelerator found
  263. } while ( *pIn++ != _T('\0') );
  264. } //*** CleanupLabel()