468 lines
8.6 KiB
C++
468 lines
8.6 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1994-1998 Microsoft Corporation
|
||
|
|
||
|
Module Name :
|
||
|
|
||
|
ddxv.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
DDX/DDV Routines
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Ronald Meijer (ronaldm)
|
||
|
|
||
|
Project:
|
||
|
|
||
|
Internet Services Manager
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
//
|
||
|
// Include Files
|
||
|
//
|
||
|
#include "stdafx.h"
|
||
|
#include "comprop.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// Prototype for external function
|
||
|
//
|
||
|
void AFXAPI AfxSetWindowText(HWND hWndCtrl, LPCTSTR lpszNew);
|
||
|
|
||
|
//
|
||
|
// Numeric strings cannot be longer than 32 digits
|
||
|
//
|
||
|
#define NUMERIC_BUFF_SIZE (32)
|
||
|
|
||
|
//
|
||
|
// Dummy password used for display purposes
|
||
|
//
|
||
|
LPCTSTR g_lpszDummyPassword = _T("**********");
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
AFXAPI DDV_MinChars(
|
||
|
IN CDataExchange * pDX,
|
||
|
IN CString const & value,
|
||
|
IN int nChars
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Validate CString using a minimum string length
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CDataExchange * pDX : Data exchange structure
|
||
|
CString const & value : String to be validated
|
||
|
int nChars : Minimum length of string
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
if (pDX->m_bSaveAndValidate && value.GetLength() < nChars)
|
||
|
{
|
||
|
TCHAR szT[NUMERIC_BUFF_SIZE + 1];
|
||
|
wsprintf(szT, _T("%d"), nChars);
|
||
|
CString prompt;
|
||
|
::AfxFormatString1(prompt, IDS_DDX_MINIMUM, szT);
|
||
|
::AfxMessageBox(prompt, MB_ICONEXCLAMATION, IDS_DDX_MINIMUM);
|
||
|
//
|
||
|
// exception prep
|
||
|
//
|
||
|
prompt.Empty();
|
||
|
pDX->Fail();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
AFXAPI DDV_MinMaxChars(
|
||
|
IN CDataExchange * pDX,
|
||
|
IN CString const & value,
|
||
|
IN int nMinChars,
|
||
|
IN int nMaxChars
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Validate CString using a minimum and maximum string length.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CDataExchange * pDX : Data exchange structure
|
||
|
CString const & value : String to be validated
|
||
|
int nMinChars : Minimum length of string
|
||
|
int nMaxChars : Maximum length of string
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
if (pDX->m_bSaveAndValidate)
|
||
|
{
|
||
|
UINT nID;
|
||
|
TCHAR szT[NUMERIC_BUFF_SIZE + 1];
|
||
|
|
||
|
if (value.GetLength() < nMinChars)
|
||
|
{
|
||
|
nID = IDS_DDX_MINIMUM;
|
||
|
::wsprintf(szT, _T("%d"), nMinChars);
|
||
|
}
|
||
|
else if (value.GetLength() > nMaxChars)
|
||
|
{
|
||
|
nID = AFX_IDP_PARSE_STRING_SIZE;
|
||
|
::wsprintf(szT, _T("%d"), nMaxChars);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Passes both our tests, it's ok.
|
||
|
//
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CString prompt;
|
||
|
::AfxFormatString1(prompt, nID, szT);
|
||
|
::AfxMessageBox(prompt, MB_ICONEXCLAMATION, nID);
|
||
|
|
||
|
//
|
||
|
// exception prep
|
||
|
//
|
||
|
prompt.Empty();
|
||
|
|
||
|
pDX->Fail();
|
||
|
}
|
||
|
else if (pDX->m_hWndLastControl != NULL && pDX->m_bEditLastControl)
|
||
|
{
|
||
|
//
|
||
|
// limit the control max-chars automatically
|
||
|
//
|
||
|
::SendMessage(pDX->m_hWndLastControl, EM_LIMITTEXT, nMaxChars, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
AFXAPI DDX_Spin(
|
||
|
IN CDataExchange * pDX,
|
||
|
IN int nIDC,
|
||
|
IN OUT int & value
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Save/store data from spinbutton control
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CDataExchange * pDX : Data exchange structure
|
||
|
int nIDC : Control ID of the spinbutton control
|
||
|
int & value : Value to be saved or stored
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
|
||
|
if (pDX->m_bSaveAndValidate)
|
||
|
{
|
||
|
value = (int)LOWORD(::SendMessage(hWndCtrl, UDM_GETPOS, 0, 0L));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::SendMessage(hWndCtrl, UDM_SETPOS, 0, MAKELPARAM(value, 0));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
AFXAPI DDV_MinMaxSpin(
|
||
|
IN CDataExchange * pDX,
|
||
|
IN HWND hWndControl,
|
||
|
IN int minVal,
|
||
|
IN int maxVal
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Enforce minimum/maximum spin button range
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CDataExchange * pDX : Data exchange structure
|
||
|
HWND hWndControl : Control window handle
|
||
|
int minVal : Minimum value
|
||
|
int maxVal : Maximum value
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
Note:
|
||
|
|
||
|
Unlike most data validation routines, this one
|
||
|
MUST be used prior to an accompanying DDX_Spin()
|
||
|
function. This is because spinbox controls have a
|
||
|
native limit of 0-100. Also, this function requires
|
||
|
a window handle to the child control. The
|
||
|
CONTROL_HWND macro can be used for this.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ASSERT(minVal <= maxVal);
|
||
|
if (!pDX->m_bSaveAndValidate && hWndControl != NULL)
|
||
|
{
|
||
|
//
|
||
|
// limit the control range automatically
|
||
|
//
|
||
|
::SendMessage(hWndControl, UDM_SETRANGE, 0, MAKELPARAM(maxVal, minVal));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
AFXAPI DDX_Password(
|
||
|
IN CDataExchange * pDX,
|
||
|
IN int nIDC,
|
||
|
IN OUT CString & value,
|
||
|
IN LPCTSTR lpszDummy
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
DDX_Text for passwords. Always display a dummy string
|
||
|
instead of the real password, and ask for confirmation
|
||
|
if the password has changed
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CDataExchange * pDX : Data exchange structure
|
||
|
int nIDC : Control ID
|
||
|
CString & value : value
|
||
|
LPCTSTR lpszDummy : Dummy password string to be displayed
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
|
||
|
if (pDX->m_bSaveAndValidate)
|
||
|
{
|
||
|
if (!::SendMessage(hWndCtrl, EM_GETMODIFY, 0, 0))
|
||
|
{
|
||
|
TRACEEOLID("No changes -- skipping");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CString strNew;
|
||
|
int nLen = ::GetWindowTextLength(hWndCtrl);
|
||
|
::GetWindowText(hWndCtrl, strNew.GetBufferSetLength(nLen), nLen + 1);
|
||
|
strNew.ReleaseBuffer();
|
||
|
|
||
|
/*
|
||
|
if (strNew == value)
|
||
|
{
|
||
|
TRACEEOLID("Password already matches -- skipping");
|
||
|
return;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
//
|
||
|
// Password has changed -- ask for confirmation
|
||
|
//
|
||
|
CConfirmDlg dlg;
|
||
|
if (dlg.DoModal() == IDOK)
|
||
|
{
|
||
|
if (strNew.Compare(dlg.GetPassword()) == 0)
|
||
|
{
|
||
|
//
|
||
|
// Password ok, pass it on
|
||
|
//
|
||
|
value = strNew;
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// No match, bad password
|
||
|
//
|
||
|
::AfxMessageBox(IDS_PASSWORD_NO_MATCH);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// throw exception
|
||
|
//
|
||
|
pDX->Fail();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Put the dummy password string in the edit control
|
||
|
//
|
||
|
if (!value.IsEmpty())
|
||
|
{
|
||
|
::AfxSetWindowText(hWndCtrl, lpszDummy);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
AFXAPI DDX_Text(
|
||
|
IN CDataExchange * pDX,
|
||
|
IN int nIDC,
|
||
|
IN OUT CILong & value
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
DDX_Text for CILong class. CILong takes care of all the dirty
|
||
|
work for output and input.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CDataExchange * pDX : Data exchange structure
|
||
|
int nIDC : Control ID code
|
||
|
CILong & value : value
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
|
||
|
pDX->m_bEditLastControl = TRUE;
|
||
|
|
||
|
TCHAR szT[NUMERIC_BUFF_SIZE + 1];
|
||
|
|
||
|
if (pDX->m_bSaveAndValidate)
|
||
|
{
|
||
|
LONG l;
|
||
|
|
||
|
::GetWindowText(hWndCtrl, szT, NUMERIC_BUFF_SIZE);
|
||
|
|
||
|
if (CINumber::ConvertStringToLong(szT, l))
|
||
|
{
|
||
|
value = l;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
HINSTANCE hOld = AfxGetResourceHandle();
|
||
|
AfxSetResourceHandle(GetModuleHandle(COMPROP_DLL_NAME));
|
||
|
|
||
|
::AfxMessageBox(IDS_INVALID_NUMBER);
|
||
|
|
||
|
AfxSetResourceHandle(hOld);
|
||
|
|
||
|
//
|
||
|
// Throw exception
|
||
|
//
|
||
|
pDX->Fail();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::wsprintf(szT, _T("%s"), (LPCTSTR)value);
|
||
|
::AfxSetWindowText(hWndCtrl, szT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
CConfirmDlg::CConfirmDlg(
|
||
|
IN CWnd * pParent OPTIONAL
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Constructor for the confirmation dialog -- brought up by the password ddx
|
||
|
whenever password confirmation is necessary.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CWnd * pParent : Optional parent window
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
: CDialog(CConfirmDlg::IDD, pParent)
|
||
|
{
|
||
|
//{{AFX_DATA_INIT(CConfirmDlg)
|
||
|
m_strPassword = _T("");
|
||
|
//}}AFX_DATA_INIT
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
CConfirmDlg::DoDataExchange(
|
||
|
IN CDataExchange * pDX
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Initialise/Store control data
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CDataExchange* pDX - DDX/DDV control structure
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
N/A
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
CDialog::DoDataExchange(pDX);
|
||
|
//{{AFX_DATA_MAP(CConfirmDlg)
|
||
|
DDX_Text(pDX, IDC_EDIT_CONFIRM_PASSWORD, m_strPassword);
|
||
|
//}}AFX_DATA_MAP
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Message Handlers
|
||
|
//
|
||
|
BEGIN_MESSAGE_MAP(CConfirmDlg, CDialog)
|
||
|
//{{AFX_MSG_MAP(CConfirmDlg)
|
||
|
//}}AFX_MSG_MAP
|
||
|
END_MESSAGE_MAP()
|