Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.08;
Скачать: [xml.tar.bz2];




Вниз

Опять - DeсimalSeparator??? 


SKing   (2002-03-26 13:42) [0]

Мастера помогите - пожалуйста...
Как заставить кнопку "." на доп. клавиатуре выдавать DeсimalSeparator во всех формах приложения при любой языковой раскладке?
Только не надо советовать для каждого контрола в отдельности.



Вадим   (2002-03-26 13:59) [1]

А если для каждого контрола использовать одну процедуру



Юрий Зотов   (2002-03-26 14:03) [2]

Например, написать обработчик Application.OnMessage, а там проверять, что нажато и подменять код клавиши, если нужно.



Johnmen   (2002-03-26 14:08) [3]

Можно хирургически - заменить "," на "." в kbdru.kbd в нужном месте - тогда будет всегда "."

Можно прописать в приложении обработчик <Del> и делать, что надо...



SKing   (2002-03-27 11:05) [4]

Вадиму-> Это для одной формы, а если форм в прилож. 100 ?
Юрию Зотову-> Если не трудно, можно поподробней...



Reindeer Moss Eater   (2002-03-27 11:10) [5]

>SKing
А если все сто форм приложения сделать наследниками одной и обработку делать в ней?



Alx2   (2002-03-27 11:29) [6]

делаем) Form1.KeyPreview = true
И добавляем метод
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key in [",","."] Then Key := ".";
end;



Alx2   (2002-03-27 11:30) [7]

Пардон, вот так:
if Key in [",","."] Then Key := DecimalSeparator;



Fay   (2002-03-27 11:55) [8]

2Alx2

if Key in [",",".", DecimalSeparator] then Key := DecimalSeparator



Alx2   (2002-03-27 11:57) [9]

if Key in [",",".", DecimalSeparator - зачем?!] then Key := DecimalSeparator



Юрий Зотов   (2002-03-27 12:10) [10]

Можно. Но я придерживаюсь принципа "надо давать не рыбу, а удочку", поэтому расскажу как я сам это делаю.

Открываем хелп на странице TApplication, щелкаем по линку Events, читаем. В боковом окне щелкаем по линку OnMessage, снова читаем. Потом в основном окне щелкаем по линку Example, смотрим пример. Копируем его к себе в программу и подправляем код под свои нужды. Для этого в том же хелпе смотрим объявление типа TMsg, а в SDK - сообщения WM_KEYDOWN, WM_KEYUP, WM_CHAR и страницу Virtual-Key Codes.

Написанный нами обработчик, конечно, сразу правильно работать не будет и это вполне нормально. Ставим в нем BreakPoint, запускаем программу, нажимаем нужные клавиши, смотрим значения переменных, выясняем, что у нас не так и исправляем. В частности, выясняем, как нужно изменить в сообщении WParam и биты 16-23 в LParam, чтобы "подменить" клавишу.

Вот так я это делаю и (честное слово!) еще ни разу не было, чтобы решение не было найдено. Чего и Вам желаю.



Fay   (2002-03-27 12:16) [11]

2Alx2
А "," зачем ?



Alx2   (2002-03-27 12:30) [12]

>Fay © (27.03.02 12:16)
Просто если key = DecimalSeparator, то ее не надо переприсваивать снова значению DecimalSeparator.
А запятую туда вставил, потому что с клавиши "." может прийти либо "." либо ","



Fay   (2002-03-27 12:37) [13]

2Alx2
Угу



Юрий Зотов   (2002-03-27 15:46) [14]

> Alx2
> Fay

Читаем вопрос. Там сказано: "... во всех формах приложения...".

Предположим, в проекте 100 форм. Вы предлагаете править все 100 вручную?



Alx2   (2002-03-27 15:54) [15]

>Вы предлагаете править все 100 вручную?
Зачем вручную?
Screen.Forms[i].KeyPreview := true;
Screen.Forms[i].OnKeyPress := FormKeyPress;
:)



Юрий Зотов   (2002-03-27 16:28) [16]

Это не пройдет по 2-причинам.

Во-первых, компилятор скажет, что FormKeyPress он не знает - ведь в классе TForm такого нет. Но даже если это обойти (например, через RTTI), то остается еще и "во-вторых".

Читаем хелп на TScreen.FormCount:

" Read FormCount to learn the number of forms currently displayed on the screen ".

То есть, Ваш метод сработает, если в момент выполнения цикла все 100 форм присутствуют на экране одновременно. Что нереально.



Reindeer Moss Eater   (2002-03-27 16:37) [17]

Наследование отдыхает?



Alx2   (2002-03-27 16:45) [18]

>Юрий Зотов © (27.03.02 16:28)
> ... forms currently displayed on the screen".
Хм.. действительно.

Но вот работающий пример для всех форм, которые входят в состав Application (то есть созданы через Application.CreateForm(TForm, Form, либо через Form := TForm.Create(Application));

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key in [",","."] Then Key := DecimalSeparator;
end;

procedure TForm1.InitHandlerBtnClick(Sender: TObject); // Раздаем обработчик.
Var k : Integer;
begin
for k := 0 to Application.ComponentCount-1 do
if Application.Components[k].ClassParent = TForm then
with Application.Components[k] as TForm do
begin
KeyPreview := true;
OnKeyPress := FormKeyPress;
end;
end;

А вот для Form2 := TForm2.Create(Nil)) - не сработает. Там только Ваш вариант IMHO.
>что FormKeyPress он не знает - ведь в классе TForm такого нет.
Зато там есть метод OnKeyPress. И ему спокойно присваивается FormKeyPress



Alx2   (2002-03-27 16:50) [19]

>Зато там есть метод OnKeyPress.
>И ему спокойно присваивается FormKeyPress

Пардон, не метод, а event



Alx2   (2002-03-27 16:57) [20]

>А вот для Form2 := TForm2.Create(Nil)) - не сработает.
>Там только Ваш вариант IMHO.
Да, а кто мешает создавать через <...>.Create(Application)?



Юрий Зотов   (2002-03-27 17:08) [21]

> Reindeer Moss Eater (27.03.02 16:37)

Наследование, конечно, не отдыхает. Но чтобы сделать общего предка тоже придется перелопатить 100 pas и 100 dfm. Зачем, если можно сделать проще?



> Alx2 © (27.03.02 16:45)

1. ... работающий пример для всех форм...

Которые на момент прогона цикла УЖЕ созданы и имеют владельцем Application. Я не представляю себе проект, в котором 100 форм создаются статически. И не всегда владельцем формы становится именно Application.

2. ...Зато там есть метод OnKeyPress. И ему спокойно присваивается FormKeyPress.

Во-первых, OnKeyPress - не метод, а событие. Адресное поле, в общем-то. Во-вторых, компилятору на все на это совершенно наплевать - в классе TForm он не знает никаких FormKeyPress и будет ругаться.



Alx2   (2002-03-27 17:15) [22]

>Во-первых, OnKeyPress - не метод, а событие.
Юрий, ну я ж исправился :( :
------------------
Alx2 © (27.03.02 16:50)
>Зато там есть метод OnKeyPress.
>И ему спокойно присваивается FormKeyPress

Пардон, не метод, а event

---------------------

>наплевать - в классе TForm он не знает
>никаких FormKeyPress и будет ругаться.

Но работает же! И не ругается. Я пример, который запостил, проверил и убедился, что все тип-топ. Никто не ругается, где бы форма ни была создана.
Но я Вас не понял. Давайте разберемся.
Мне действительно интересно, что Вы имеете в виду?

>И не всегда владельцем формы становится именно Application.
И про это тоже уже отписал.



Юрий Зотов   (2002-03-27 17:50) [23]

ОК, но вечером.



Alx2   (2002-03-27 17:49) [24]

>Юрий Зотов
Но в общем случае, конечно, Вы правы.



Fay   (2002-03-27 17:52) [25]

2Юрий Зотов
>Но чтобы сделать общего предка тоже придется перелопатить 100
>pas и 100 dfm. Зачем, если можно сделать проще?
ошибки на стадии проектирования часто бывают связаны с подобными траблами :(
Применение Вашего простого метода, если я правильно его понял, повлияет на весь ввод - где надо и где не надо; и не на весь, если понял не правильно Ж8)



Alx2   (2002-03-27 17:53) [26]

Блин, я уже ухожу. Но завтра утром, думаю, ветка еще будет жить...



Reindeer Moss Eater   (2002-03-27 18:35) [27]

Люди, а скажите честно, у вас что, есть проекты, где все формы - прямо от TForm отнаследованы?



Anatoly Podgoretsky   (2002-03-27 19:58) [28]

Reindeer Moss Eater (27.03.02 18:35)
Я пытаюсь вспомнить хоть один проект где бы было иначе.



Anatoly Podgoretsky   (2002-03-27 20:04) [29]

Alx2 © (27.03.02 11:57)
Затем, что необязательно . или ,

Alx2 © (27.03.02 12:30)
Неверно, может и другое



Юрий Зотов   (2002-03-27 22:37) [30]

Ну, вот и вечер...


> Fay © (27.03.02 17:52)
> ... повлияет на весь ввод

А разве я говорил, что не нужно делать никаких проверок? Конечно, в обработчике нужен хотя бы if. Кстати, точно такой же if нужен и при любом другом способе перехвата клавиатуры для всех форм проекта разом. Поэтому речь может идти только о том, как осуществить этот перехват проще, универсальнее и без переделки кучи уже готовых форм. А уж что именно делать в этом перехватчике, что именно проверять или не проверять - это от способа перехвата, по сути, не зависит.



> Alx2 © (27.03.02 17:15)
> Но работает же! И не ругается.

В классе TForm1 обработчик FormKeyPress компилятору известен, поэтому, естественно, работает (а чего бы ему не работать?). Правда, форма не обязана наследоваться от TForm напрямую, поэтому вместо проверки ClassParent=TForm лучше проверять is TForm, иначе проверка может и не сработать.

Но исходную проблему это не решает - если на момент прогона цикла хотя бы одна из 100 форм еще не создана (в чем можно быть практически уверенным), или ее владельцем будет не Application, то и в цикл она не попадет. Соответственно, никаких KeyPreview и никаких обработчиков ей назначено не будет - и мы приплыли! Более того, стоит в процессе работы программы уничтожить любую форму, а потом снова ее создать - и для нее снова придется делать все то же самое. А отсюда новая проблема - как отловить создание формы не из нее самой? Решить можно, но это лишняя головная боль и лишний код.

> Всем желающим

Вот простейший (работающий) пример - во все TEdit"ы проекта, где бы они ни находились разрешается ввод только плюса, минуса, цифр, буквы "E", запятой и точки. При этом запятая, точка и все соответствующие им клавиши (на любом регистре) автоматически преобразуются в корректный DecimalSeparator (при любых настройках системы), а все клавиши, соответствующие русской или латинской букве "E" (на любом регистре) - в латинскую "E". Еще отключен стандартный Beep при Enter. И при этом проект может содержать любое количество любых форм, которые можно создавать и уничтожать где угодно и когда угодно.


type
TForm1 = class(TForm)
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
private
procedure OnAppMessage(var Msg: TMsg; var Handled: Boolean);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := OnAppMessage
end;

procedure TForm1.OnAppMessage(var Msg: TMsg; var Handled: Boolean);
const
Separators = [".", ",", "<", ">", "б", "ю", "Б", "Ю", "?", "/" ];
Exponents = ["e", "у", "У", "е", "Е", "t", "T"];
ValidChars = [#8, #9, "+", "-", "E", "0".."9"];
begin
with Msg do
if (Message = WM_CHAR) and (Screen.ActiveControl is TEdit) then
if Char(WParam) in Separators
then WParam := Byte(DecimalSeparator)
else if Char(WParam) in Exponents
then WParam := Byte("E")
else Handled := not (Char(WParam) in ValidChars)
end;




Alx2   (2002-03-28 08:05) [31]

>Юрий Зотов
>ClassParent=TForm лучше проверять is TForm,
>иначе проверка может и не сработать.
:) Как раз в случае <...>.ClassParent is TForm проверка не может работать: ошибка компиляции.
>как отловить создание формы не из нее самой?
>Решить можно, но это лишняя головная боль и лишний код.
Теперь понял, о чем Вы. Согласен.


>Anatoly Podgoretsky © (27.03.02 20:04)
>Alx2 © (27.03.02 11:57)
>Затем, что необязательно . или ,
Анатолий, если я правильно понял, это ответ на мое
"if Key in [",",".", DecimalSeparator - зачем?!] then Key := DecimalSeparator".

То есть, получается (что мне странно), Вы настаиваете на таком коде:
if Key in [",",".", DecimalSeparator] then Key:=DecimalSeparator;
Но это ведь эквивалентно следующему:
if Key in [",","."] then Key:=DecimalSeparator;
Если такое утверждение Вас не убеждает, то попробую расписать (хотя, мне кажется, что я Вас неправильно понял, ибо то, что пойдет ниже - само собой разумеещееся)
Итак,
if Key in [",",".",DecimalSeparator] then Key:=DecimalSeparator;
можно записать в виде:
if Key = "." then Key := DecimalSpearator else
if Key = "," then Key := DecimalSpearator else
if Key = DecimalSeparator then Key := DecimalSpearator;
Вопрос: а последняя строчка нужна ли? Ненужна. Посему
эквивалентная запись для "if Key in [",",".", DecimalSeparator] then Key:=DecimalSeparator" будет
if Key = "." then Key := DecimalSpearator else
if Key = "," then Key := DecimalSpearator;
или
if Key in [",","."] then Key:=DecimalSeparator;

Примечание: конструкцию с "Else" использовал для минимизации количества сравнений. Так как, при отсутствии else и Key="." после положительного результата теста на Key="." выполнится тест на Key=",", что уже не имеет смысла.

>Alx2 © (27.03.02 12:30)
>Неверно, может и другое
Я писал: "А запятую туда вставил, потому что с клавиши "." может прийти либо "." либо ",""

Спасибо за поправку. Действительно, категорично сказал.
Конечно, может прийти нечто другое :)). А оно нам надо?



Alx2   (2002-03-28 08:14) [32]

>Юрий Зотов.
Опять исправляюсь:
Вот это я нагнал: :) Как раз в случае <...>.ClassParent is TForm проверка не может работать: ошибка компиляции. Лучше бы я это не писал. Стыдно :(



Lord Warlock   (2002-03-28 09:07) [33]

Господа, все очень просто.
В дельфе есть глобальная системная переменная
GlobalDecmailSeparator (по моему так, но точно не помню, можно поискать в хелпе по слову DecmailSeparator)
На ОнКреат приложения запоминаешь старый и ставишь какой нужно,
на ОнДестрой - возвращаешь старый и все :)



Alx2   (2002-03-28 09:38) [34]

>Lord Warlock © (28.03.02 09:07)
Вопрос в другом: "Как заставить кнопку "." на доп. клавиатуре выдавать DeсimalSeparator во всех формах приложения при любой языковой раскладке?". Его уже решили. Остались некоторые, но скорее всего надуманные, детали.




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.08;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.8 MB
Время: 0.031 c
1-22676           DikobraZ              2002-03-28 15:08  2002.04.08  
Новые компоненты закрывают старые...


1-22719           vlv                   2002-03-26 20:45  2002.04.08  
Как очистить TBitmap?


1-22696           andr                  2002-03-26 14:52  2002.04.08  
Как в Word вставить таблицу?


1-22740           snoup                 2002-03-26 23:47  2002.04.08  
Почему не работает вот такая фигня: if timeover = 10 then label1.color:=clred;??????


1-22670           NTDim                 2002-03-28 14:38  2002.04.08  
Вопрос ...