![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблема с UpperCase и InputBox [D7, WinXP]
PRT © (2006-06-18 18:23:00)1. Почему UpperCase('строка') не работает если строка - русские символы ???
2. Можно ли в InputBox ограничить ввод символов ?? (например, чтоб можно было вводить только русские символы)
Leonid Troyanovsky (2006-06-19 20:42:00) [1]
> begin...end © (19.06.06 20:38) [10]
> ли когда-нибудь будет по-другому, но мне почему-то полагаться
> на это не хочется.
Тогда ActiveForm и перебрать Controls.
--
Regards, LVT.
begin...end (2006-06-19 20:38:00) [2]> Leonid Troyanovsky © (19.06.06 20:20) [8]
> Хотя, конечно, Screen.ActiveControl для InputBox вполне,
> IMHO, хватит.
Ну, если положиться на то, что фокус после вызова InputBox обязательно будет у edit'а -- тогда да. Собственно, вряд ли когда-нибудь будет по-другому, но мне почему-то полагаться на это не хочется.
:-)
begin...end (2006-06-19 20:25:00) [3]> Leonid Troyanovsky © (19.06.06 20:20) [8]
И правда. Забыл.
Leonid Troyanovsky (2006-06-19 20:20:00) [4]
> begin...end © (19.06.06 19:53) [7]
> EditInstance := TEdit(SendMessage(EditHandle, GetObjectInstanceMessage,
Ну, есть, вообще-то, FindControl.
Хотя, конечно, Screen.ActiveControl для InputBox вполне, IMHO, хватит.
--
Regards, LVT.
begin...end (2006-06-19 19:53:00) [5]> PRT (18.06.06 18:23) [0]
> 2. Можно ли в InputBox ограничить ввод символов ?? (например,
> чтоб можно было вводить только русские символы)
Можно.
Что происходит при вызове InputBox? Создаётся форма c edit'ом и двумя кнопками, которая показывается модально.
Можем ли мы выполнить какой-нибудь свой код сразу после того, как эта форма будет модально показана? Можем -- сразу после её показа заработает цикл выборки сообщений, заключённый в методе ShowModal. Если послать, скажем, нашей главной форме асинхронное сообщение перед вызовом InputBox, то оно будет выбрано из очереди в ходе работы этого цикла. А в обработчике этого сообщения как раз и можно разместить нужный код.
Допустим, дескриптор модальной формы мы определили.
Можем ли мы получить дескриптор дочернего edit'а? Можем -- см. FindWindowEx.
Можем ли мы получить указатель на экземпляр класса TEdit (Self), связанный с этим дескриптором? Можем -- см. Controls.pas, сообщение RM_GETOBJECTINSTANCE.
Безопасно ли использовать этот указатель? Да, безопасно, потому что контрол находится в том же процессе, в котором находимся мы -- а значит, указатель содержит адрес экземпляра в ВАП нашего процесса.
Можем ли мы, имея этот указатель, назначить edit'у свой обработчик события? Можем, причём совершенно стандартно -- установив значение соответствующего свойства.
А вот код, который всё это делает. Особо не тестировал, но, вроде бы, работает.
const
WM_MODALMESSAGE = WM_USER + 100;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
procedure WMModalMessage(var Message: TMessage); message WM_MODALMESSAGE;
procedure EditKeyPress(Sender: TObject; var Key: Char);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
PostMessage(Handle, WM_MODALMESSAGE, 0, 0);
InputBox('Изменённый InputBox', 'Сюда вводятся только русские буквы:', '')
end;
procedure TForm1.EditKeyPress(Sender: TObject; var Key: Char);
begin
if not (Key in ['А'..'я', 'ё', 'Ё']) then
Key := #0
end;
procedure TForm1.WMModalMessage(var Message: TMessage);
var
EditHandle: Cardinal;
EditInstance: TEdit;
GetObjectInstanceMessage: Cardinal;
begin
EditHandle := FindWindowEx(GetActiveWindow, 0, 'TEdit', nil);
if EditHandle <> 0 then
begin
GetObjectInstanceMessage := RegisterWindowMessage(PChar(Format('ControlOfs%.8X%.8X', [HInstance, GetCurrentThreadID])));
EditInstance := nil;
EditInstance := TEdit(SendMessage(EditHandle, GetObjectInstanceMessage, 0, 0));
if Assigned(EditInstance) then
begin
EditInstance.OnKeyPress := EditKeyPress
end
end
end;
Здесь edit'у назначается обработчик OnKeyPress, поэтому будет фильтроваться только текст, вводимый вручную, а проблему вставки текста с русскими буквами из буфера это не решает, но совершенно аналогично можно решить и эту проблему -- назначить нужный OnChange вместо OnKeyPress.
kaif (2006-06-19 10:37:00) [6]AnsiUpperCase
PZ (2006-06-18 20:09:00) [7]Используйте переключатель клавиатуры:
LoadKeyboardLayout('00000419', KLF_ACTIVATE); // вкл. русский шрифт
LoadKeyboardLayout('00000409', KLF_ACTIVATE); // вкл. латинский шрифт
Rial (2006-06-18 20:03:00) [8]function UpCase(C : Char): Char; assembler;
asm
MOV AL,C
CMP AL,'a'
JB @@3
CMP AL,'z'
JBE @@2
CMP AL,'ё'
JZ @@1
CMP AL,'а'
JB @@3
CMP AL,'я'
JBE @@2
JMP @@3
@@1: MOV AL,'Ё'
JMP @@3
@@2: SUB AL,$20
@@3:
end;
jack128 (2006-06-18 18:59:00) [9]PRT (18.06.06 18:56) [2]
Не спорю, но это еще одна форма, еще пару лишних кБ.
если форму динамически создавать, а не в дезин тайм, то не более 500 байт - 100 пудов.
PRT (2006-06-18 18:56:00) [10]
> вряд ли, но что может быть проще, чем написать свою InputBoxEx
> ?
Не спорю, но это еще одна форма, еще пару лишних кБ.
Eraser (2006-06-18 18:29:00) [11]> [0] PRT (18.06.06 18:23)
> 1. Почему UpperCase('строка') не работает если строка -
> русские символы ???
см. AnsiUpperCase
> 2.
вряд ли, но что может быть проще, чем написать свою InputBoxEx ?