Controls

Как заставить клавишу с “точкой” всегда вводить точку

Вопрос

На альтернативной цифровой клавиатуре (правая часть клавиатуры под клавишей NumLock) есть клавиша с "точкой". Однако она водит именно точку только при английской раскладке клавиатуры, а при русской раскладке клавиатуры вводит запятую. При вводе чисел с дробной частью это создает проблемы. Как можно заставить вводить символ точки вне зависимости от текущей раскладки клавиатуры?

Ответ

В событии KeyPress для Вашего объекта TextBox пишете такой код

  
  LPARAMETERS nKeyCode, nShiftAltCtrl  
  IF InList(CHR(nKeyCode),'.',',') AND CHR(nKeyCode)<>SET('POINT')  
  	NODEFAULT  
  	DoDefault(ASC(SET('POINT')),nShiftAltCtrl)  
    
 	*!* или вместо DoDefault в данном случае можно дать такую команду  
 	*!* KeyBoard SET('POINT') PLAIN CLEAR  
  ENDIF

Все. Теперь при попытке ввода точки или запятой будет автоматически введен символ, который Вы приняли в качестве разделителя целой и дробной части. Даже если это, например, дефис.

Для удобства работы, лучше создать отдельный класс на основе TextBox с данным кодом, чтобы не дублировать его каждый раз при создании нового объекта.

Как заменить сообщение Invalid Date при вводе некорректной даты

Вопрос

Если в TextBox вводится некорректная дата, то появляется сообщение "Invalid Date". Как можно проконтролировать корректность ввода даты до появления этого сообщения и заменить данное сообщение своим?

Ответ

Для начала следует задуматься о необходимости такой замены. Дело в том, что если Вы поставляете вместе с готовым файлом EXE русскоязычную Run-Time библиотеку с именем vfpXrrus.dll (X - цифра, соответствующая номеру версии Visual FoxPro), то вместо английского сообщения "Invalid Date" возникнет сообщение по-русски "Неверная дата".

Тем не менее, если Вы все-таки хотите произвести подмену вручную, то для этого есть способ.

Начиная с версии Visual FoxPro 5, для объекта TextBox добавлено свойство StrictDataEntry.

По умолчанию, это свойство имеет значение: 1 - Strict. Установите его в значение: 0 - Loose.

В этом случае, если введено некорректное значение даты, то никакого сообщения об ошибке вообще не возникает. Просто значение свойства TextBox.Value становиться пустым.

Это можно определить в событии TextBox.Valid() и выдать собственное сообщение об ошибке

  
 * Событие TextBox.Valid  
  IF EMPTY(This.Value) = .T.   
  	MessageBox("Дата введена некорректно!")  
  ENDIF

Однако при таком подходе возникают две проблемы:

1) Событие TextBox.Valid() наступает при выходе из объекта вне зависимости от того, изменяли Вы содержимое данного объекта или нет.

Это значит, что если значение поля изначально было пустым и пользователь в нем ничего не менял, а просто "прошел" через этот объект, например, при помощи клавиши Tab, то возникнет сообщение об ошибке. Чего быть не должно.

2) Если изначально дата уже была введена, а в процессе изменения пользователь ошибся, то желательно установить не пустое значение даты, а вернуть ее в исходное состояние. Т.е. установить то значение, которое было до редактирования.

Чтобы решить эти проблемы необходимо небольшое пояснение.

Если пользователь что-то изменяет в объекте, то на каждую модификацию срабатывает событие TextBox.InteractiveChage(). Но в данном случае недостаточно просто определить факт модификации. Необходимо определить тот факт, что пользователь пытался ввести не пустое значение.

То, что пользователь пытался ввести сохраняется в свойстве TextBox.Text. Точнее, в этом свойстве хранится то, что пользователь видит на экране, а не то, что сохраняется в свойстве TextBox.Value. Хотя значение этих свойств могут и совпадать. Но в общем случае это не так. Они отличаются, например, из-за используемых масок ввода.

К сожалению, нельзя просто сравнить в событии TextBox.Valid() значение свойств TextBox.Value и TextBox.Text. Дело в том, что если объект TextBox имеет не пустое значение свойства TextBox.ControlSource (например, TextBox "привязан" к полю таблицы), то к моменту выполнения события TextBox.Valid() в случае ошибки ввода свойство TextBox.Text также окажется пустым. Отдельное спасибо Андрею Тарасову (XAndy), обратившему на это внимание.

Следовательно, необходимо в событии TextBox.InteractiveChange() организовать сохранение текущего значения свойства TextBox.Text. И если в событии TextBox.Valid() окажется, что значение TextBox.Value пустое, а сохраненное значение TextBox.Text не пустое, то это и будет означать ошибку ввода.

Аналогичным образом следует поступить и для восстановления значения до редактирования. Надо просто сохранить исходное значение. Процедуру сохранения выполнить при входе в объект. Либо в событии TextBox.When(), либо в событии TextBox.GotFocus().

У любого объекта FoxPro есть два дополнительных свойства: Tag и Comment. Это свойства-комментарии. Они никак не влияют на работу объекта и предназначены для хранения справочной информации. Следует только иметь в виду, что они принимают значения только и исключительно символьного типа. Вот эти-то два свойства и используем для хранения нужных значений.

В результате, после всех пояснений, получаем такой код:

  
 * Событие TextBox.When  
  This.Comment = DTOC(This.Value)  
    
    
 * Событие TextBox.InteractiveChange  
 * Используется TransForm(), а не DTOC(),   
 * поскольку значение This.Text может не преобразовываться в дату  
  This.Tag = TransForm(This.Text)  
    
    
 * Событие TextBox.Valid  
 * Значение, которое попытался ввести пользователь  
  LOCAL lcUserText  
  lcUserText = This.Tag  
    
 * Очищаем сохраненное значение  
  This.Tag = ""  
    
 * Сравниваю то, что реально введено с тем, что пытались ввести   
 * Предполагаю, что реально введено то, что должно вернуть Ctod(m.lcUserText)  
  If Empty(m.lcUserText)=.F. AND m.lcUserText <> Dtoc(Ctod(m.lcUserText))  
  	This.Value = Ctod(This.Comment)  
  	MessageBox("Неверный ввод даты")  
  	  
 	* Если хотите запретить выход из объекта,   
 	* то снимите комментарий со следующей команды  
 	* Return 0  
  EndIf

Вам решать, стоит ли полученный результат затраченных усилий.

Замечание

Если объект TextBox, не связан ни с каким источником данных. Т.е. и TextBox.ControlSource, и TextBox.Value при открытии формы не указаны. То для того, чтобы символы разделители в дате не съезжали при вводе, необходимо указать нужный формат

TextBox.Format = "D"
//////////////// ///////////////
Авторизация
*
*
Генерация пароля