Событие числовой проверки CEdit C++ MFC

У меня есть текстовое поле CEdit, которое является частью панели свойств и допускает только числовые значения (положительные целые числа). Поле работает нормально, когда люди вводят нечисловые значения, но когда они удаляют значение в поле, появляется диалоговое окно с сообщением: «Пожалуйста, введите положительное целое число».

Вот ситуация:
1. У меня есть число (скажем, 20) в поле.
2. Я удаляю число.
3. Я получаю диалоговое окно с ошибкой.
Кто-нибудь может мне сказать как я могу перехватить это событие и поместить туда значение по умолчанию?

Вот как выглядит моя панель свойств:


const int DEFAULT_VALUE = 20;

class MyPropertyPane:public CPropertyPane
{
    //....
private:
    CEdit m_NumericBox;
    int   m_value;

    //....
public:
    afx_msg void OnEnChangeNumericBox();

    //....
}
void MyPropertyPane::MyPropertyPane()
{
   // Set a default value
   m_value = DEFAULT_VALUE;
}

//....
void MyPropertyPane::DoDataExchange(CDataExchange* pDX)
{
    DDX_Control(pDX, IDC_NUMERIC_BOX, m_NumericBox);

    // this sets the displayed value to 20
    DDX_Text(pDX, IDC_NUMERIC_BOX, m_value);
}

//....
void MyPropertyPane::OnEnChangeNumericBox()
{
    // Somebody deleted the value in the box and I got an event
    // saying that the value is changed.

    // I try to get the value from the box by updating my data
    UpdateData(TRUE);

    // m_value is still 20 although the value is 
    // deleted inside the text box.
}


person Kiril    schedule 13.04.2009    source источник


Ответы (3)


Сообщение, которое вы получаете, исходит от процедур проверки данных, а не от процедур обмена данными. Вероятно, в DoDataExchange() есть такой вызов:

void MyPropertyPane::DoDataExchange(CDataExchange* pDX)
{
    DDX_Control(pDX, IDC_NUMERIC_BOX, m_NumericBox);
    DDX_Text(pDX, IDC_NUMERIC_BOX, m_value);
    DDV_MinMaxInt(pDX, m_value, 1, 20); // if the value in m_value is outside the range 1-20, MFC will pop up an error dialog
}

Вы можете решить эту проблему, удалив встроенную проверку данных MFC и добавив свою собственную:

void MyPropertyPane::DoDataExchange(CDataExchange* pDX)
{
    DDX_Control(pDX, IDC_NUMERIC_BOX, m_NumericBox);
    DDX_Text(pDX, IDC_NUMERIC_BOX, m_value);

    if( m_value < 1 || m_value > 20 )
    {
        m_value = DefaultValue;
    }
}
person John Dibling    schedule 13.04.2009
comment
Но m_value по-прежнему равно 20 даже после того, как оно было удалено... поэтому проверка, если m_value ‹ 1, вернет false, а m_value не будет установлено в DEFAULT_VALUE. Всплывающая ошибка Введите положительное целое число перед событием OnChange. - person Kiril; 13.04.2009
comment
На самом деле исправление ... в DoDataExchange он даже не проходит мимо DDX_Text (pDX, IDC_NUMERIC_BOX, m_value), поэтому он даже не попадет в код проверки. - person Kiril; 13.04.2009

Подсказка Джона Диблинга привела меня к такому решению:


void MyPropertyPane::OnEnChangeNumericBox()
{
    UpdateData(TRUE);
    CString value;
    m_NumericBox.GetWindowText(value);
    if( value.IsEmpty() )
    {
        m_value = DEFAULT_VALUE;
        UpdateData(FALSE);
    }
}

ЕДИНСТВЕННАЯ проверка, которую мне действительно нужно было сделать, - это проверить, что поле содержит значение, поскольку фактическая числовая проверка уже обрабатывается полем. Пользователь не может ввести нечисловое значение, но он может удалить существующее, так что это была ситуация, которую было трудно обработать в функции обмена данными, и мне пришлось «взломать» событие OnChange.

person Kiril    schedule 13.04.2009
comment
Это работает во многих случаях, но часто лучше всего выполнять весь обмен данными и проверку с помощью функции DoDataExchange(), поскольку OnEnChangeNumericBox() может быть не единственным местом, где изменяется m_value. Например, если у вас есть переключатель, который изменяет m_value на предустановленные значения. - person John Dibling; 13.04.2009
comment
Хороший момент, в целом функция DoDataExchange(), вероятно, является лучшим местом для проверки... мой пример является исключением. - person Kiril; 13.04.2009

Это сработало для меня

void CtimersDlg::OnEnChangeInterval()
{
   CString value; //or use char *
   CWnd *pWnd = GetDlgItem(IDC_INTERVAL);//IDC_EDITBOX

   if(pWnd)
   {
      pWnd->GetWindowTextW(value);
   }

   int i = _wtoi(value); //if char * use _atol()
   if((!value.IsEmpty())&& (i))  //To check i = 0 or 00 entered or not
      UpdateData(TRUE);
}
person jsmurthy4    schedule 22.02.2010
comment
Как пользователь может ввести 0? - person sergiol; 10.01.2018