Исходя из ТЗ приходится загонять пользователей в жесткие рамки ввода текста... Задача следующего характера, пользователи могут вводить только русские символы, как бы организовать выдачу сообщения, что в данный момент у них раскладка английская или введены цифры? Смотрел по свойствам Edit - OnKeyPress или OnChange, единственное что пришло в голову это туп перебирать все буквы так:
Код
begin
if Edit2.Text='Q' then
begin ShowMessage('Смените раскладку клавиатуры на русскоязычную'); end; end;
Может есть способ проще, а то данный способ после двух неверных вводом почему не хочет дальше ругаться... P.s. По свойствам Edit все символы будут большими буквами CharCase = ecUpperCase
--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
На самом деле, задача сложнее, чем просто отследить, какая на данный момент раскладка. Просто раскладка - это вот так:
if LOWORD(GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow, nil))) = $0419 then { Русская } else { Не русская }
, только тебе это ничего не даст. Надо еще и контролировать Ctrl+C снаружи -> Ctrl+V в твое приложение. Я бы сделал как-то вот так:
uses ..., ClipBrd;
// Сразу говорю, чтоб не было вопросов, почему здесь не множество, а строка: // НЕ РАБОТАЕТ Дельфи с множествами из юникодных символов. Если компилятор // выше, чем D2007, то начнутся проблемы
function CheckSymbol(Ch : Char) : Boolean; const StrAlpha : String = 'ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ'; begin result := (Pos(Ch, StrAlpha) <> 0); end;
// Пишем свою оконную процедуру для Edit-а, где будем отслеживать Paste function NewEditProc(MyWnd: HWND; uMsg: UINT; MyWParam: WPARAM; MyLParam: LPARAM): Integer; stdcall; var s: String; i: Integer; begin if (uMsg = WM_PASTE) and Clipboard.HasFormat(CF_TEXT) then begin s := Clipboard.AsText; for i := 1 to Length(s) do if not CheckSymbol(s[i]) then begin uMsg := 0; Break // Если хоть один символ попадает под ограничения - отменить Paste полностью end end; result := CallWindowProc(Pointer(GetWindowLong(MyWnd, GWL_USERDATA)), MyWnd, uMsg, MyWParam, MyLParam); end;
// При создании формы установим Edit-у новую оконную процедуру // (ecUpperCase можно не устанавливать, ES_UPPERCASE в любом случае сделает то же самое) procedure TForm1.FormCreate(Sender: TObject); begin SetWindowLong(Edit1.Handle, GWL_STYLE, GetWindowLong(Edit1.Handle, GWL_STYLE) or ES_UPPERCASE); SetWindowLong(Edit1.Handle, GWL_USERDATA, SetWindowLong(Edit1.Handle, GWL_WNDPROC, LPARAM(@NewEditProc))) end;
// Ну ладно, Paste мы отследили, там враг не пройдет. А что с печатанием в Эдит? procedure TForm1.Edit1Change(Sender: TObject); var i: integer; s : TCaption; begin s := Edit1.Text; for i := 1 to Length(s) do begin if not CheckSymbol(s[i]) then begin ShowMessage('Неверная раскладка / символ'); delete(s, i, 1); break; end; end; Edit1.Text := s; Edit1.SelStart := Length(s) + 1; end;