Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   [решено] Как поменять раскладку клавиатуры через AutoIt на заданную? (http://forum.oszone.net/showthread.php?t=156073)

evg64 07-11-2009 09:47 1263765

Как поменять раскладку клавиатуры через AutoIt на заданную?
 
Добрый день! Вариант send("!+") не подойдет, потому что нужно определить, какая раскладка у клавиатуры в данный момент, а потом высылать "!+" 1 или 0 раз.
Лучше же всего вообще обойтись без send.
Как взаимодействовать с языковой панелью у меня нет даже идеи)

Вообще задача такая:

Код:

... ; запомнить, какой была ракладка до начала "махинаций"
$str1=inputbox("1","2", "") ; при вводе в этот инпутбокс сделать раскладку английской
$str2=inputbox("1","2", "") ; при вводе в этот инпутбокс сделать раскладку русской
... ; вернуть ракладку в первоначальное состояние


kaster 07-11-2009 10:49 1263783

Код:

Global $Rus = '00000419'; Раскладка русского языка
Global $Eng = '00000409'; Раскладка английского языка
Global $hWnd = WinGetHandle('AutoIt Help'); Находишь хендл своего окна
$def_lang = _WinAPI_GetKeyboardLayout($hWnd); Запоминаешь раскладку до "махинаций"
_WinAPI_SetKeyboardLayout($Rus, $hWnd); Ставишь язык на русским и делаешь что-то
_WinAPI_SetKeyboardLayout($Eng, $hWnd); Ставишь язык на английский и делаешь что-то
_WinAPI_SetKeyboardLayout($def_lang, $hWnd); Ставишь язык на начальный

Func _WinAPI_GetKeyboardLayout($hWnd)
        Local $Ret = DllCall('user32.dll', 'long', 'GetWindowThreadProcessId', 'hwnd', $hWnd, 'ptr', 0)
        If (@error) Or ($Ret[0] = 0) Then
                Return SetError(1, 0, 0)
        EndIf
        $Ret = DllCall('user32.dll', 'long', 'GetKeyboardLayout', 'long', $Ret[0])
        If (@error) Or ($Ret[0] = 0) Then
                Return SetError(1, 0, 0)
        EndIf
        Return '0000' & Hex($Ret[0], 4)
EndFunc  ;==>_WinAPI_GetKeyboardLayout

Func _WinAPI_SetKeyboardLayout($sLayout, $hWnd)
        If Not WinExists($hWnd) Then
                Return SetError(1, 0, 0)
        EndIf
        Local $Ret = DllCall('user32.dll', 'long', 'LoadKeyboardLayout', 'str', StringFormat('%08s', StringStripWS($sLayout, 8)), 'int', 0)
        If (@error) Or ($Ret[0] = 0) Then
                Return SetError(1, 0, 0)
        EndIf
        DllCall('user32.dll', 'ptr', 'SendMessage', 'hwnd', $hWnd, 'int', 0x0050, 'int', 1, 'int', $Ret[0])
        Return SetError(0, 0, 1)
EndFunc  ;==>_WinAPI_SetKeyboardLayout


Yashied 07-11-2009 15:31 1263935

@kaster

В последней версии WinAPIEx.au3 уже используются не строковые значения для указания языка, а целочисленные - LCID константы.

:)

kaster 07-11-2009 15:36 1263937

Yashied, да, это я уде опосля понял нашел в твое либе эти функции. а то что привел выше это из оффорума. наглец даже не указал откуда взял :teeth:

evg64 08-11-2009 17:54 1264929

А как быть, если я создаю inputbox, в нем по умолчанию язык станет русским. Как поменять на английский?
Если так:

Код:

_WinAPI_SetKeyboardLayout($hWnd, $Eng)
inputbox(1,1)

то невозможно правильно указать $hWnd. Если так:
Код:

inputbox(1,1)
_WinAPI_SetKeyboardLayout($hWnd, $Eng)

то сначала исчезнет инпутбокс...

Попробовал поменять так:

читать дальше »
Код:

#include <File.au3>
; Декларируем константы
Global $Rus = 0x0419
Global $Eng = 0x0409
Global $Chn = 0x0804
Global $InputBoxTitle = "InputBox"

; код файла, который запустим
$Code='#Include <WinAPIEx.au3>' & @CRLF & _
'Global $Rus = 0x0419' & @CRLF & _
'Global $Eng = 0x0409' & @CRLF & _
'Global $Chn = 0x0804 '& @CRLF & _
'Global $InputBoxTitle = "InputBox"'& @CRLF & _
'WinWait ($InputBoxTitle)'& @CRLF & _
'Global $hWnd = WinGetHandle($InputBoxTitle, "")'& @CRLF & _
'$def_lang = _WinAPI_GetKeyboardLayout($hWnd)'& @CRLF & _
'_WinAPI_SetKeyboardLayout($hWnd, $Eng)'
'WinSetTitle($hWnd,"","123321")' ; это чтобы знать, что $hWnd найден верно


$FilePath=@DesktopDir & "\ChangeLang.au3"
_FileCreate( $FilePath) ; создаем файл
FileWrite( $FilePath,$Code) ; пишем туда $code
ShellExecute($FilePath) ; запускаем его, по идее он должен дождаться окна с заголовком "InputBox" и поменять там язык на английский
inputbox($InputBoxTitle,1)
FileDelete ($FilePath) ; удаляем файл


но что-то не меняется, а ошибки не вижу.

beve 08-11-2009 22:02 1265139

Раньше я делал переключение расскладки клавиатуры, и заметил одно, что в таких окнах (если это окно на данный момент активно), как inputbox, или в окне Запуск программы (если нажать Пуск --> Выполнить), в Диспетчере задач windows и еще в некоторых, переключение расскладки с помощью такого способа (имеется ввиду способ описанный в примере kasterа или с помощью этого же способа, но использования библиотеки WinAPIEx.au3) не работает (Windows наверно думает что она умнее и поэтому расскладка клавиатуры в таких окнах не изменяется :( ), жалко что расскладку таким образом можно менять только в отдельном окне, хенд которого узнается, а не вобще, ибо если бы было что то наподобие как в windows меняется расскладка (shift+alt у меня), то было бы гораздо проще. А так поменял расскладку в каком то окне, запустил inputbox, а windows бах, и поставила какая до этого была установлена раскладка с помощью тех таки клавиш (shift+alt)... а другого способа наверное нет?.......

kaster 08-11-2009 22:44 1265172

Т.к. в AutoIt нет многопоточности, могу посоветовать перед запуском InputBox запустить еще один скрипт, которые будет ждать окна с нужным заголовком, а после того, как дождется, поменяет там раскладку.
Примерно так.
Готовишь вспомогательный скрипт следующего содержания
Код:

Global $Rus = '00000419'; Раскладка русского языка
Global $Eng = '00000409'; Раскладка английского языка
While 1
        If WinExists('InputBoxTitle', '') Then
                $hWnd = WinGetHandle('InputBoxTitle', '')
                ;MsgBox(0, '', 'Got it')
                _WinAPI_SetKeyboardLayout($Rus, $hWnd)
                ExitLoop
        EndIf
        Sleep(100)
WEnd

Func _WinAPI_GetKeyboardLayout($hWnd)
        Local $Ret = DllCall('user32.dll', 'long', 'GetWindowThreadProcessId', 'hwnd', $hWnd, 'ptr', 0)
        If (@error) Or ($Ret[0] = 0) Then
                Return SetError(1, 0, 0)
        EndIf
        $Ret = DllCall('user32.dll', 'long', 'GetKeyboardLayout', 'long', $Ret[0])
        If (@error) Or ($Ret[0] = 0) Then
                Return SetError(1, 0, 0)
        EndIf
        Return '0000' & Hex($Ret[0], 4)
EndFunc  ;==>_WinAPI_GetKeyboardLayout

Func _WinAPI_SetKeyboardLayout($sLayout, $hWnd)
        If Not WinExists($hWnd) Then
                Return SetError(1, 0, 0)
        EndIf
        Local $Ret = DllCall('user32.dll', 'long', 'LoadKeyboardLayout', 'str', StringFormat('%08s', StringStripWS($sLayout, 8)), 'int', 0)
        If (@error) Or ($Ret[0] = 0) Then
                Return SetError(1, 0, 0)
        EndIf
        DllCall('user32.dll', 'ptr', 'SendMessage', 'hwnd', $hWnd, 'int', 0x0050, 'int', 1, 'int', $Ret[0])
        Return SetError(0, 0, 1)
EndFunc  ;==>_WinAPI_SetKeyboardLayout

Он будет непрерывно мониторить нужное тебе окно. Как только оно появится, немедленно поменяет в нем раскладку на нужную. Вот к примеру нужное
Код:

InputBox('InputBoxTitle', 'Russian text')
Аналогично можешь ставить какую угодно раскладку, и совершенствовать скрипт для мониторинга под свои нужны. Это первое что пришло в голову

Yashied 09-11-2009 16:06 1265767

Все намного проще. Для изменения раскладки для любого окна созданного в AutoIt (в том числе и InputBox()), нужно изменить раскладку для скрытого окна AutoIt.

Код:

AutoItWinSetTitle('MyAutoItTitle')
_WinAPI_SetKeyboardLayout(WinGetHandle(AutoItWinGetTitle()), 0x0419)
InputBox(...)


kaster 09-11-2009 16:21 1265779

все гениальное просто :yes:

Yashied 09-11-2009 17:04 1265825

На самом деле это не есть хорошо. При смене раскладки клавиатуры системой посылаются сообщения WM_INPUTLANGCHANGE..., так вот, AutoIt окна, те что созданы с помощью GUICreate(), эти сообщения не обрабатывают. Только скрытое окно. В этом можно убедиться, применив _WinAPI_SetKeyboardLayout() к любому AutoIt-овскому окну, ничего не произойдет.

kaster 09-11-2009 17:38 1265866

Странно, но в случае, описанном мною пару постов выше (#7), там где два скрипта запущены, то есть один мониторит, другое окно - цель, так вот там все норм меняется. или чего то недопонял :)

Yashied 09-11-2009 17:42 1265872

Я про GUICreate().

Creat0R 09-11-2009 22:08 1266125

Забавно что даже такой скрипт не работает:

Код:

Run(@AutoItExe & ' /AutoIt3ExecuteLine "InputBox(''My InputBox'', ''Prompt'')"')

WinWait("My InputBox")
_WinAPI_SetKeyboardLayout(0x0419, WinGetHandle("My InputBox"))


Yashied 10-11-2009 01:18 1266250

Код:

_WinAPI_SetKeyboardLayout(0x0419, WinGetHandle("My InputBox"))
Он и не должен работать.

Код:

_WinAPI_SetKeyboardLayout(WinGetHandle("My InputBox"), 0x0419)

evg64 15-11-2009 14:55 1270873

Оказывается действительно надо было просто поменять раскладку скрытого AutoIt окна :)


Время: 23:57.

Время: 23:57.
© OSzone.net 2001-