Информационный сервер для программистов: Исходники со всего света. Паскальные исходники со всего света
  Powered by Поисковый сервер Яndex: Найдется ВСЁ!
На Главную Pascal Форум Информер Страны мира
   Турбо Вижн    >>    tvhotrus
   
 
 Русские горячие клавиши в TV  Андрей Вярвельский 15.06.1993

2 варианта реализации русских Hot Keys в меню и потомках объекта TCluster в Turbo Vision



5k 
 

From: Andrew Vyarvelsky <andrew@alta.msk.su> Organization: ALTA Co.Ltd Business News Agency <admin@bimail.donetsk.ua> Fri, 04 Jun writes: > Помогите реализовать русские Hot keys в меню и потомках объекта > TCluster в Turbo Vision Приветствую, admin! :) Поскольку вопрос о русских Hot Keys в Turbo Vision задается в этой конференции, если мне не изменяет память, уже в третий раз, отвечу на него в конференции, а не E-mail-ом. Проще всего, imho, заставить работать русские hot keys, слегка подправив исходные тексты модулей drivers, dialogs и menus, взяв их из RTL. Сразу скажу, что у такого способа русификации есть как минимум два серьезных недостатка. Во-первых, при переходе к новой версии Turbo Vision (2.0 из BP 7.0) модификацию исходных текстов придется повторять. Во-вторых, если Вы делаете свою программу в двух вариантах (русском и английском), вам, возможно, придется хранить два комплекта этих файлов (либо все вносимые изменения оформлять директивами условной компиляции). С другой стороны, imho, этот способ самый простой и надежный. А теперь сами модификации TV 1.0 из TP 6.0 (в TV 2.0 я еще этого не сделал, но не думаю, что там будут принципиальные отличия): ---------------------------------- Drivers. Модифицируем функцию GetAltCode так, чтобы она давала Scan-коды для символов кириллицы: const CyrCodes: array[$10..$35] of Char = { Таблица соответствия } 'ЙЦУКЕНГШЩЗХЪ'#0#0'ФЫВАПРОЛДЖЭЁ'#0#0'ЯЧСМИТЬБЮ'#0; { Scan code -> символ } { или так: здесь #0 --^, а здесь Ё --^, } { если Вы считаете, что буква 'Ё' должна } { располагаться на клавише '/', а не на '`' } function GetAltCode(Ch: Char): Word; var I: Word; begin GetAltCode := 0; if Ch = #0 then Exit; Ch := UpCase(Ch); if Ch = #240 then begin GetAltCode := $0200; Exit; end; if (Ch > #127) and (Ch < #160) then begin {<--------------------------} for I:= $10 to $35 do { Добавляем поиск скэн-кода } if CyrCodes[I] = Ch then begin { для символов кириллицы } GetAltCode:= I shl 8; { аналогично тому, как это } Exit { сделано для цифр и } end { латиницы (см.ниже) } end; {<--------------------------} for I := $10 to $32 do if AltCodes1[I] = Ch then ... -------------------------------------- Dialogs. В HandleEvent-ах трех объектов (TButton, TCluster и TLabel) код символа при обработке нажатия клавиши (Event.CharCode) сравнивается с кодом символа Hot Key. Это делается для обработки в пост-процессной фазе нажатий горячих клавиш без 'Alt'; нажатия горячих клавиш с 'Alt' опознаются путем сравнения Scan-кодов, через вызов функции GetAltCode, которую мы уже исправили. Модифицируем это сравнение кодов так, чтобы русские и латинские буквы, расположенные на одной клавише, считались совпадающими -- русские Hot Keys должны распознаваться вне зависимости от текущего режима клавиатуры (возможно, латинские hot keys тоже должны бы распознаваться вне зависимости от режима клавиатуры, но я в этом не уверен, потому и не сделал :) ). function IsHotKey(EvChar, HotChar: char): boolean; var IsHot: boolean; const Cyr: array ['A'..'Z'] of char = 'ФИСВУАПРШОЛДЬТЩЗЙКЫЕГМЦЧНЯ'; begin EvChar:=UpCase(EvChar); HotChar:=UpCase(HotChar); IsHotKey:=(EvChar = HotChar) or ((EvChar in ['A'..'Z']) and (Cyr[EvChar] = HotChar)) or (HotChar = 'Х') and (EvChar = '[') or (HotChar = 'Ъ') and (EvChar = ']') or (HotChar = 'Ж') and (EvChar = ';') or (HotChar = 'Э') and (EvChar = '''') or (HotChar = 'Б') and (EvChar = ',') or (HotChar = 'Ю') and (EvChar = '.') or (HotChar = 'Ё') and ((EvChar = '`') or (EvChar = '/')) end; procedure TButton.HandleEvent(var Event: TEvent); ... evKeyDown: begin C := HotKey(Title^); if (Event.KeyCode = GetAltCode(C)) or ((Owner^.Phase = phPostProcess) and (C <> #0) and IsHotKey(Event.CharCode,C)) or { <-- } ((State and sfFocused <> 0) and (Event.CharCode = ' ')) then begin ... procedure TCluster.HandleEvent(var Event: TEvent); ... begin C := HotKey(PString(Strings.At(I))^); if (GetAltCode(C) = Event.KeyCode) or (((Owner^.Phase = phPostProcess) or (State and sfFocused <> 0)) and (C <> #0) and IsHotKey(Event.CharCode,C)) then { <-- } begin ... procedure TLabel.HandleEvent(var Event: TEvent); ... else if Event.What = evKeyDown then begin C := HotKey(Text^); if (GetAltCode(C) = Event.KeyCode) or ((C <> #0) and (Owner^.Phase = phPostProcess) and IsHotKey(Event.CharCode,C)) then { <-- } begin ... ------------------------------------- Menus. Поступаем аналогично: function TMenuView.FindItem(Ch: Char): PMenuItem; ... if (P^.Name <> nil) and not P^.Disabled then begin I:= Pos('~', P^.Name^); if (I <> 0) and IsHotKey(Ch,P^.Name^[I+1]) then begin { <-- } ... ------------------------------------- Есть, однако, один пакостный момент: не следует использовать в качестве Hot Keys буквы 'Х', 'Ъ', 'Ж', 'Э', 'Б', 'Ю', 'Ё'. Они будут работать только частично -- при нажатии без 'Alt'. Дело в том, что сочетания 'Alt-[', 'Alt-;' и т.п. не попадают в буфер клавиатуры, и эту ситуацию можно исправить imho только заменой обработчика int 09h на собственный, чего мне делать не хотелось бы. --- Вярвельский Андрей (095) 466-7508 Relcom: andrew@alta.msk.su FIDO: 2:5020/112.7 {> Cut here. FileName= TVHOTRU2.TXT } - TVISION ------------------------------------------------------ Turbo Vision - Msg : 24 of 29 Addr Date From : Сергей Малинин 22.06.93 Subj : Русские горячие клавиши в TV (комментарий) ------------------------------------------------------------------------------- From: root@dem.khabarovsk.su (Sergey A. Malinin) Subject: Коментарии и дополнения к [News] Re: Руские Hot Keys в Turbo Vision Organization: Kompaniy DEM Hi, ALL ! Небольшой коменнтарий к варианту русификации. Andrey Vyarvelsky writes: > Проще всего, imho, заставить работать русские hot keys, слегка подправив > исходные тексты модулей drivers, dialogs и menus, взяв их из RTL. ^ | Imho исправлять не нужно вообще, я этот файл не исправлял. > ---------------------------------- > Drivers. Модифицируем функцию GetAltCode так, чтобы она давала Scan-коды > для символов кириллицы: Но еще нужно также переделать функцию UpCase, чтобы она правильно обраба- тывала кириллицу. { Keyboard support routines } const AltCodes: array[$10..$34] of Char = 'ЙЦУКЕНГШЩЗХ`'#0#0'ФЫВАПРОЛДЖЭ'#0#0#0'ЯЧСМИТЬБЮ'; AltCodes1: array[$10..$32] of Char = 'QWERTYUIOP'#0#0#0#0'ASDFGHJKL'#0#0#0#0#0'ZXCVBNM'; AltCodes2: array[$78..$83] of Char = '1234567890-='; function GetAltChar(KeyCode: Word): Char; begin GetAltChar := #0; if Lo(KeyCode) = 0 then case Hi(KeyCode) of $02: GetAltChar := #240; $10..$32: GetAltChar := AltCodes1[Hi(KeyCode)]; $78..$83: GetAltChar := AltCodes2[Hi(KeyCode)]; end; end; function GetAltCode(Ch: Char): Word; var I: Word; function UpCaseN(Ch: Char):Char; begin if ((Ch>='а') AND (Ch<='п')) then UpCaseN:=Chr(Ord(Ch)-32) else if (Ch>='р') AND (Ch<='я') then UpCaseN:=Chr(Ord(Ch)-80) else UpCaseN:=UpCase(Ch); end; begin GetAltCode := 0; if Ch = #0 then Exit; Ch := UpCaseN(Ch); if Ch = #240 then begin GetAltCode := $0200; Exit; end; if Ch < Chr(128) then begin for I := $10 to $32 do if AltCodes1[I] = Ch then begin GetAltCode := I shl 8; Exit; end; end else begin for I := $10 to $34 do if AltCodes[I] = Ch then begin GetAltCode := I shl 8; Exit; end; end; for I := $78 to $83 do if AltCodes2[I] = Ch then begin GetAltCode := I shl 8; Exit; end; end; --------------------------------------------------------------- После этой манипуляции у меня символы кириллицы стали обрабатываться везде правильно, кроме Меню. > Dialogs. В HandleEvent-ах трех объектов (TButton, TCluster и TLabel) Imho переделывать не нужно вообще -- оно и так правильно работает. А Menus, я переделал немного по другому. Но в принципе почти тоже самое. --------------------------------------------- function Eng_Rus(Ch:Char):Char; var Cn: Char; begin case Ch of 'Й': Cn:='Q'; 'Ц': Cn:='W'; 'У': Cn:='E'; 'К': Cn:='R'; 'Е': Cn:='T'; 'Н': Cn:='Y'; 'Г': Cn:='U'; 'Ш': Cn:='I'; 'Щ': Cn:='O'; 'З': Cn:='P'; 'Ф': Cn:='A'; 'Ы': Cn:='S'; 'В': Cn:='D'; 'А': Cn:='F'; 'П': Cn:='G'; 'Р': Cn:='H'; 'О': Cn:='J'; 'Л': Cn:='K'; 'Д': Cn:='L'; 'Я': Cn:='Z'; 'Ч': Cn:='X'; 'С': Cn:='C'; 'М': Cn:='V'; 'И': Cn:='B'; 'Т': Cn:='N'; 'Ь': Cn:='M'; else Cn:=Ch; end; Eng_Rus:=Cn; end; function TMenuView.FindItem(Ch: Char): PMenuItem; var P: PMenuItem; I: Integer; begin Ch := UpCase(Ch); P := Menu^.Items; while P <> nil do begin if (P^.Name <> nil) and not P^.Disabled then begin I := Pos('~', P^.Name^); if (I <> 0) and (Ch = Eng_Rus(UpCase(P^.Name^[I + 1]))) then begin FindItem := P; Exit; end; end; P := P^.Next; end; FindItem := nil; end; > > Есть, однако, один пакостный момент: не следует использовать в качестве Hot > Keys буквы 'Х', '`', 'Ж', 'Э', 'Б', 'Ю', 'Ё'. Они будут работать только > частично -- при нажатии без 'Alt'. Дело в том, что сочетания 'Alt-[', 'Alt-;' > и т.п. не попадают в буфер клавиатуры, и эту ситуацию можно исправить imho > только заменой обработчика int 09h на собственный, чего мне делать не хотелось Imho обработчик int 09h переделывать не нужно, он и так неплохо работает. Переделать нужно функцию GetKeyEvent в модуле Drivers. Правда я этим не занимался не было необходимости. Но осенью когда этот вопрос обсуждался , был вариант переделки этой функции для Vision под C++. Выглядело это так: /*------------------------------------------------------------*/ /* filename - tevent.cpp */ /* TEvent member functions */ /*------------------------------------------------------------*/ // ........... #pragma warn -asc void TEvent::getKeyEvent() { asm { MOV AH,1; INT 16h; JNZ keyWaiting; }; what = evNothing; return; keyWaiting: what = evKeyDown; asm { MOV AH,0; INT 16h; MOV BX,AX; MOV AH,2; INT 16h; TEST AL,08h; JNE RusAlt; JMP EndProc; }; RusAlt: asm XOR BL,BL; EndProc: asm MOV AX,BX; keyDown.keyCode = _AX; return; } #pragma warn .asc Правда я не помню, кто это написал. В общем все, как видите для русификации надо сделать гораздо меньше изменений программе. Сергей Малинин. serg@dem.khabarovsk.su