Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.08.2008, 20:39   #1
Minimus
Пользователь
 
Аватар для Minimus
 
Регистрация: 03.08.2008
Сообщений: 43
Вопрос Преобразование VK в символ

Доброго всем вечера.
Возникла у меня проблемка следующего содержания:
У меня есть:
-Раскладка клавиатуры (в виде HKL - хэндла раскладки клавиатуры);
-Виртуальный код клавиши.
Нужно получить:
-код символа, который соответствует этим данным.

Единственное, что я смог придумать - это воспользоваться таблицей соответствия, т.е примерно по такому алгоритму:

1.Резервируем массив из 256 элементов.
2.Загружаем нужную раскладку клавиатуры.
3.Заполняем массив с помощью VkKeyScanEx примерно так:
Код:
procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
tabl:array[0..255] of char;
i,k:integer;
hk:Cardinal;
tmp:string;
begin
  hk:=GetKeyboardLayout(GetCurrentThreadId);
  for i:=0 to 255 do                                          //перебираем все символы
  begin
    k:=VkKeyScanEx(char(i),hk);
    if k<=255 then tabl[k]:=char(i);                      //индекс=VK,значение=символ.
  end;
  tmp:=tabl[Key];
  if Key<=255 then Caption:=tmp;
end;
4.Восстанавливаем старую раскладку.

Ну а дальше используя VK (если он <= 255) в качестве индекса получаем нужный символ.

А никто не знает какого нибудь более рационального способа?
Заранее большое человеческое спасибо.

ЗЫ1: Не обращайте внимание на бредовость кода - он написан исключительно с целью проверки правильности работы алгоритма и не более того.

ЗЫ2: Чуть не забыл: раскладку и виртуальные коды клавиш приложение получает посредством SendMessage от хука типа WH_KEYBOARD.
бороться и искать
найти и перепрятать.

Последний раз редактировалось Minimus; 15.08.2008 в 00:53. Причина: Ошибка в коде
Minimus вне форума Ответить с цитированием
Старый 15.08.2008, 00:13   #2
Minimus
Пользователь
 
Аватар для Minimus
 
Регистрация: 03.08.2008
Сообщений: 43
По умолчанию

Попробовал еще одним способом:
1.Загружаю нужную раскладку
2.Создаю структуру MSG
3.Заполняю искуственно ее поля (message,wParam,lParam)
4.Вызываю TranslateMessage
5.Принимаю сообщение WM_CHAR
6.Восстанавливаю прежнюю раскладку

Гемора стало еще больше, а результаты еще хуже. Это все явно не наши методы!

ЗЫ:Помогите!!!
бороться и искать
найти и перепрятать.
Minimus вне форума Ответить с цитированием
Старый 15.08.2008, 08:39   #3
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
код символа, который соответствует этим данным
Чет я недоперепонял, а разве var Key: Word не возвращает как раз этот код?
Цитата:
от хука типа WH_KEYBOARD.
А пример о чем говорит?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 15.08.2008, 11:20   #4
Minimus
Пользователь
 
Аватар для Minimus
 
Регистрация: 03.08.2008
Сообщений: 43
Сообщение

Цитата:
Сообщение от Stilet Посмотреть сообщение
Чет я недоперепонял, а разве var Key: Word не возвращает как раз этот код?
В справке дельфей написано следующее:

Код HTML:
Key parameter is the key on the keyboard. For non-alphanumeric keys, use virtual key codes to determine the key pressed. For more information, see Virtual Key codes.
Т.е var Key:Word является именно VK нажатой клавиши, а не символом.

Цитата:
Сообщение от Stilet Посмотреть сообщение
А пример о чем говорит?
Дык пример, несмотря на его бессмысленность, просто тестирует работу этого алгоритма - т.е. я взял var Key:WORD (= VK клавиши), с помощью VkKeyScanEx заполнил таблицу символов, и уже из этой таблицы извлек символ (используя Key в качестве индекса), т.е. фактически, выполнил преобразование VK->char с учетом раскладки клавиатуры hk.
В реальном приложении, я буду брать VK и hk из message, посылаемого окну от хука. Но это не меняет сути процесса преобразования.

ЗЫ: В принципе метод неплохо работает, но медленно. Вот я и решил спросить, может быть кто-нибудь знает как это сделать попроще?
бороться и искать
найти и перепрятать.

Последний раз редактировалось Minimus; 15.08.2008 в 11:38.
Minimus вне форума Ответить с цитированием
Старый 15.08.2008, 11:37   #5
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Ясно, попробуй примени MapVirtualKeyEx
Даже помоему уже обсуждалось это...

Вот тут посмотри: http://programmersforum.ru/showthrea...apVirtualKeyEx
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 15.08.2008, 12:31   #6
Minimus
Пользователь
 
Аватар для Minimus
 
Регистрация: 03.08.2008
Сообщений: 43
По умолчанию

Спасибо. Щас посмотрю...
Попробовал. Что-то вроде такого:

вариант1:

Код:
procedure TForm1.Memo2KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
ch:char;
hk:Cardinal;
begin
  hk:=GetKeyboardLayout(GetCurrentThreadId);
  ch:=char(MapVirtualKeyEx(Key,2,hk));
  Caption:=ch;
end;
Выдает только латиницу в верхнем регистре, а вместо непечатаемых символов - квадратики. Зачем ей тогда нужно раскладка клавиатуры?

вариант2:

Код:
procedure TForm1.Memo3KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
ch:char;
code:DWord;
hk:Cardinal;
ks:TKeyboardState;
begin
  hk:=GetKeyboardLayout(GetCurrentThreadId);
  code:=MapVirtualKeyEx(Key,0,hk); //получаем скан-код
  ToAscii(Key,code,ks,@ch,0);
  Caption:=ch;
end;
Работает!

ЗЫ: А вам, уважаемый Stilet, как и обещалось в первом послании,
БОЛЬШОЕ ЧЕЛОВЕЧЕСКОЕ СПАСИБО!
бороться и искать
найти и перепрятать.
Minimus вне форума Ответить с цитированием
Старый 15.08.2008, 12:52   #7
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Всегда пожалуйста.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 15.08.2008, 20:56   #8
Minimus
Пользователь
 
Аватар для Minimus
 
Регистрация: 03.08.2008
Сообщений: 43
Лампочка

После долгих экспериментов я наконец-то нашел окончательный вариант:
самое простое решение - это призводить все преобразования в контексте того процесса, от которого VK и был получен.
Код:
KEYBOARDSTATE struct
        keydata db 256 dup(?)
KEYBOARDSTATE ends

.code

VKtoChar proc vkcode:DWORD
LOCAL tmpchar:DWORD
LOCAL ks:KEYBOARDSTATE
    invoke GetCurrentThreadId
    invoke GetKeyboardLayout,eax                                     
    push eax
    sub eax,eax
    mov tmpchar,eax
    invoke GetKeyboardState,addr ks
    pop edx                                                 
    invoke ToAsciiEx,vkcode,0,addr ks,addr tmpchar,0,edx
    mov eax,tmpchar
    ret
VKtoChar endp
То же самое:
Код:
function VKtoChar(VKKey: Word):char;
var
ch:char;
code:DWord;
hk:Cardinal;
ks:TKeyboardState;
begin
  hk:=GetKeyboardLayout(GetCurrentThreadId);
  GetKeyboardState(ks);
  ToAsciiEx(VKKey,0,ks,@ch,0,hk);
  result:=ch;
end;
В таком варианте происходит полное декодирование - даже учитывается регистр.
Ну и чтобы окончательно закрыть тему выкладываю архив с исходниками(может быть кому и пригодиться), в котором содержатся:
1.Dll-ка, ставящая глобальный хук на события клавиатуры (с исходниками на masm);
2.Заголовочный файл на дельфях;
3.Тестовая програмка (также на дельфях);

ЗЫ: Дельфи не перестают удивлять - оказывается после события OnShow и до появления окна на экране форма успевает поменять свой хандл (по крайней мере в дельфи 7)! И во время работы приложения - при сворачивании и восстановлении окна иногда(я так и не понял от чего это зависит) происходило тоже самое. Поэтому для обновления хандла я использовал таймер - на всякий случай.
Вложения
Тип файла: rar KeyHook.rar (5.4 Кб, 48 просмотров)
бороться и искать
найти и перепрятать.

Последний раз редактировалось Minimus; 15.08.2008 в 22:06.
Minimus вне форума Ответить с цитированием
Старый 25.05.2009, 22:36   #9
Asis
Новичок
Джуниор
 
Регистрация: 25.05.2009
Сообщений: 1
По умолчанию

Нашел в сети такой вариант:

Код:
function GetCharFromVirtualKey(Key: Word): string;
var
   keyboardState: TKeyboardState;
   asciiResult: Integer;
begin
   GetKeyboardState(keyboardState) ;

   SetLength(Result, 2) ;
   asciiResult := ToAscii(key, MapVirtualKey(key, 0), keyboardState, @Result[1], 0) ;
   case asciiResult of
     0: Result := '';
     1: SetLength(Result, 1) ;
     2:;
     else
       Result := '';
   end;
end;
источник: http://delphi.about.com/od/adptips2006/qt/vkey2char.htm
Asis вне форума Ответить с цитированием
Старый 02.06.2009, 00:33   #10
Munigas
Новичок
Джуниор
 
Регистрация: 31.05.2009
Сообщений: 2
По умолчанию Преобразование VK в символ

Нигде не могу найти ответ на мой вопрос : как имея число код символа получить сам символ ? В СBuilder все легко : создаешь переменную типа char, присваиваешь ей число и вот тебе символ. Но понятия не имею, как это сделать в Delphi ??? Уже пробовал через string и pchar, но уж очень плохо получается.
Может это и легко ... но я не знаю как Помогите, пожайлуста
Munigas вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как из delphi вставить символ в word? Sony Общие вопросы Delphi 10 04.09.2014 19:51
Как получить символ?(Delphi) The_Darkness Помощь студентам 3 18.07.2008 08:36
Потоки и символ конца строки Deatz Общие вопросы C/C++ 3 07.05.2008 20:02
Перл. Замена символа \ на символ / Stilet PHP 1 12.04.2008 10:17
как присвоить char'у символ перевода строки? Retiz Помощь студентам 6 06.04.2008 00:05