Что нового

[Мышь, клавиатура] Не работает смена раскладки для скрытого окна Autoit

Glum

Новичок
Сообщения
7
Репутация
1
Имею кучку скриптов Autoit, запуск которых осуществляется, как правило, с помощью горячих клавиш, отслеживаемых скриптом AutoHotKey (очень уж удобно и кратко там это реализуется).

Вылезла такая особенность:
- при запуске с помощью AutoHotKey, смена раскладки с помощью
Код:
_WinAPI_SetKeyboardLayout

не работает. При этом, если тот же самый скрипт запустить, например, из Total Commander'а, раскладка нормально меняется.

Не работают также горячие клавиши, назначенные функцией
Код:
GUISetAccelerators

Причем, если для запуска нужной функции существует также кнопка GUI, то после ее нажатия мышью, эти горячие клавиши начинают работать.

Если со 2-й проблемой можно бороться путем однократного нажатия на кнопку GUI, то 1-ю никак не могу преодолеть.

Версия Autoit - 3.3.8.1
Версия WinAPIEx - 3.8

Help me, please!
 

alex33

Скриптер
Сообщения
1,457
Репутация
186
Код:
Global $t = False
TraySetToolTip("Нажмите alt + d для проверки")
ConsoleWrite("@KBLayout = "&@KBLayout&@CRLF)
Local $aRet = DllCall('user32.dll', 'uint_ptr', 'LoadKeyboardLayoutW', 'wstr', '00000409', 'uint', '0x00000101')
ConsoleWrite("return: "&$aRet[0]&@CRLF)
ConsoleWrite("@KBLayout = "&@KBLayout&@CRLF)
HotKeySet("!d", "ShowMessage")
HotKeySet("{ESC}", "_exit")
Func ShowMessage()
If $t Then Return
$t = True
MsgBox(4096, "Сообщение", "Всё работает")
$t = False
EndFunc
Func _exit()
Exit
EndFunc
While 1
Sleep(100)
WEnd
 
Автор
G

Glum

Новичок
Сообщения
7
Репутация
1
alex33,

Большое спасибо, но оказалось, что проблема не в этом. Сразу после смены раскладки стоит inputbox:
Код:
Do
   $Firma=InputBox("Введите название фирмы:"," ", $firma,"",300,150,Default,Default,$hBr)
Until $Firma<>""

;$hBr - это окно браузера



В окне inputbox никак не удается получить русскую раскладку.
Перед ним уже проверяю раскладку так:
Код:
AutoItWinSetTitle('GetTalonToSQL_runned')
$hAutoit=WinGetHandle('GetTalonToSQL_runned')
...
$tmp=Hex(_WinAPI_GetKeyboardLayout($hAutoit),4)
MsgBox(266288,"2", $hAutoit & ",   " & $tmp)


Показывает, что раскладка = 0419, а в инпутбоксе все равно лат. алфавит...
???
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Glum,
1.
Предупреждение За нарушение правил форума (пункт В.11):
Любые отрывки AutoIt кода необходимо заключать в тег [autoit]
autoit.gif
(подробнее), а обычный код соответственно в тег [code]
code.gif
(подробнее). Также большие выдержки текста помещайте под тег [spoiler]
spoiler.gif
(подробнее), там где это поддерживается естественно. Как в случае с названием темы, также короткое и эргономичное сообщение привлекает больше внимания, и шансы на получение конкретного ответа увеличиваются.


С уважением, ваш Модератор.




2. Первый пример, как менять раскладку.
Код:
#include <WinAPIEx.au3>
#include <APIConstants.au3>
#include <GUIConstantsEx.au3>

Global $sTmp, $aLang[3][2] = [['0419', 'RU'],['0409', 'EN'],[-1]], $iInput, $hInput, $iLblLang, $iLblRead, $iBtnRead, $iBtnChangeLang

$sTmp = _WinAPI_GetLocaleInfo($LOCALE_USER_DEFAULT, $LOCALE_IDEFAULTLANGUAGE)
For $i = 0 To 1
	If $aLang[$i][0] = $sTmp Then
		$aLang[2][0] = $i
		ExitLoop
	EndIf
Next
If $aLang[2][0] = -1 Then Exit 13
$sTmp = ''
GUICreate('Test', 200, 140)
$iInput = GUICtrlCreateInput('', 20, 30, 160, 20)
$hInput = GUICtrlGetHandle($iInput)
$iLblLang = GUICtrlCreateLabel($aLang[$aLang[2][0]][1], 20, 2, 30, 20)
$iLblRead = GUICtrlCreateLabel('', 20, 60, 160, 20)
GUICtrlSetBkColor(-1, 0xFFFFFF)
$iBtnRead = GUICtrlCreateButton('Read', 10, 100, 85, 30)
$iBtnChangeLang = GUICtrlCreateButton('Change Lang', 105, 100, 85, 30)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $iBtnChangeLang
			$aLang[2][0] = Not $aLang[2][0]
			GUICtrlSetData($iLblLang, $aLang[$aLang[2][0]][1])
			GUICtrlSetData($iInput, '')
			GUICtrlSetData($iLblRead, '')
			_WinAPI_SetKeyboardLayout($hInput, '0x' &  $aLang[$aLang[2][0]][0])
			GUICtrlSetState($iInput, $GUI_FOCUS)
		Case $iBtnRead
			$sTmp = GUICtrlRead($iInput)
			If $sTmp Then GUICtrlSetData($iLblRead, $sTmp)
	EndSwitch
WEnd
3. Второй пример.
Код:
#include <WinAPIEx.au3>
#include <GUIConstantsEx.au3>

Global $sTmp, $aLang[3][2] = [['0419', 'RU'],['0409', 'EN'],[-1]], $iInput, $hInput, $iLblLang, $iLblRead, $iBtnRead, $iBtnChangeLang

GUICreate('Test', 200, 140)
$iInput = GUICtrlCreateInput('', 20, 30, 160, 20)
$hInput = GUICtrlGetHandle($iInput)
$sTmp = Hex(_WinAPI_GetKeyboardLayout($hInput), 4)
For $i = 0 To 1
	If $aLang[$i][0] = $sTmp Then
		$aLang[2][0] = $i
		ExitLoop
	EndIf
Next
If $aLang[2][0] = -1 Then Exit 13
$sTmp = ''
$iLblLang = GUICtrlCreateLabel($aLang[$aLang[2][0]][1], 20, 2, 30, 20)
$iLblRead = GUICtrlCreateLabel('', 20, 60, 160, 20)
GUICtrlSetBkColor(-1, 0xFFFFFF)
$iBtnRead = GUICtrlCreateButton('Read', 10, 100, 85, 30)
$iBtnChangeLang = GUICtrlCreateButton('Change Lang', 105, 100, 85, 30)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $iBtnChangeLang
			$aLang[2][0] = Not $aLang[2][0]
			GUICtrlSetData($iLblLang, $aLang[$aLang[2][0]][1])
			GUICtrlSetData($iInput, '')
			GUICtrlSetData($iLblRead, '')
			_WinAPI_SetKeyboardLayout($hInput, '0x' &  $aLang[$aLang[2][0]][0])
			GUICtrlSetState($iInput, $GUI_FOCUS)
		Case $iBtnRead
			$sTmp = GUICtrlRead($iInput)
			If $sTmp Then GUICtrlSetData($iLblRead, $sTmp)
	EndSwitch
WEnd
4. Пример смены раскладки в InputBox
Код:
#include <Timers.au3>
#include <WinAPIEx.au3>

Global $iTimer, $sTitle = 'Введите название фирмы', $sName

For $i = 1 To 4
	$iTimer = _Timer_SetTimer(0, 100, '_Change_InputBoxLang')
	$sName = InputBox($sTitle, 'Смена раскладки')
	MsgBox(64, 'Info num ' & $i, $sName)
Next

Func _Change_InputBoxLang($hWnd, $Msg, $iIDTimer, $dwTime)
	Local $h_Wnd, $s_Lang, $h_Edit, $s_Ru = '0419', $s_En = '0409', $s_NewLang, $s_Txt

	$h_Wnd = WinGetHandle('[Title:' & $sTitle & '; Class:#32770]')
	If Not $h_Wnd Then Return
	$h_Edit = ControlGetHandle($h_Wnd, '', '[CLASS:Edit; INSTANCE:1]')
	If Not $h_Edit Then Return
	$s_Lang = Hex(_WinAPI_GetKeyboardLayout($h_Edit), 4)
	Switch $s_Lang
		Case $s_Ru
			$s_NewLang = $s_En
			$s_Txt = 'english'
		Case $s_En
			$s_NewLang = $s_Ru
			$s_Txt = 'русский'
		Case Else
			Return
	EndSwitch
	_WinAPI_SetKeyboardLayout($h_Edit, '0x' & $s_NewLang)
	ControlSetText($h_Wnd, '', $h_Edit, $s_Txt)
	_Timer_KillTimer(0, $iTimer)
	$iTimer = 0
EndFunc   ;==>_Change_InputBoxLang
 

alex33

Скриптер
Сообщения
1,457
Репутация
186
Glum, Вставь код AutoIt в соответствующие теги...
 
Автор
G

Glum

Новичок
Сообщения
7
Репутация
1
Понял, исправился...


Добавлено:
Сообщение автоматически объединено:

madmasles,

Спасибо огромное (4. Пример смены раскладки в InputBox), все понял.
Раньше считал (Yashied вроде писал об этом), что смена раскладки у скрытого окна Autoit ведет к смене раскладки дочерних инпутбоксов.

Насчет 2-го вопроса (про несрабатывание гор. клавиш GUISetAccelerators у GUI, созданного скриптом, запущенным из AutoHotKey) надо открывать отдельную тему?
 
Автор
G

Glum

Новичок
Сообщения
7
Репутация
1
madmasles,

Дело в том, что у меня стоит в начале скрипта такой код:

Код:
Global $hAutoit=WinGetHandle(AutoItWinGetTitle())
...
If Hex(_WinAPI_GetKeyboardLayout($hAutoit),4)<>Hex(0x0409,4) Then
      _WinAPI_SetKeyboardLayout($hAutoit, 0x0409)
EndIf


Не помогает, однако. Т.е. с раскладкой все в порядке, но гор. клавиши, назначенные по GUISetAccelerators, не работают, пока не нажмешь кнопку мышью.


Только что обнаружил такую вещь - там у меня идет создание GUI:

Код:
$Form1 = GUICreate( $Form1_Caption, $DesktopWidth-30 , $DesktopHeight-85, -1, -1)
...
GUISetState()

While 1 ; это цикл опроса нажатий
   $nMsg = GUIGetMsg()
...


В общем, если где-то, в любом месте до этого цикла поставить MsgBox (с любыми параметрами), потом, при работе скрипта, когда MsgBox убирается (по нажатию к-л кнопки), гор. клавиши нормально работают.
Пробуя дальше, обнаружил, что также помогает переключение на другое окно Windows с последующим возвратом на окно скрипта (Alt+Tab либо мышью).

Видимо, дело в потере какого-то фокуса...

Попробовал после GUISetState() ставить Winactivate($Form1), GUISetState(@SW_SHOWNORMAL) - не помогает.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Glum
А у вас в GUISetAccelerators какие буквы используются?
 
Автор
G

Glum

Новичок
Сообщения
7
Репутация
1
Даже не буквы - F1, F2, и др. "F...".
 

alex33

Скриптер
Сообщения
1,457
Репутация
186
Код:
#NoTrayIcon
#include <GUIConstants.au3>
$gui1 = GUICreate("test", 300, 200, 1, 1)
$label1 = GUICtrlCreateLabel("Keys: F1, F2, F3", 20, 40, 90, 30)
; set hot keys
$dummy1 = GUICtrlCreateDummy()
$dummy2 = GUICtrlCreateDummy()
$dummy3 = GUICtrlCreateDummy()
Local $aKey[3][2] = [["{F1}", $dummy1],["{F2}", $dummy2],["{F3}", $dummy3]]
;~ Local $aRet = DllCall('user32.dll', 'uint_ptr', 'LoadKeyboardLayoutW', 'wstr', '00000409', 'uint', '0x00000101')
GUISetAccelerators($aKey)
; end set hot keys
GUISetState(@SW_SHOW, $gui1)

While 1
Switch(GUIGetMsg())
Case $GUI_EVENT_CLOSE
ExitLoop

Case $dummy1
test1()

Case $dummy2
test2()

Case $dummy3
test3()
EndSwitch
WEnd
GUIDelete($gui1)

Func test1()
MsgBox(4096, "Тест1", "Сработала функция один", 30)
EndFunc

Func test2()
MsgBox(4096, "Тест2", "Сработала функция два", 30)
EndFunc

Func test3()
MsgBox(4096, "Тест3", "Сработала функция три", 30)
EndFunc
У меня всё работает без проблем, с цифрами, буквами и F1, F2, F3 ...
 
Автор
G

Glum

Новичок
Сообщения
7
Репутация
1
Напомню, у меня запуск скриптов осуществляется с помощью горячих клавиш, отслеживаемых скриптом AutoHotKey. При прямом запуске скриптов из файл-менеджеров все работает нормально.
Получается, что каким-то образом теряется фокус... Причем кликанье мышкой по GUI не помогает, работа гор. клавиш восстанавливается в след. случаях (которые я смог выявить):
- если Alt+Tab переключиться на другое окно, а затем снова на GUI - т. е., если свернуть, а затем развернуть окно GUI
- если хотя бы 1 раз нажать кнопку в GUI (мышью, или Tab'ом, а затем Enter)
- если вставить в скрипт MsgBox, потом закрыть его (например, кнопкой Ok или Отмена - не важно)

Получается, что при выполнении одного из этих условий, GUI получает какой-то "нужный" фокус, и все работает нормально.

Это, конечно, не глобальная проблема, можно и мышкой тыкать, или скрипты запускать чем-нибудь еще, но не хотелось бы отказываться от использования AutoHotKey - обработка горячей клавиши там занимает всего 1 строку, к примеру:

Код:
^F8:: Run, %ProgramFiles%\AutoIt3\AutoIt3.exe "d:\_Projects\_Projects AutoIt\CheckLinksSQL.au3"
!F8:: Run, %ProgramFiles%\AutoIt3\AutoIt3.exe "d:\_Projects\_Projects AutoIt\Links_FF.au3"
 
Верх