Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.53/47: Рейтинг темы: голосов - 47, средняя оценка - 4.53
46 / 25 / 0
Регистрация: 08.03.2016
Сообщений: 435
1

Как программно определить текущую раскладку клавиатуры?

04.03.2020, 21:11. Показов 9524. Ответов 19
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Хочу написать для себя небольшую программку, которая будет постоянно показывать на экране монитора небольшое окошко, на котором будет высвечиваться текущее время и раскладка клавиатуры ("RU" или "ENG"). Как сделать это окно в стиле TopMost я знаю, как время вывести тоже знаю. А вот как программно определить текущую раскладку клавиатуры? И ещё, как можно ловить события изменения раскладки клавиатуры, чтобы изменения мгновенно отображались?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.03.2020, 21:11
Ответы с готовыми решениями:

Как определить текущую раскладку клавиатуры?
Прошу помочь

Как определить раскладку клавиатуры (язык) в фоновом режиме?
Всем доброго дня суток! Как можно определить раскладку клавиатуры и выводить сообщение, когда...

Программно установить Русскую раскладку клавиатуры (именно установить, не активировать)
Прошу помощи. Необходимо Программно установить Русскую раскладку клавиатуры в английскую версию...

Как получить текущую раскладку клавиатуры?
Пытаюсь получить раскладку активного окна, всегда получаю одно и тоже независимо от переключения...

19
6804 / 2831 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
04.03.2020, 21:33 2
Лучший ответ Сообщение было отмечено Power_Basic как решение

Решение

Цитата Сообщение от Power_Basic Посмотреть сообщение
как программно определить текущую раскладку клавиатуры?
Win API GetKeyboardLayout
если совсем простой код, то вот
Visual Basic
1
2
3
4
5
6
7
Private Declare Function GetKeyboardLayout Lib "user32" (ByVal dwLayout As Long) As Long
 
Private Sub Timer1_Timer()
Dim R As Long
    R = GetKeyboardLayout(0)
    Me.Caption = IIf(R = 67699721, "EN", "RU")
End Sub
Timer1 выставить интервал, который отвечает вашему требованию "мгновенно"
2
46 / 25 / 0
Регистрация: 08.03.2016
Сообщений: 435
05.03.2020, 14:33  [ТС] 3
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Win API GetKeyboardLayout
Спасибо, работает.

Цитата Сообщение от Pro_grammer Посмотреть сообщение
Timer1 выставить интервал, который отвечает вашему требованию "мгновенно"
Как говорится, дарёному коню в зубы не смотрят, но ...
Уж очень это всё-таки как-то ресурсо-затратно вызывать функцию таймера каждые, например, 100 миллисекунд в течении всего дня. Хотя, разумеется, для современного компьютера это как слону дробинка, я согласен, но пресловутый "хороший стиль программирования" подталкивает меня к поиску более рационального решения
Мне почему-то мечталось, что должен быть какой-нибудь способ отлавливать сообщение операционной системы о смене раскладки. Ну есть же в Визуальном Бэйсике всякие хитрые предустановленные объекты - Screen и ему подобные. Неужели ни один из них не умеет ловить событие смены раскладки? Тогда можно было бы именно туда "повесить" наш код, и это было бы гораздо более изящно. Ну или как-нибудь с помощью механизма WinAPI можно было бы организовать такой "отлов"?

На самом деле, для моей простенькой программки, как говорится, "и так сойдёт", но мне уже просто любопытно было бы узнать, существует такая возможность в принципе или нет. Ну будем говорить, сейчас уже даже не для практической цели, а хотя бы для чисто теоретической, с целью обучения.
0
63 / 48 / 12
Регистрация: 28.12.2014
Сообщений: 270
05.03.2020, 15:23 4
Имя окна, получающего оконные сообщения при смене раскладки - "TF_FloatingLangBar_WndTitle", класс окна "CiceroUIWndFrame". По имени окна и классу окна находится хэндл окна, по хэндлу окна находится id потока, которому принадлежит окно, в цепочку обработки сообщений потока устанавливает хук, хук мониторит сообщения, в случае получения сообщения, которое указывает на смены раскладки, хук процедура отправляет уведомления процессу пользовательского приложения, которое в свою очередь, либо просматривает свою очередь сообщений потока и обрабатывает событие смены раскладки клавиатуры, либо делает это через RPC - remote procedure call.
1
46 / 25 / 0
Регистрация: 08.03.2016
Сообщений: 435
05.03.2020, 16:51  [ТС] 5
Цитата Сообщение от IDK Посмотреть сообщение
Имя окна, получающего оконные сообщения при смене раскладки - "TF_FloatingLangBar_WndTitle", класс окна "CiceroUIWndFrame". По имени окна и классу окна находится хэндл окна, по хэндлу окна находится id потока, которому принадлежит окно, в цепочку обработки сообщений потока устанавливает хук, хук мониторит сообщения, в случае получения сообщения, которое указывает на смены раскладки, хук процедура отправляет уведомления процессу пользовательского приложения, которое в свою очередь, либо просматривает свою очередь сообщений потока и обрабатывает событие смены раскладки клавиатуры, либо делает это через RPC - remote procedure call.
Ну это точно из серии "уж лучше бы и не спрашивал", не открывал этот ящик Пандоры
Но в любом случае, спасибо за эту "дорожную карту", буду пробовать разобраться. А то надоело уже постоянно по верхам скользить, хочется уже когда-нибудь и поглубже копнуть
0
6804 / 2831 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
05.03.2020, 18:59 6
Цитата Сообщение от IDK Посмотреть сообщение
Имя окна, получающего оконные сообщения при смене раскладки - "TF_FloatingLangBar_WndTitle", класс окна "CiceroUIWndFrame".
Почему то мне кажется это ненадёжный способ. А если на компе отключена языковая панель, кто то удалил ctfmon.exe из автозагрузки или вообще с компа? А индикацию осуществляет другая программа, у меня например это Punto Switcher.
0
46 / 25 / 0
Регистрация: 08.03.2016
Сообщений: 435
05.03.2020, 23:01  [ТС] 7
Короче, полистал я в интернете материалы на эту тему, полистал, и понял, что это тема для докторской диссертации, за которую мне - простому смертному - лучше не браться вовсе, а, и правда, довольствоваться рабоче-крестьянским таймером

Цитата Сообщение от Pro_grammer Посмотреть сообщение
Почему то мне кажется это ненадёжный способ. А если на компе отключена языковая панель, кто то удалил ctfmon.exe из автозагрузки или вообще с компа? А индикацию осуществляет другая программа, у меня например это Punto Switcher.
У меня сейчас 2 языковых индикатора, расположенных на панели задач - один от системы, второй от Punto Switcher. Но проблема в том, что когда я запускаю IDE визуального бэйсика на своём Windows 10, панель задач почему-то отказывается появляться, как это обычно происходит, когда я подвожу курсор к краю экрана. Обычно-то у меня панель задач убирается автоматически, я к этому уже очень давно привык, и мне это нравится. А тут возникает такая ситуация, что для того, чтобы увидеть индикатор раскладки мне приходится поштучно минимизировать все открытые окна, поскольку они тоже в такие моменты начинают "бастовать", ну или нажимать клавишу "Win", заставляя всё-таки панель задач показаться, но это не удобно совсем, да и раздражает как-то, если честно.

Вот потому-то и появилось желание сделать дополнительное самодельное плавающее окошко с часами и индикатором раскладки. Кстати, мне сейчас пришла мысля, что можно ещё дополнительно при смене раскладки озвучивать голосом диктора текущую раскладку. Это же совсем не сложно будет сделать и должно быть очень удобно вроде бы, надо будет попробовать. Всё-таки зрение-то уже, увы, далеко не идеальное

P.S. Punto Switcher у меня присутствует на компе уже даже и сам не знаю зачем
Автоматическую смену раскладки я уже давным-давно отключил. Использую только Дневник, который иногда реально выручает, ну и ещё "повесил" на сочетание клавиш CTRL + "Б" появление окошка с содержимым всего буфера обмена, что очень удобно, на самом деле.
0
6804 / 2831 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
06.03.2020, 06:40 8
Лучший ответ Сообщение было отмечено Power_Basic как решение

Решение

Цитата Сообщение от Power_Basic Посмотреть сообщение
Вот потому-то и появилось желание сделать дополнительное самодельное плавающее окошко с часами и индикатором раскладки.
Может быть удобно, когда индикатор привязан к курсору.
Есть программа десятилетней давности, написал Пётр aka locm на том форуме. Он пишет на PureBasic правда, но идею можно подхватить, если понравится, программа и исходный код в комплекте:
KlavaState_Cursor.zip

Тоже на таймере индикация, без высших материй.
1
46 / 25 / 0
Регистрация: 08.03.2016
Сообщений: 435
06.03.2020, 17:49  [ТС] 9
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Может быть удобно, когда индикатор привязан к курсору.
Есть программа десятилетней давности, написал Пётр aka locm на том форуме. Он пишет на PureBasic правда, но идею можно подхватить, если понравится, программа и исходный код в комплекте:
KlavaState_Cursor.zip
Тоже на таймере индикация, без высших материй.
Спасибо, идея мне понравилась.
Когда одна раскладка, лампочка ScrollLock на клавиатуре горит, когда другая - погашена. Согласен, удобно. Тогда, по идее, уже и плавающее окно не нужно
И дополнительный индикатор раскладки в трее тоже не нужен, потому что там их и без того уже с изьытком

Но вот чего я не понял. Как следует из названия этой небольшой программки, курсор мыши при изменении раскладки тоже вроде бы должен менять свою форму, или нет? А, в принципе, это было бы удобно, всегда перед глазами текущая раскладка в виде привязанной к ней формы курсора. Да, удобно.
Но у меня не меняет почему-то, хотя пробовал уже и в Windows 10, и в WindowsXP в виртуальном боксе.

Чтобы разобраться в этом вопросе долго пытался просмотреть как-нибудь содержимое файла "cursor.res" в Power Basic'е, но я в таких делах не особо опытный, поэтому ничего из этого не получилось. По идее, там можно такие файлы открывать, но мне как-то никогда раньше не приходилось
А в Визуальном даже и не знаю, имеется ли вообще такая возможность.

Разумеется, я в PureBasic'е более чем слабоват, но, как я понял, по замыслу автора, курсор всё-таки вроде бы должен меняться в зависимости от раскладки:

PureBasic
1
2
SetSystemCursor_(LoadCursor_(GetModuleHandle_(0), 200), #OCR_IBEAM) 
SetSystemCursor_(LoadCursor_(GetModuleHandle_(0), 100), #OCR_IBEAM)
Но за две эти идеи, в любом случае, спасибо.
0
4394 / 2244 / 252
Регистрация: 28.10.2011
Сообщений: 8,576
Записей в блоге: 6
06.03.2020, 18:10 10
Цитата Сообщение от Power_Basic Посмотреть сообщение
Как следует из названия этой небольшой программки, курсор мыши при изменении раскладки тоже вроде бы должен менять свою форму, или нет?
Меняется текстовый курсор, а не тот что в виде стрелки.
1
6804 / 2831 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
06.03.2020, 18:50 11
Вот так это выглядит на примере редактора VB6 в win7 (на win10 не запускал)
Как программно определить текущую раскладку клавиатуры?
1
46 / 25 / 0
Регистрация: 08.03.2016
Сообщений: 435
06.03.2020, 20:07  [ТС] 12
Цитата Сообщение от locm Посмотреть сообщение
Меняется текстовый курсор, а не тот что в виде стрелки.
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Вот так это выглядит на примере редактора VB6 в win7 (на win10 не запускал)
Виноват, сразу не сообразил почему-то
Ну да, работает, удобно, спасибо!

А можно как-нибудь в Визуальном зажигать и гасить лампочку ScrollLock? А то, я смотрю, в Пюре это вобще пара пустяков:

PureBasic
1
ScrollLock(1)
и

PureBasic
1
ScrollLock(0)
А то мне, в принципе, уже даже одной этой лампочки было бы вполне достаточно.
А если в Визуальном это невозможно, тогда как с помощью WinAPI можно добиться такого эффекта?
0
4394 / 2244 / 252
Регистрация: 28.10.2011
Сообщений: 8,576
Записей в блоге: 6
06.03.2020, 21:15 13
Для USB HID клавиатур есть такой код.
PureBasic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
Structure PSP_DEVICE_INTERFACE_DETAIL_DATA
  cbSize.l
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    DevicePath.l
  CompilerElse 
    DevicePath.c
  CompilerEndIf
EndStructure
 
Structure KEYBOARD_INDICATOR_PARAMETERS
  UnitId.u
  LedFlags.u
EndStructure
 
#KEYBOARD_CAPS_LOCK_ON    = 4
#KEYBOARD_NUM_LOCK_ON     = 2
#KEYBOARD_SCROLL_LOCK_ON  = 1
 
#IOCTL_KEYBOARD_SET_INDICATORS = $000B0008
 
EnableExplicit
 
Procedure Open_Key_Device()
  Protected HidGuid.Guid
  Protected devInfoData.SP_DEVICE_INTERFACE_DATA
  Protected *detailData.PSP_DEVICE_INTERFACE_DETAIL_DATA
  Protected Length.l, CurrentIndex.w, hDevInfo
  Protected i, Result, DevicePath.s
  Protected Required, hDevice=0, FlagsAndAttributes = 0
  
  devInfoData\cbSize = SizeOf(SP_DEVICE_INTERFACE_DATA)
  
  CopyMemory(?KeyGuid, @HidGuid, SizeOf(HidGuid))
  
  hDevInfo=SetupDiGetClassDevs_(@HidGuid,0,0, #DIGCF_PRESENT|#DIGCF_DEVICEINTERFACE)
  If hDevInfo=0
    ProcedureReturn 0
  EndIf
    
  For i=0 To 255
    
    Result=SetupDiEnumDeviceInterfaces_(hDevInfo, 0, @HidGuid, i, @devInfoData)
    If Result
      Result = SetupDiGetDeviceInterfaceDetail_(hDevInfo, @devInfoData, 0, 0,@Length, 0)
      *detailData=AllocateMemory(Length)
      *detailData\cbSize=SizeOf(PSP_DEVICE_INTERFACE_DETAIL_DATA)
      Result = SetupDiGetDeviceInterfaceDetail_(hDevInfo, @devInfoData, *detailData, Length+1, @Required, 0)
      
      DevicePath.s=PeekS(@*detailData\DevicePath)
      FreeMemory(*detailData)
      
      If FindString(DevicePath, "rdp_kbd", 1, #PB_String_NoCase)>0
        Continue
      EndIf
      
      hDevice=CreateFile_(@DevicePath, #GENERIC_WRITE, #FILE_SHARE_READ|#FILE_SHARE_WRITE,
                          0, #OPEN_EXISTING, 0, 0)
      
      If hDevice<>#INVALID_HANDLE_VALUE
        SetupDiDestroyDeviceInfoList_(hDevInfo)
        ProcedureReturn hDevice
      EndIf
    Else
      Break 
    EndIf
  Next i
  
  SetupDiDestroyDeviceInfoList_(hDevInfo)
  ProcedureReturn 0
  
  DataSection
    KeyGuid:
    Data.l $884B96C3
    Data.u $56EF, $11D1
    Data.a $BC, $8C, $00, $A0, $C9, $14, $05, $DD
  EndDataSection
EndProcedure
 
Procedure SetLedState(hDev, State)
  Protected Param.KEYBOARD_INDICATOR_PARAMETERS
  Protected nBytes.l
  
  Param\UnitId = 0
  Param\LedFlags = State
  
  DeviceIoControl_(hDev, #IOCTL_KEYBOARD_SET_INDICATORS, @Param, SizeOf(Param), 0, 0, @nBytes, 0)
  
EndProcedure
 
Define hDev=Open_Key_Device()
 
If hDev
  SetLedState(hDev, #KEYBOARD_CAPS_LOCK_ON | #KEYBOARD_NUM_LOCK_ON)
EndIf
1
46 / 25 / 0
Регистрация: 08.03.2016
Сообщений: 435
06.03.2020, 21:50  [ТС] 14
Цитата Сообщение от locm Посмотреть сообщение
Для USB HID клавиатур есть такой код.
Не, ну я на PureBasic'е ничего не понимаю, совершенно не знакомый язык
Вот если бы на PowerBasic'е
0
6804 / 2831 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
06.03.2020, 21:54 15
Цитата Сообщение от Power_Basic Посмотреть сообщение
А если в Визуальном это невозможно, тогда как с помощью WinAPI можно добиться такого эффекта?
Можно много кода написать, как у locm и это очень правильно.
А можно попробовать SendKeys "{SCROLLLOCK}"
Или API имитировать нажатие клавиши на клавиатуре при помощи keybd_event
Почему попробовать? Просто не знаю, как win 10 на это реагирует.
0
4394 / 2244 / 252
Регистрация: 28.10.2011
Сообщений: 8,576
Записей в блоге: 6
06.03.2020, 21:56 16
Если кратко, процедура Open_Key_Device() перечисляет все HID клавиатуры и возвращает дескриптор первой найденной.
Процедура SetLedState() отправляет драйверу клавиатуры сообщение с информацией какие индикаторы нужно включить.

Не по теме:

Цитата Сообщение от Power_Basic Посмотреть сообщение
Вот если бы на PowerBasic'е
Нужно учиться переводить код с разных языков.
В дальнейшем это понадобится.

1
6804 / 2831 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
06.03.2020, 22:51 17
Лучший ответ Сообщение было отмечено Power_Basic как решение

Решение

вот простой код, который включает и выключает индикатор SCROLL LOCK, имитируя нажатие клавиши на клавиатуре:

Visual Basic
1
2
3
4
5
6
7
8
9
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Const VK_SCROLL = &H91
Const KEYEVENTF_KEYUP = &H2
 
Private Sub Command1_Click()
    Call keybd_event(VK_SCROLL, 0, 0, 0)
    Call keybd_event(VK_SCROLL, 0, KEYEVENTF_KEYUP, 0)
 
End Sub
1
46 / 25 / 0
Регистрация: 08.03.2016
Сообщений: 435
07.03.2020, 15:44  [ТС] 18
Цитата Сообщение от Pro_grammer Посмотреть сообщение
вот простой код, который включает и выключает индикатор SCROLL LOCK, имитируя нажатие клавиши на клавиатуре:
Классно! Мне понравилось!
Даже как-то неожиданно, что лампочкой можно вот так вот легко управлять
Беру на вооружение!

Цитата Сообщение от Pro_grammer Посмотреть сообщение
А можно попробовать SendKeys "{SCROLLLOCK}"
Или API имитировать нажатие клавиши на клавиатуре при помощи keybd_event
Почему попробовать? Просто не знаю, как win 10 на это реагирует.
На десятке работает превосходно!

Цитата Сообщение от Pro_grammer Посмотреть сообщение
Можно много кода написать, как у locm и это очень правильно.
Ну да, наверно это очень правильно, но это такой тернистый путь, на который даже и ступить страшно
0
6804 / 2831 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
09.03.2020, 15:20 19
Цитата Сообщение от Power_Basic Посмотреть сообщение
дополнительное самодельное плавающее окошко с часами и индикатором раскладки.
Плюс ещё прибавил индикацию на клавиатуре ScrollLock
Вложения
Тип файла: zip Клавиатуры индикатор.zip (5.8 Кб, 58 просмотров)
1
46 / 25 / 0
Регистрация: 08.03.2016
Сообщений: 435
09.03.2020, 19:40  [ТС] 20
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Плюс ещё прибавил индикацию на клавиатуре ScrollLock
Спасибо, попробовал, работает хорошо.

Возможно я к идее плавающего окона ещё вернусь, если появятся мысли, какую важную информацию надо выводить на экран. Ну например, "Не забудь поздравить тёщу с днём рождения" или что-нибудь ещё в таком роде
Будем считать, что это был очень полезный для меня урок по WinAPI. Вот например, про эту функцию

Visual Basic
1
GetKeyState
я ничего не знал, и поэтому собирался действовать по довольно запутанному алгоритму.
0
09.03.2020, 19:40
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.03.2020, 19:40
Помогаю со студенческими работами здесь

Как получить текущую раскладку клавиатуры для чужого активного окна?
Что нужно передавать в GetKeyboardLayout для того, чтобы получить раскладку активного чужого окна,...

Как программно сменить раскладку клавиатуры
Подскажите пожалуйста, как сменить раскладку клавиатуры на английскую, если в системе установлено...

Как определить раскладку клавиатуры?
Товарищи, подскажите. Как определить какая сейчас раскладка клавиатуры (рус/анг)?

Как определить раскладку клавиатуры консольного приложения?
Привет форумчане! Как определить раскладку клавиатуры консольного приложения?

Программно JS установить раскладку клавиатуры с русского на английский и обратно
Надо программно установить раскладку клавиатуры с русского на английский и обратно (функцию надо на...

Программно эмулировать нажатие клавиш, различая регистр и раскладку клавиатуры
Функция keybd_event корректно воспринимает только большие латинские буквы. Регистр и раскладка...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru