175 / 65 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
1

Как не допустить в ячейку TDrawGrid повторного ввода десятичного разделителя?

09.12.2020, 12:47. Показов 1317. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Окно ячейки Gridа предназначено для ввода вещественных чисел. Если нечаянно поставить ещё одну точку(запятую) - вываливается ошибка с предложением остановить выполнение программы.
То же самое произойдёт если поставить второй минус или поставить минус не первым символом.
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
procedure TDrawGrid.KeyPress(var Key: char);
begin
    inherited KeyPress(Key);  
    Case Key of
        '0'..'9' : exit;   // Действие по-умолчанию (ввод цифры от 0 до 9)
        #8      : exit;   // Действие по-умолчанию (BACKSPACE)
        '.',','  : begin   // Точку или запятую заменяем десятичным разделителем, проверив что он в числе единственный
                      Key:= DecimalSeparator;
                   end;
        else   Key:=#0;
    end;
end;
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.12.2020, 12:47
Ответы с готовыми решениями:

Как определить символ десятичного разделителя?
Подскажите, пожалуйста, как можно определить в программе какой символ является десятичным...

Как временно изменить значение десятичного разделителя в системе?
1. Сохранить текущий десятичный разделитель существующий в системе в настоящее время 2. Подменить...

Как получить знак десятичного разделителя для текущей культуры
Как получить знак десятичного разделителя для текущей культуры? Добавлено через 27 минут Ответ:...

Как преобразовать строку в число без учёта десятичного разделителя?
В системе установлен десятичный разделитель <запятая>. В строке сформировано число 2,5...

16
Почетный модератор
64288 / 47587 / 32739
Регистрация: 18.05.2008
Сообщений: 115,182
09.12.2020, 12:55 2
Лучше не делать этот костыль который все равно обойдет тот кому это нужно, лучше проверять числа в гриде при чтении и если не верно введено, поправлять.
Типа так
Pascal
1
2
3
4
5
6
7
for i:=0 to m-1 do
for j:=0 to n-1 do
if not TryStrToFloat(DrawGrid1.Cells[j,i],a[i,j]) then
 begin
  ShowMessage('В ячейке ['+inttostr(i)+','+inttostr(j)+'] неверно введено значение, поправьте');
   exit
 end;
1
175 / 65 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
09.12.2020, 13:32  [ТС] 3
Puporev, один ряд, самый первый, - целые числа. И куда это вставлять?
0
Почетный модератор
64288 / 47587 / 32739
Регистрация: 18.05.2008
Сообщений: 115,182
09.12.2020, 13:36 4
Pascal
1
2
3
4
5
6
7
8
for i:=0 to m-1 do
for j:=0 to n-1 do
if((i=0)and not TryStrToInt(DrawGrid1.Cells[j,i],a[i,j]) )
or  not TryStrToFloat(DrawGrid1.Cells[j,i],a[i,j]) then
 begin
  ShowMessage('В ячейке ['+inttostr(i)+','+inttostr(j)+'] неверно введено значение, поправьте');
   exit
 end;
1
175 / 65 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
09.12.2020, 13:42  [ТС] 5
Puporev, в какое событие Gridа это предполагается вставлять?
0
Почетный модератор
64288 / 47587 / 32739
Регистрация: 18.05.2008
Сообщений: 115,182
09.12.2020, 13:43 6
Это в то событе где читаете таблицу например в Buton1Click.
1
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32577 / 21048 / 8131
Регистрация: 22.10.2011
Сообщений: 36,322
Записей в блоге: 8
09.12.2020, 14:38 7
Лучший ответ Сообщение было отмечено jkrnd как решение

Решение

jkrnd, у тебя ж есть уже класс-перехватчик с переопределенным KeyPress, в нем все и делается:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TDrawGrid.KeyPress(var Key: char);
var e : TStringCellEditor;
begin
  inherited KeyPress(Key);
  case Key of
    '0' .. '9' : ; // do nothing
    else
      if Key = DecimalSeparator then
      begin
        e := TStringCellEditor(Editor); // получаешь текущий редактор (для строк - это всегда TStringCellEditor
        // и проверяешь, есть ли уже внутри редактируемой строки DecimalSeparator. Если есть - второй не разрешать.
        if Pos(DecimalSeparator, e.Caption) > 0 then Key := #0;
      end
      else Key := #0; // вот сюда аналогичным образом добавишь проверку на "минус"
  end;
end;
1
175 / 65 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
09.12.2020, 15:43  [ТС] 8
Puporev, извините, но это совсем не то.

Добавлено через 1 час 4 минуты
volvo, как предотвратить ввод минуса в середине числа? Он должен быть всегда в первой позиции.
Delphi
1
2
3
4
5
    '-':
        begin
            e:= TStringCellEditor(Editor);                      // Получаем текущий редактор 
            if Pos(Key, e.Caption) > 0 then Key := #0;   // Не допускаем повтора минуса
        end;
0
Нарушитель
8592 / 4597 / 1060
Регистрация: 12.03.2015
Сообщений: 21,580
09.12.2020, 15:52 9
Цитата Сообщение от jkrnd Посмотреть сообщение
как предотвратить ввод минуса в середине числа? Он должен быть всегда в первой позиции.
Не делай проверку во время ввода: это кривой бажный костыль.
Проверяй введённое, когда оно понадобится для использования.
1
175 / 65 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
09.12.2020, 15:59  [ТС] 10
Verevkin, категорически с Вами не согласен.
0
Нарушитель
8592 / 4597 / 1060
Регистрация: 12.03.2015
Сообщений: 21,580
09.12.2020, 16:06 11
Цитата Сообщение от jkrnd Посмотреть сообщение
категорически с Вами не согласен.
Ну и хрен с тобой!
Имеешь полное право!
1
175 / 65 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
09.12.2020, 16:13  [ТС] 12
volvo, вот так всё понятно и всё работает, за исключением проверки позиции ввода минуса:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
procedure TDrawGrid.KeyPress(var Key: char);
var e: TStringCellEditor;
begin
    inherited KeyPress(Key);
    case Key of
    '0' .. '9', #8 : ; 
    '.',',':
        begin
            if Self.Col>1 then  // Номер колонки > 1 - значения с плавающей точкой
            begin
                Key:= DecimalSeparator{%H-};
                e:= TStringCellEditor(Editor); // Получаем текущий редактор (для строк - это всегда TStringCellEditor)
                // Проверяем, есть ли уже внутри редактируемой строки DecimalSeparator. Если есть - второй не разрешать.
                if Pos(DecimalSeparator{%H-}, e.Caption) > 0 then Key := #0;
            end
            else   Key:= #0;
        end;
    '-':
        begin
            if Self.Col>1 then  // Номер колонки > 1 - значения с плавающей точкой
            begin
                e:= TStringCellEditor(Editor); // Получаем текущий редактор (для строк - это всегда TStringCellEditor)
                // Проверяем, есть ли уже внутри редактируемой строки '-'. Если есть - второй не разрешать.                
                if Pos(Key, e.Caption) > 0 then Key := #0;
            end
            else   Key:= #0;
        end;
    else   Key:= #0;    
 
    end;                
end;
0
Нарушитель
8592 / 4597 / 1060
Регистрация: 12.03.2015
Сообщений: 21,580
09.12.2020, 16:18 13
Цитата Сообщение от jkrnd Посмотреть сообщение
вот так всё понятно и всё работает, за исключением
ctrl+v
1
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32577 / 21048 / 8131
Регистрация: 22.10.2011
Сообщений: 36,322
Записей в блоге: 8
09.12.2020, 16:21 14
Ctrl+V предотвратится в другом месте, при попытке записать изменения в ячейке в контейнер. Если там всунуто что-то не то - будет облом и просто восстановится старое значение.
1
175 / 65 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
09.12.2020, 16:40  [ТС] 15
volvo, в каком обработчике события обрабатываем проверку правильности введённого?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32577 / 21048 / 8131
Регистрация: 22.10.2011
Сообщений: 36,322
Записей в блоге: 8
09.12.2020, 16:43 16
Я ж написал, в OnSetEditText...
1
175 / 65 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
11.12.2020, 10:11  [ТС] 17
Цитата Сообщение от Verevkin Посмотреть сообщение
ctrl+v
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
var bVCX: boolean;              // Eckb TRUE == Использовались горячие клавиши копирования-вставки.
procedure TDrawGrid.KeyDown(var Key: Word; Shift: TShiftState);
begin
    inherited KeyDown(Key, Shift);
    if  ((Key = ord('X')) and (ssCtrl in Shift)) then bVCX:= true
    else if ((Key = ord('C')) and (ssCtrl in Shift)) then bVCX:= true
    else if ((Key = ord('V')) and (ssCtrl in Shift)) then bVCX:= true;
end;
procedure TDrawGrid.KeyUp(var Key: Word; Shift: TShiftState);
begin
    inherited KeyUp(Key, Shift);
    bVCX:= false;
end;
А уже в KeyPress учитываем состояние переменной bVCX.

Добавлено через 26 минут
Цитата Сообщение от volvo Посмотреть сообщение
e := TStringCellEditor(Editor);
Так мы получаем текущий редактор до ввода клавиши в KeyPress. А можно узнать в какую позицию <e> мы пытаемся ввести некоторый Key в событии KeyPress?

Добавлено через 5 минут
ой, извините. Сам нашёл:
Pascal
1
e.SelStart
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.12.2020, 10:11
Помогаю со студенческими работами здесь

Замена десятичного разделителя
Здравствуйте! Возникла следующая проблема: Требуется, чтобы у дробных чисел десятичный...

Проблема с настройками десятичного разделителя
Возникла проблема программного конструирования SQL-строки: Десятичным разделителем на моем...

Замена символа десятичного разделителя в TextBox
Помогите решить проблемку с преобразованием значений в тип который воспринимает запятую. Есть 9 -...

Нужен компонент - наследник TDrawGrid с подержкой многострочного ввода
Нужен компонент - наследник TDrawGrid с подержкой многосторочного ввода (что-то вроде свойства...

Сделать проверку ввода и допустить ввод только цифр
Как сделать проверку ввода символов, типа если вводится не цифры а текст, то выводить ошибку ...

Определить ограничения на вводимые пользователем значения и не допустить ввода неверных значений
В общем, выделил жирным то с чем проблема. А вообще программа работает, но как я понял нужно что...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru