///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1999 - 2002 Microsoft Corporation // // Module Name: // DDxDDv.cpp // // Description: // Implementation of custom dialog data exchange/dialog data validation // routines. // // Author: // David Potter (DavidP) March 24, 1999 // // Maintained by: // George Potts (GPotts) April 19, 2002 // // Revision History: // // Notes: // The IDS_REQUIRED_FIELD_EMPTY string resource must be defined in // the resource file. // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "DDxDDv.h" #include "resource.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// //++ // // DDX_Number // // Description: // Do data exchange between the dialog and the class. // // Arguments: // pDX [IN OUT] Data exchange object // nIDC [IN] Control ID. // dwValue [IN OUT] Value to set or get. // dwMin [IN] Minimum value. // dwMax [IN] Maximum value. // bSigned [IN] TRUE = value is signed, FALSE = value is unsigned // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void AFXAPI DDX_Number( IN OUT CDataExchange * pDX, IN int nIDC, IN OUT DWORD & rdwValue, IN DWORD dwMin, IN DWORD dwMax, IN BOOL bSigned ) { HWND hwndCtrl; DWORD dwValue; HRESULT hr = S_OK; ASSERT( pDX != NULL ); #ifdef _DEBUG if ( bSigned ) { ASSERT( static_cast< LONG >( dwMin ) < static_cast< LONG >( dwMax ) ); } else { ASSERT( dwMin < dwMax ); } #endif // _DEBUG AFX_MANAGE_STATE( AfxGetStaticModuleState() ); // Get the control window handle. hwndCtrl = pDX->PrepareEditCtrl( nIDC ); if ( pDX->m_bSaveAndValidate ) { BOOL bTranslated; // Get the number from the control. dwValue = GetDlgItemInt( pDX->m_pDlgWnd->m_hWnd, nIDC, &bTranslated, bSigned ); // If the retrival failed, it is a signed number, and the minimum // value is the smallest negative value possible, check the string itself. if ( ! bTranslated && bSigned && (dwMin == 0x80000000) ) { UINT cch; TCHAR szNumber[ 20 ]; // See if it is the smallest negative number. cch = GetDlgItemText( pDX->m_pDlgWnd->m_hWnd, nIDC, szNumber, RTL_NUMBER_OF( szNumber ) ); if ( (cch != 0) && (ClRtlStrNICmp( szNumber, _T("-2147483648"), RTL_NUMBER_OF( szNumber ) ) == 0) ) { dwValue = 0x80000000; bTranslated = TRUE; } // if: text retrieved successfully and is highest negative number } // if: error translating number and getting signed number // If the retrieval failed or the specified number is // out of range, display an error. if ( ! bTranslated || (bSigned && ( (static_cast< LONG >( dwValue ) < static_cast< LONG >( dwMin )) || (static_cast< LONG >( dwValue ) > static_cast< LONG >( dwMax )) ) ) || (! bSigned && ( (dwValue < dwMin) || (dwValue > dwMax) ) ) ) { TCHAR szMin[ 32 ]; TCHAR szMax[ 32 ]; CString strPrompt; if ( bSigned ) { hr = StringCchPrintf( szMin, RTL_NUMBER_OF( szMin ), _T("%d%"), dwMin ); hr = StringCchPrintf( szMax, RTL_NUMBER_OF( szMax ), _T("%d%"), dwMax ); } // if: signed number else { hr = StringCchPrintf( szMin, RTL_NUMBER_OF( szMin ), _T("%u%"), dwMin ); hr = StringCchPrintf( szMax, RTL_NUMBER_OF( szMax ), _T("%u%"), dwMax ); } // else: unsigned number AfxFormatString2( strPrompt, AFX_IDP_PARSE_INT_RANGE, szMin, szMax ); AfxMessageBox( strPrompt, MB_ICONEXCLAMATION, AFX_IDP_PARSE_INT_RANGE ); strPrompt.Empty(); // exception prep pDX->Fail(); } // if: invalid string else { rdwValue = dwValue; } // if: number is in range } // if: saving data else { CString strMinValue; CString strMaxValue; UINT cchMax; // Set the maximum number of characters that can be entered. if ( bSigned ) { strMinValue.Format( _T("%d"), dwMin ); strMaxValue.Format( _T("%d"), dwMax ); } // if: signed value else { strMinValue.Format( _T("%u"), dwMin ); strMaxValue.Format( _T("%u"), dwMax ); } // else: unsigned value cchMax = max( strMinValue.GetLength(), strMaxValue.GetLength() ); SendMessage( hwndCtrl, EM_LIMITTEXT, cchMax, 0 ); // Set the value into the control. if ( bSigned ) { LONG lValue = static_cast< LONG >( rdwValue ); DDX_Text( pDX, nIDC, lValue ); } // if: signed value else DDX_Text( pDX, nIDC, rdwValue ); } // else: setting data onto the dialog } //*** DDX_Number() ///////////////////////////////////////////////////////////////////////////// //++ // // DDV_RequiredText // // Description: // Validate that the dialog string is present. // // Arguments: // pDX [IN OUT] Data exchange object // nIDC [IN] Control ID. // nIDCLabel [IN] Label control ID. // rstrValue [IN] Value to set or get. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void AFXAPI DDV_RequiredText( IN OUT CDataExchange * pDX, IN int nIDC, IN int nIDCLabel, IN const CString & rstrValue ) { ASSERT( pDX != NULL ); AFX_MANAGE_STATE( AfxGetStaticModuleState() ); if ( pDX->m_bSaveAndValidate ) { if ( rstrValue.GetLength() == 0 ) { HWND hwndLabel; TCHAR szLabel[ 1024 ]; CString strPrompt; // Get the label window handle hwndLabel = pDX->PrepareEditCtrl( nIDCLabel ); // Get the text of the label. GetWindowText( hwndLabel, szLabel, RTL_NUMBER_OF( szLabel ) ); // Remove ampersands (&) and colons (:). CleanupLabel( szLabel ); // Format and display a message. strPrompt.FormatMessage( IDS_REQUIRED_FIELD_EMPTY, szLabel ); AfxMessageBox( strPrompt, MB_ICONEXCLAMATION ); // Do this so that the control receives focus. (void) pDX->PrepareEditCtrl( nIDC ); // Fail the call. strPrompt.Empty(); // exception prep pDX->Fail(); } // if: field not specified } // if: saving data } //*** DDV_RequiredText() ///////////////////////////////////////////////////////////////////////////// //++ // // CleanupLabel // // Description: // Prepare a label read from a dialog to be used as a string in a // message by removing ampersands (&) and colons (:). // // Arguments: // pszLabel [IN OUT] Label to be cleaned up. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CleanupLabel( LPTSTR pszLabel ) { LPTSTR pIn, pOut; LANGID langid; WORD primarylangid; BOOL bFELanguage; // Get the language ID. langid = GetUserDefaultLangID(); primarylangid = static_cast< WORD >( PRIMARYLANGID( langid ) ); bFELanguage = ((primarylangid == LANG_JAPANESE) || (primarylangid == LANG_CHINESE) || (primarylangid == LANG_KOREAN) ); // // Copy the name sans '&' and ':' chars // pIn = pOut = pszLabel; do { // // Strip FE accelerators with parentheses. e.g. "foo(&F)" -> "foo" // if ( bFELanguage && (pIn[ 0 ] == _T('(')) && (pIn[ 1 ] == _T('&')) && (pIn[ 2 ] != _T('\0')) && (pIn[ 3 ] == _T(')')) ) { pIn += 3; } // if: Far East language with accelerator else if ( (*pIn != _T('&')) && (*pIn != _T(':')) ) { *pOut++ = *pIn; } // else if: accelerator found } while ( *pIn++ != _T('\0') ); } //*** CleanupLabel()