CEditを継承したクラスを作成する
ナビゲーションに移動
検索に移動
エディットコントロールで入力制限を行う
CEditを継承したクラスを作成し、OnChar関数をオーバーライドする。
CNumericEdit.h
#pragma once
class CNumericEdit : public CEdit
{
DECLARE_DYNAMIC(CNumericEdit)
public:
CNumericEdit();
virtual ~CNumericEdit();
void SetRoundPlaceValue(const int RoundPlaceValue)
{
m_iRoundPlaceValue = RoundPlaceValue;
}
int GetRoundPlaceValue() const
{
return m_iRoundPlaceValue;
}
protected:
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
CString m_strDelim;
int m_iRoundPlaceValue;
DECLARE_MESSAGE_MAP()
};
#include "stdafx.h"
#include "CNumericEdit.h"
IMPLEMENT_DYNAMIC(CNumericEdit, CEdit)
CNumericEdit::CNumericEdit()
{
// determine the decimal delimiter buffer size
const int nBuffLen = ::GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, NULL, 0 );
_ASSERT( nBuffLen > 0 );
// get the decimal number delimiter
const int nResult = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, m_strDelim.GetBuffer(nBuffLen), nBuffLen);
_ASSERT(nResult != 0);
m_strDelim.ReleaseBuffer();
}
CNumericEdit::~CNumericEdit()
{
}
BEGIN_MESSAGE_MAP(CNumericEdit, CEdit)
ON_WM_CHAR()
END_MESSAGE_MAP()
void CNumericEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CString strText;
GetWindowText(strText);
int iStart, iEnd;
GetSel(iStart, iEnd);
// 小数点が入力された場合
if(nChar == m_strDelim)
{
// 空欄の場合は小数点の入力を許可しない
if(strText.IsEmpty())
{
return;
}
else
{ // 小数点が既に入力されている場合は入力を許可しない
if (strText.Find(m_strDelim) >= 0)
return;
}
}
if(nChar == '-')
{ // マイナスを入力できるのは空欄の時のみ
if (!strText.IsEmpty())
{
return;
}
}
// 小数点以下の入力文字数を制限
if(nChar >= '0' && nChar <= '9' && strText.Find(m_strDelim) != -1)
{
int iLength = strText.GetLength();
int iRoundPlaceValue = strText.Find(m_strDelim);
if(iStart == iEnd)
{
if(iStart > iRoundPlaceValue && (iLength - iRoundPlaceValue) > m_iRoundPlaceValue)
{
return;
}
}
}
if((nChar >= '0' && nChar <= '9') || (nChar == m_strDelim) || (nChar == '-') || (nChar == '\b'))
{
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
}
ダイアログから値を取得する
下記のように、ダイアログを起動して入力された値を取得するときは注意が必要である。
DoModal()関数がIDOKを返した時点で、ダイアログ内のコントロールが破棄されてしまうため、値を取得する事ができない。
この場合、メンバにCString型の変数を定義し、DDX_Textで値を更新する。
CMyDialog dlg;
if(dlg.DoModal() == IDOK)
{
// この時点で CMyDialog 内のコントロールは消滅する
CString strText;
dlg.m_editValue.GetWindowText(strText); // アサーションエラー
}
入力値の制限と値取得を同時に行う
CEdit型とCString型の変数を定義し、DoDataExchange内に、DDXControlとDDXTEXTを追加する。
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
// 入力値の制限,OnChar()をオーバーライドしたクラス
DDX_Control(pDX, IDC_EDIT_VALUE, m_editValue);
// ダイアログ消滅後の値取得用
DDX_Text(pDX, IDC_EDIT_VALUE, m_strValue);
}
入力値の範囲をチェックする
ダイアログデータバリデーション(DDV)を使用する。
DoDataExchange()内に下記のように関数を追加する。
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
// 入力値の制限,OnChar をオーバーライドしたクラス
DDX_Control(pDX, IDC_EDIT_VALUE, m_editValue);
// ダイアログ消滅後の値取得用
DDX_Text(pDX, IDC_EDIT_VALUE, m_strValue);
// 入力値の範囲確認
// 他の型用の DDV も標準であります
DDV_MinMaxDouble(pDX, atof(m_strValue), 0.0, 1.0);
}
複数のエディットコントロール間で有効性を確認する
2つのエディットコントロール間の関係性から、データの有効性を決めたいことがある。
例えば、ユーザに上限値と下限値を入力してもらう場合、上限値は下限値より大きくなければいけない。
そこで、データが有効か確認するための独自関数を作成する。
void DDV_CheckLowerUpper(CDataExchange* pDX, double lower, double upper)
{
if(lower > upper)
{
AfxMessageBox(_T("下限値には上限値より小さい数値を入力してください."), MB_ICONWARNING);
pDX->Fail();
}
}
上記の関数を、DoDataExchange()内に追記する。
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
// 入力値の制限,OnChar をオーバーライドしたクラス
DDX_Control(pDX, IDC_EDIT_LOWER_VALUE, m_editLower);
DDX_Control(pDX, IDC_EDIT_UPPER_VALUE, m_editUpper);
// ダイアログ消滅後の値取得用
DDX_Text(pDX, IDC_EDIT_LOWER_VALUE, m_strLower);
DDX_Text(pDX, IDC_EDIT_UPPER_VALUE, m_strUpper);
// 入力値の範囲確認
// 他の型用のDDVも標準で存在する
DDV_MinMaxDouble(pDX, atof(m_strLower), 0.0, 1.0);
DDV_MinMaxDouble(pDX, atof(m_strUpper), 0.0, 1.0);
// 下限値と上限値が入力されている場合は 下限値 < 上限値 であるかチェックする
if(!m_strLower.IsEmpty() && !m_strUpper.IsEmpty())
{
DDV_CheckLowerUpper(pDX, atof(m_strLower), atof(m_strUpper));
}
}