「CEditを継承したクラスを作成する」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
(文字列「<source lang」を「<syntaxhighlight lang」に置換)
2行目: 2行目:
CEditを継承したクラスを作成し、OnChar関数をオーバーライドする。
CEditを継承したクラスを作成し、OnChar関数をオーバーライドする。


  <source lang="c++">
  <syntaxhighlight lang="c++">
  CNumericEdit.h
  CNumericEdit.h
   
   
35行目: 35行目:
  </source>
  </source>
<br>
<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  #include "stdafx.h"
  #include "stdafx.h"
  #include "CNumericEdit.h"
  #include "CNumericEdit.h"
119行目: 119行目:
DoModal()関数がIDOKを返した時点で、ダイアログ内のコントロールが破棄されてしまうため、値を取得する事ができない。<br>
DoModal()関数がIDOKを返した時点で、ダイアログ内のコントロールが破棄されてしまうため、値を取得する事ができない。<br>
この場合、メンバにCString型の変数を定義し、DDX_Textで値を更新する。<br>
この場合、メンバにCString型の変数を定義し、DDX_Textで値を更新する。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  CMyDialog dlg;
  CMyDialog dlg;
   
   
133行目: 133行目:
== 入力値の制限と値取得を同時に行う ==
== 入力値の制限と値取得を同時に行う ==
CEdit型とCString型の変数を定義し、DoDataExchange内に、DDXControlとDDXTEXTを追加する。
CEdit型とCString型の変数を定義し、DoDataExchange内に、DDXControlとDDXTEXTを追加する。
  <source lang="c++">
  <syntaxhighlight lang="c++">
  void CMyDialog::DoDataExchange(CDataExchange* pDX)
  void CMyDialog::DoDataExchange(CDataExchange* pDX)
  {
  {
150行目: 150行目:
ダイアログデータバリデーション(DDV)を使用する。<br>
ダイアログデータバリデーション(DDV)を使用する。<br>
DoDataExchange()内に下記のように関数を追加する。<br>
DoDataExchange()内に下記のように関数を追加する。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  void CMyDialog::DoDataExchange(CDataExchange* pDX)
  void CMyDialog::DoDataExchange(CDataExchange* pDX)
  {
  {
173行目: 173行目:
そこで、データが有効か確認するための独自関数を作成する。<br>
そこで、データが有効か確認するための独自関数を作成する。<br>
<br>
<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  void DDV_CheckLowerUpper(CDataExchange* pDX, double lower, double upper)
  void DDV_CheckLowerUpper(CDataExchange* pDX, double lower, double upper)
  {
  {
184行目: 184行目:
  </source>
  </source>
上記の関数を、DoDataExchange()内に追記する。<br>
上記の関数を、DoDataExchange()内に追記する。<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  void CMyDialog::DoDataExchange(CDataExchange* pDX)
  void CMyDialog::DoDataExchange(CDataExchange* pDX)
  {
  {

2021年11月15日 (月) 00:33時点における版

エディットコントロールで入力制限を行う

CEditを継承したクラスを作成し、OnChar関数をオーバーライドする。

<syntaxhighlight lang="c++">
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()
};
</source>


<syntaxhighlight lang="c++">
#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);
   }
}
</source>



ダイアログから値を取得する

下記のように、ダイアログを起動して入力された値を取得するときは注意が必要である。
DoModal()関数がIDOKを返した時点で、ダイアログ内のコントロールが破棄されてしまうため、値を取得する事ができない。
この場合、メンバにCString型の変数を定義し、DDX_Textで値を更新する。

<syntaxhighlight lang="c++">
CMyDialog dlg;

if(dlg.DoModal() == IDOK)
{
   // この時点で CMyDialog 内のコントロールは消滅する
   CString strText;
   dlg.m_editValue.GetWindowText(strText); // アサーションエラー
}
</source>



入力値の制限と値取得を同時に行う

CEdit型とCString型の変数を定義し、DoDataExchange内に、DDXControlとDDXTEXTを追加する。

<syntaxhighlight lang="c++">
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);
}
</source>



入力値の範囲をチェックする

ダイアログデータバリデーション(DDV)を使用する。
DoDataExchange()内に下記のように関数を追加する。

<syntaxhighlight lang="c++">
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);
}
</source>



複数のエディットコントロール間で有効性を確認する

2つのエディットコントロール間の関係性から、データの有効性を決めたいことがある。
例えば、ユーザに上限値と下限値を入力してもらう場合、上限値は下限値より大きくなければいけない。
そこで、データが有効か確認するための独自関数を作成する。

<syntaxhighlight lang="c++">
void DDV_CheckLowerUpper(CDataExchange* pDX, double lower, double upper)
{
   if(lower > upper)
   {
      AfxMessageBox(_T("下限値には上限値より小さい数値を入力してください."), MB_ICONWARNING);
      pDX->Fail();
   }
}
</source>

上記の関数を、DoDataExchange()内に追記する。

<syntaxhighlight lang="c++">
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));
   }
}
</source>