1 Востаннє редагувалося Betterthanyou (29.04.2016 22:32:28)

Тема: WinAPI Дізнатися розкладку клавіатури

Перша проблема, коли я намагаюся дізнатися розкладку, це те що віндовс дозволяє налаштувати: або однакова розкладка для всіх програм, або індивідуальна для кожної. Щоб довго не визначати як там налаштував користувач я вирішив розглядати ситуацію коли для кожного вікна окрема розкладка.
GetForegroundWindow  - наскільки я зрозумів дає мені hwnd активного вікна
GetKeyboardLayout - повертає розкладку, але тут розпочалися нові проблеми
- що хоче GetKeyboardLayout  я не розумію навіщо їй _In_ DWORD idThread а не hwnd наприклад, як даній функції сказати щоб вона вернула розкладку яка зараз у активному вікні (тобто ту що я отримав за допомогою GetForegroundWindow) ?
- Я використав 0 (0 означає ... 0 for the current thread) але й що вона вертає якийсь HKL якщо подивитися в опис я так зрозумів це ідентифікатор мов код мови представлені у 16 коді, то HKL можна (як так думаю) конвертувати в int, а в int_ті цей результат виглядає так 67699721 а якщо подивитися у 16 системі то так 4090409 (можливо я не правильно перетворив, я робив так включив window calculator поставив перемикача в dec, ввів 67699721 і поставив перемикача в hex) ну і звичайно такого коду мов немає. Чому я отримую не вірний код мов ?
- current thread що це ? Потік моєї програми чи активної програми на даний момент ?

Подякували: leofun011

2

Re: WinAPI Дізнатися розкладку клавіатури

4090409h <=> (0409h << 16d + 0409h)
Подякували: Betterthanyou, leofun012

3

Re: WinAPI Дізнатися розкладку клавіатури

GetKeyboardLayout - повертає розкладку, але тут розпочалися нові проблеми
- що хоче GetKeyboardLayout  я не розумію навіщо їй _In_ DWORD idThread а не hwnd наприклад, як даній функції сказати щоб вона вернула розкладку яка зараз у активному вікні

GetKeyboardLayout() працює для процесу.
GetWindowThreadProcessId() визначає ID процесу, якому належить вікно, яке ви визначаєте через пошук вікна поверх всіх GetForegroundWindow().

http://raxp2.blogspot.com/2015/04/api-r … omvbs.html

Подякували: Betterthanyou, leofun012

4

Re: WinAPI Дізнатися розкладку клавіатури

Мені вдалося визначити RUS i ENG мову, а UKR що не хоче точніше так:
Не дуже розбираюся в бітових операціях, я так зрозумів щоб мені побачити 16 код (Locale identifier) потрібно HKL перетворити в int і здвинути на 16 тобто так

((int)GetKeyboardLayout(idProcess))>>16

Не зрозумів цей запис
4090409h <=> (0409h << 16d + 0409h) (від Chemist-i)

якщо поставити ENG я отримую 1033 в 10 системі, а в 16 це число виглядає так 409 дивимося в таблицю 0х0409 = United States (US)
аналогічно з RUS 1049 -> 419 = LANG_RUSSIAN
А з UKR почалися проблеми, я отримав -3928 ну і звичайно (unsigned позбавляє від мінуса, але проблему не вирішує) FFFFFFFFFFFFF0A8 немає в таблиці
Що я роблю не так ?, як правильно здвинути біти в GetKeyboardLayout щоб отримати Locale identifier ( з першого стовпчика ) в таблиці ?

5 Востаннє редагувалося Betterthanyou (30.04.2016 15:05:05)

Re: WinAPI Дізнатися розкладку клавіатури

Ну от, так-сяк вийшло

//Спочатку дізнаємося активне вікно і його процес (idProcess) який буде потрібний потім
    HWND hWindow = GetForegroundWindow();
    DWORD idProcess = GetWindowThreadProcessId(hWindow, 0);

//Зберігаємо HWND (точніше зберігаємо трохи нижче а тут створюємо лише змінну статичну)
    static HWND SaveWindow = NULL;
    wchar_t  WindowName[256]{'\n'};

//Дивимося чи змінилося вікно
    if(hWindow != SaveWindow)
    {
        SaveWindow = hWindow;
        GetWindowText (SaveWindow, WindowName, 256);
        if(QString::fromWCharArray(WindowName) != "")
        {
            //ТУТ ЗБЕРІГАЄМО НАШЕ ВІКНО (його WindowName)
        }
    }

//НЕВДАЛИЙ КОД
//дізнаємося Language Identifier
    unsigned int lanHere = ((int)GetKeyboardLayout(idProcess))>>16;
//Зберігаємо мову
    static unsigned int lanSave = 0;
//Ну і записуємо мову 
    if(lanHere != lanSave)
    {
        lanSave = lanHere;
        if(lanSave == 1033)
        {
            //English
            //ТУТ ЗБЕРІГАЄМО МОВУ ВВЕДЕННЯ (приклад += "\n\n<Language = English>\n\n";)
        }
        else if(lanSave == 4294963368)
        {
            //Ukrainian
            //ТУТ ЗБЕРІГАЄМО МОВУ ВВЕДЕННЯ 
        }
        else if(lanSave == 1049)
        {
            //Russian
            //ТУТ ЗБЕРІГАЄМО МОВУ ВВЕДЕННЯ 
        }
        else
        {
            //language other
            //ТУТ ЗБЕРІГАЄМО МОВУ ВВЕДЕННЯ (приклад += "\n<Language = other, HKL = (int)" +
                    IntToStr(lanHere)
                    + ", more = https://msdn.microsoft.com/uk-ua/library/windows/desktop/dd318693(v=vs.85).aspx>\n";)
        }
    }

І отримав я такий вихідний файл (Щоб його отримати цей код потрібно циклічно повторювати, звичайно з якоюсь затримкою наприклад 10 мілісекунд достатньо щоб не грузити процесора і встигнути записати всі зміни (які відбуваються), можливо можна й більші паузи але й навіщо)

--KEY--


User chose another program = doing.cpp - System32 - Qt Creator



<Language = English>



User chose another program = Нове повідомлення - WinAPI Дізнатися розкладку клавіатури - C/C++ - Український форум програмістів – Yandex



<Language = Ukrainian>



<Language = English>



<Language = Ukrainian>



User chose another program = Program Manager



User chose another program = File Explorer


User chose another program = Нове повідомлення - WinAPI Дізнатися розкладку клавіатури - C/C++ - Український форум програмістів – Yandex
Подякували: leofun01, 0xDADA11C72

6

Re: WinAPI Дізнатися розкладку клавіатури

Клавіатурного шпигуна пишете, ліл

7 Востаннє редагувалося -=ЮрА=- (30.04.2016 18:02:54)

Re: WinAPI Дізнатися розкладку клавіатури

Ну от, так-сяк вийшло

- буду відвертим - як на мене повна лажа, раджу ознайомитись про WH_KEYBOARD (тут про хуки https://msdn.microsoft.com/uk-ua/librar … s.85).aspx  ), ще й з КутЕ фрейморком, QString::fromWCharArray(WindowName) - для конвертації вайдів слугує WideCharToMultiByte https://msdn.microsoft.com/uk-ua/librar … s.85).aspx
Якщо йдеться про шпигуна то взагалі маємо на виході ехе, тобто процес у таскменеджері і як ховати будемо назвемо svhost.exe?Коли юзаємо хуки то можемо приховати длл зробивши інжект у потрібний процес.

Подякували: Betterthanyou, leofun012

8

Re: WinAPI Дізнатися розкладку клавіатури

-=ЮрА=- написав:

Ну от, так-сяк вийшло

- буду відвертим - як на мене повна лажа, раджу ознайомитись про WH_KEYBOARD (тут про хуки https://msdn.microsoft.com/uk-ua/librar … s.85).aspx  ), ще й з КутЕ фрейморком, QString::fromWCharArray(WindowName) - для конвертації вайдів слугує WideCharToMultiByte https://msdn.microsoft.com/uk-ua/librar … s.85).aspx
Якщо йдеться про шпигуна то взагалі маємо на виході ехе, тобто процес у таскменеджері і як ховати будемо назвемо svhost.exe?Коли юзаємо хуки то можемо приховати длл зробивши інжект у потрібний процес.

Це не шпигун і не шкідлива програма має буди тому ховати нічого не треба. А що до коду так я й написав що там проблеми (зокрема у визначені української розкладки), я не пропоную цей коди як взірець, я його навів щоб форумчани бачили що я роблю і змогли мені допомогти

9 Востаннє редагувалося -=ЮрА=- (30.04.2016 19:30:22)

Re: WinAPI Дізнатися розкладку клавіатури

Betterthanyou

тоді раджу використати ось цю функцію (гадаю що окрім розкладки може ще щось знадобитись - тобто конкретно ловити чари)
ToAsciiEx  https://msdn.microsoft.com/uk-ua/librar … s.85).aspx
для отримання символів чи їх групи (це прямий транслятор того що було натиснуто з врахуванням конкретного layout)

Тут невиличкий "говнокод" з моєї практики (видрав з длл-ки хука)

short GetSymbolFromVK(WPARAM wParam) // конвертує код натиснутої кнопки у текст
{
    BYTE btKeyState[256];
    HKL hklLayout = GetKeyboardLayout(0); // отримуємо keyboard layout
    WORD Symbol; 
    GetKeyboardState(btKeyState); 
    if((ToAsciiEx(wParam, MapVirtualKey(wParam, 0), btKeyState, &Symbol, 0, hklLayout) == 1) && // сама конвертація
                 GetKeyState(VK_CONTROL) >= 0 && GetKeyState(VK_MENU) >= 0) // перевіряємл CTRL и ALT
        return Symbol;
     return -1;
}

Ну і все ж таки хуки дають безпосердню гарантію що буде "зловлено" усе, бо це механізм нотіфікацій а не перевірки по таймауту (хоча насправді там теж є таймінг  :) )

Подякували: Betterthanyou1

10

Re: WinAPI Дізнатися розкладку клавіатури

0х0409 = United States (US)
аналогічно з RUS 1049 -> 419 = LANG_RUSSIAN
А з UKR почалися проблеми, я отримав -3928 ну і звичайно (unsigned позбавляє від мінуса, але проблему не вирішує) FFFFFFFFFFFFF0A8 немає в таблиці

ніяких проблем немає з отриманням розкладки українського:
http://сайт-злодій/img/img7/fs/ezgif-419445585.1462040530.gif

Підозрюю, ви вийшли за межі розрядної сітки обраних типів.

11

Re: WinAPI Дізнатися розкладку клавіатури

raxp, чим(софтина?) "запілив" таку гіфку з моніка?

12 Востаннє редагувалося Betterthanyou (30.04.2016 23:14:19)

Re: WinAPI Дізнатися розкладку клавіатури

raxp написав:

Підозрюю, ви вийшли за межі розрядної сітки обраних типів.

Але й як ? Я знайшов що shr (в delphi) зсовує на вказану кількість.
тобто "shr 16" теж що і ">> 16"
а дальше код мій і ваш однаковий.
Якщо у вас осталася програма (просто програма exe, а не проект бо в мене немає delphi) будь-ласка скиньте, можливо це щось з моєю ОС ? Чи такого не може бути.

13 Востаннє редагувалося raxp (01.05.2016 07:46:33)

Re: WinAPI Дізнатися розкладку клавіатури

Betterthanyou написав:

а дальше код мій і ваш однаковий.

говорю не за код, а за типи даних обраних вами змінних, яким ви привласнюєте результат. У моєму коді взагалі немає проміжних змінних. Різницю відчуваєте? Поява мінуса в ваших результатах говорить про вихід за розрядну сітку, навіть дивитися на код не треба.

Якщо у вас осталася програма
...
можливо це щось з моєю ОС ?

можливо. Давайте перевiримо, ось.

-=ЮрА=- написав:

raxp, чим(софтина?) "запілив" таку гіфку з моніка?

HyperCam + EZGIF, бо готове.

Звiсно таке можливо й самому, але лiньки. Наприклад BitBlt + GifImage (або GDI+). Щось на кшалт:

var gif: tgifimage;
...
 //у циклi
 BitBlt(bitmap.Canvas.Handle, 0, 0, Screen.Width, Screen.Height,
         GetDC(GetDesktopWindow), 0, 0, SRCCopy);

 GIF.AddFrame(bitmap);

 // end цикла

 ...
 // save
 gif.savetofile('bla-bla-bla.gif');
 ...

GDI+:

var // GDI+
    encoderClsid: TGUID;
    Image: TGPImage;
...
Image := TGPImage.Create(tifpath);
  GetEncoderClsid('image/gif', encoderClsid);
  s:= pansichar(copy(tifpath,1,length(tifpath)-4) + '.gif');
  image.Save(s, encoderClsid, nil);
  image.Free
Подякували: -=ЮрА=-1

14 Востаннє редагувалося -=ЮрА=- (01.05.2016 08:38:07)

Re: WinAPI Дізнатися розкладку клавіатури

HyperCam + EZGIF, бо готове.

  я саме це і хотів дізнатись - imho класна річ коли треба візуалізація процесу на моніку *THUMBSUP*

15 Востаннє редагувалося Betterthanyou (01.05.2016 14:46:44)

Re: WinAPI Дізнатися розкладку клавіатури

raxp написав:

У моєму коді взагалі немає проміжних змінних

Біда в тому що С++ каже що error: invalid operands of types 'HKL' and 'int' to binary 'operator>>' тому і мушу щось видумувати з типами даних, але проблема виявилася не в коді а все таки в ОС
Дивіться скрін
http://replace.org.ua/misc.php?action=pun_attachment&amp;item=1249&amp;download=0
а на ENG i RUS програма реагує адекватно, так само як і моя програма

Post's attachments

Untitled.png 2.17 kb, 222 downloads since 2016-05-01 

16

Re: WinAPI Дізнатися розкладку клавіатури

HKL це LongWord = 4 байта.

Type Range Format:

Shortint -128..127 signed 8-bit
Smallint -32768..32767 signed 16-bit
Longint -2147483648..2147483647 signed 32-bit
Int64 -2^63..2^63-1 signed 64-bit
Byte 0..255 unsigned 8-bit
Word 0..65535 unsigned 16-bit
Longword 0..4294967295 unsigned 32-bit

Що у вас за Windows?
Та 32 або 64bit?

17 Востаннє редагувалося Betterthanyou (01.05.2016 23:21:07)

Re: WinAPI Дізнатися розкладку клавіатури

raxp написав:

Що у вас за Windows?
Та 32 або 64bit?

OS Name    Microsoft Windows 8 Pro (щось в мене 8.1 а також 10 просто жахливо працюють тому не оновлююся, хоча начинка ПК дозволяє)
Version    6.2.9200 Build 9200
System Type    x64-based PC (Процесор теж х64 AMD FX-8320)

А якщо говорити про типи то я побував int 32 bit, а 4 bite * 8 bit = 32 bit. Тобто проблем не має буди з розміром.

18 Востаннє редагувалося -=ЮрА=- (02.05.2016 14:58:59)

Re: WinAPI Дізнатися розкладку клавіатури

Betterthanyou , це з консолі напряму вводимо значення HKL?

'HKL' and 'int' to binary 'operator>>'

cin під стандарт С++ писаний, там просто не має типу HKL
Код під ВІН32

#include <windows.h>
#include <iostream>
using namespace std;

#define DIRECT_HKL 1

int main(){
    HKL  hHKL;
    long lHKL;
    cout<<"HKL : ";
#if DIRECT_HKL
    cin>>hHKL;
#else
    cin>>lHKL;
    memcpy(&hHKL, &lHKL, sizeof(HKL));
#endif
    cout<<sizeof(HKL)<<endl;
    return 0;
}

Якщо поставити дефайн у нуль то все буде норм

Post's attachments

Untitled.png 58.71 kb, 223 downloads since 2016-05-02 

19 Востаннє редагувалося Betterthanyou (02.05.2016 15:04:08)

Re: WinAPI Дізнатися розкладку клавіатури

-=ЮрА=- написав:

Betterthanyou , це з консолі напряму вводимо значення HKL?

ні його повертає функція GetKeyboardLayout -> https://msdn.microsoft.com/uk-ua/librar … s.85).aspx

20

Re: WinAPI Дізнатися розкладку клавіатури

Betterthanyou я написав бо незрозумів чому ти писав про це

error: invalid operands of types 'HKL' and 'int' to binary 'operator>>

, звичайно ж я знаю яка функція поверає цей дескріптор.