БлогNot. С++/CLI: валидация TextBox и перехват нажатий клавиш формой

С++/CLI: валидация TextBox и перехват нажатий клавиш формой

Представим себе проект Windows Forms с обычным текстовым полем TextBox. Требуется разрешить вводить в поле только определённые данные, скажем, вещественные числа. Как и в QT, мы можем не применять в .NET довольно неуклюжие решения, связанные с проверкой вводимых данных "на лету" при помощи обработки событий нажатия клавиш, а воспользоваться вместо этого событием Validating, позволяющим проверить данные после ввода.

Кстати, при успешном результате проверки после этого происходит ещё и событие Validated, которое тоже можно программировать. Вот простой кусочек кода для Validating:

private: bool ValidNumber(String ^s) {
 if (s->Trim()->Length == 0) return false;
 Double d;
 bool Is_Num = Double::TryParse(textBox1->Text,
  System::Globalization::NumberStyles::Number,
  System::Globalization::NumberFormatInfo::CurrentInfo, d);
 if (!Is_Num) return false;
 return true;
}

private: System::Void textBox1_Validating(System::Object^  sender, 
                      System::ComponentModel::CancelEventArgs^  e) {
 if (!ValidNumber(textBox1->Text)) {
  e->Cancel = true; 
  textBox1->Select(0, textBox1->Text->Length);
 }
}

Что касается второй проблемы, для того, чтобы форма получала все события клавиш, на каком бы активном элементе они не происходили, нужно установить свойство формы KeyPreview = true. Тогда все события сначала будет получать форма, а затем передавать управление событиям, назначенным элементам.

Если нужно, чтобы после обработки события в форме управление не передавалось дальше другим элементам, можно использовать в обработчике формы e->Handled = true; что будет означать, что событие уже обработано и остальные события того же типа, скажем, KeyPress обрабатывать не нужно.

Вот пример кода для события KeyUp формы:

private: System::Void MyForm1_KeyUp(System::Object^  sender, 
                      System::Windows::Forms::KeyEventArgs^  e) {
 int c = e->KeyValue;
 String^ Digit;
 if (c >= (int)Keys::D0 && c <= (int)Keys::D9) 
   Digit = (c - (int)Keys::D0).ToString();
 else if (c == 190) Digit = "."; 
 else if (c == 187) Digit = ",";
 //...и т.д., потом что-то делаем со строкой Digit
 e->Handled = true;
}

Здесь просто примитивно разрешаются нажатия на форме цифровых клавиш, точки и запятой.

В обработчике события от клавиатуры для находящегося в форме textBox1 тоже должно быть e->Handled = true;, чтобы не происходило "дублирования" символов.

private: System::Void textBox1_KeyPress(System::Object^  sender, 
                      System::Windows::Forms::KeyPressEventArgs^  e) {
 e->Handled = true;
}

Ну и, конечно, не смешиваем все способы контроля в одном программном модуле :)


теги: c++ studio программирование

10.09.2019, 17:24; рейтинг: 38