Страница 1 из 1

Перехват русских букв в консоли Win32

Добавлено: 27 июн 2004, 01:50
BreakPointMAN
Имеем: консольное Win32-приложение, написанное в Borland C++ 5.02.

Необходимо: отлавливать нажатия клавиш на клавиатуре в русской раскладке.

Проблема: при использовании функции getch() все нормально, если вводятся цифры, знаки препинания и
строчные/прописные буквы латиницы - в этом случае getch() возвращает целочисленное значение ASCII-кода соответствующего символа. Но все меняется, когда мы переключаемся в режим ввода кириллицы - цифры и спец. символы вводятся по-прежнему нормально, а вот если нажимается какая-нибудь русская буква, то: 1) она генерирует два байта, причем первый байт - нулевой ('\0'), а второй равен ASCII-коду соответствующей русской буквы; 2) и даже это соблюдается не для всех клавиш: таким образом, например, не ловятся буквы 'х', 'ъ', 'ж', 'э', 'б' и 'ю' - вместо них возвращаются ASCII-коды символов "[];',." ... ........при компиляции того же самого под TC3 все проходит чисто и гладко... На ум уже всякое лезет - и UNICODE, и то, что getch() все-таки больше DOS-овская функция, а не форточная... тестилось под платформами Win98 SE и Win2000 SP4. Результат одинаковый.

Вопрос: можно ли как-то обойти поставленную проблему? Т.е. существуют ли другие функции, аналогичные getch() (аналогичные - т.е. ожидающие нажатия клавиши и возвращающие код символа без эха на экран), которые делали бы то же самое, но корректно? Вообще-то, можно, конечно, пропускать нулевой символ и анализировать следующий за ним, но буквы 'х', 'ъ', 'ж', 'э', 'б' и 'ю' мы все равно в таком случае не поймаем...

Добавлено: 29 июн 2004, 11:55
Romeo
Как задача стоит вообще?

Добавлено: 29 июн 2004, 17:53
BreakPointMAN
Romeo писал(а):Как задача стоит вообще?
пффф... цель всех махинаций до безобразия проста - нужно иметь возможность вводить символы кириллицы при включенной русской раскладке, НО без_эха_на_экран. То есть нажал букву - получил ее код... мне тут посоветовали WinAPI заюзать - ReadConsoleInput... что это и с чем его едят - еще не смотрел, времени пока не очень много было... но... может быть, можно обойтись стандартными средствами BC++ 5.02?.. честно говоря, немного непонятен глюк getch()-а... в чем он проявляется и условия - см. пост #1...

Добавлено: 30 июн 2004, 11:53
Romeo
Глюк как раз понятен. Не все скан коды можно закодировать восемью битами, потому некторые систеные сканкоды двух байтные, первый символ 0. Так было и в DOSе. Потому следующий код вполне уместен при использовании getch под DOS.

Код: Выделить всё

char ch;
BOOL isSystem = FALSE;

// очищаем буфер чтобы не было его переполнения, 
// которое сопровождается противным писком писиспикера.
while (kbhit())
{
   getch();
}

// читаем символ
ch = getch();

// Проверяем на системность.
if (ch == 0)
{
   ch = getch();
   isSystem = TRUE;
}
А вот как бороться с этим глюком под Windows не совсем очевидно...

Добавлено: 30 июн 2004, 14:56
BreakPointMAN
Romeo писал(а):Глюк как раз понятен. Не все скан коды можно закодировать восемью битами, потому некторые систеные сканкоды двух байтные, первый символ 0. Так было и в DOSе.
В DOS-е для хранения всех символов использовалось 8 бит - модифицированная альтернативная кодировка ГОСТа (кодовая страница 866), которая включала в себя и кириллицу в том числе. Т.е. кириллица была полноправным множеством символов кодовой таблицы, и кодировались русские буквы одним байтом. В Windows - с его кодовой таблицей 1251 - ситуация та же самая: были убраны за ненадобностью символы псевдографики, и изменились ASCII-коды символов кириллицы, но в кодовой таблице они так и остались...

Можно понять, скажем, что для клавиш системного назначения генерируется двухбайтовый код. Да и то - не для всех: скажем, F1==0,59; Right Arrow==0,77, а вот BackSpace==8; ESC=27...

Но вот когда речь заходит о русских буквах - тут уж увольте! Они никак не системные! И располагаются на тех же клавишах, что и латинский алфавит... Но почему-то генерируются именно расширенные коды, второй байт которых равен ASCII-коду данной нажатой буквы в кодировке 866 страницы, а первый - нулевой. То есть для буквы 'я' первый байт==0, второй==239. Для буквы 'г' первый байт==0, второй==163 (note: как в 866 кодовой таблице!).

Ладно, все было бы легко и просто, если таким образом можно было бы поймать ВСЕ русские буквы - откидываем первый байт, анализируем второй... НО: при попытке ввести букву русскую 'х' мне возвращается однобайтовый код символа '[', равный 91. При попытке ввести 'ж' мне возвращается код символа ';', равный 59. ОДНОБАЙТОВЫЕ!..