<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AutoHotkey: Определение языка ввода, переключение раскладок клавиатуры]]></title>
		<link>http://forum.script-coding.com/viewtopic.php?id=189</link>
		<atom:link href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=189&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AutoHotkey: Определение языка ввода, переключение раскладок клавиатуры».]]></description>
		<lastBuildDate>Sat, 08 Sep 2012 14:41:10 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: AutoHotkey: Определение языка ввода, переключение раскладок клавиатуры]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=63656#p63656</link>
			<description><![CDATA[<p>Определение языка раскладки активного окна:</p><div class="codebox"><pre><code>F11:: MsgBox % GetInputLangName(GetInputLangID(&quot;A&quot;))
 
GetInputLangID(window)  {
   if !hWnd := WinExist(window)
      return

   WinGetClass, winClass
   if (winClass != &quot;ConsoleWindowClass&quot;) || (b := SubStr(A_OSVersion, 1, 2) = &quot;10&quot;)  {
      if b  {
         WinGet, consolePID, PID
         childConhostPID := GetCmdChildConhostPID(consolePID)
         dhw_prev := A_DetectHiddenWindows
         DetectHiddenWindows, On
         hWnd := WinExist(&quot;ahk_pid &quot; . childConhostPID)
         DetectHiddenWindows, % dhw_prev
      }
      threadId := DllCall(&quot;GetWindowThreadProcessId&quot;, Ptr, hWnd, UInt, 0)
      lyt := DllCall(&quot;GetKeyboardLayout&quot;, Ptr, threadId, UInt)
      langID := Format(&quot;{:#x}&quot;, lyt &amp; 0x3FFF)
   }
   else  {
      WinGet, consolePID, PID
      DllCall(&quot;AttachConsole&quot;, Ptr, consolePID)
      VarSetCapacity(lyt, 16)
      DllCall(&quot;GetConsoleKeyboardLayoutName&quot;, Str, lyt)
      DllCall(&quot;FreeConsole&quot;)
      langID := &quot;0x&quot; . SubStr(lyt, -4)
   }
   return langID
}

GetCmdChildConhostPID(CmdPID)  {
   static TH32CS_SNAPPROCESS := 0x2, MAX_PATH := 260
   
   h := DllCall(&quot;CreateToolhelp32Snapshot&quot;, UInt, TH32CS_SNAPPROCESS, UInt, 0, Ptr)
   VarSetCapacity(PROCESSENTRY32, size := 4*7 + A_PtrSize*2 + (MAX_PATH &lt;&lt; !!A_IsUnicode), 0)
   NumPut(size, PROCESSENTRY32, &quot;UInt&quot;)
   res := DllCall(&quot;Process32First&quot;, Ptr, h, Ptr, &amp;PROCESSENTRY32)
   while res  {
      parentPid := NumGet(PROCESSENTRY32, 4*4 + A_PtrSize*2, &quot;UInt&quot;)
      if (parentPid = CmdPID)  {
         exeName := StrGet(&amp;PROCESSENTRY32 + 4*7 + A_PtrSize*2, &quot;CP0&quot;)
         if (exeName = &quot;conhost.exe&quot; &amp;&amp; PID := NumGet(PROCESSENTRY32, 4*2, &quot;UInt&quot;))
            break
      }
      res := DllCall(&quot;Process32Next&quot;, Ptr, h, Ptr, &amp;PROCESSENTRY32)
   }
   DllCall(&quot;CloseHandle&quot;, Ptr, h)
   Return PID
}
 
GetInputLangName(langId)  {
   static LOCALE_SENGLANGUAGE := 0x1001
   charCount := DllCall(&quot;GetLocaleInfo&quot;, UInt, langId, UInt, LOCALE_SENGLANGUAGE, UInt, 0, UInt, 0)
   VarSetCapacity(localeSig, size := charCount &lt;&lt; !!A_IsUnicode, 0)
   DllCall(&quot;GetLocaleInfo&quot;, UInt, langId, UInt, LOCALE_SENGLANGUAGE, Str, localeSig, UInt, size)
   return localeSig
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sat, 08 Sep 2012 14:41:10 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=63656#p63656</guid>
		</item>
		<item>
			<title><![CDATA[Re: AutoHotkey: Определение языка ввода, переключение раскладок клавиатуры]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=29667#p29667</link>
			<description><![CDATA[<p><a href="http://msdn.microsoft.com/en-us/library/dd318693%28VS.85,classic%29.aspx">Идентификаторы локали</a> для сообщения WM_INPUTLANGCHANGEREQUEST (0x50).</p>]]></description>
			<author><![CDATA[null@example.com (teadrinker)]]></author>
			<pubDate>Sat, 24 Oct 2009 09:26:47 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=29667#p29667</guid>
		</item>
		<item>
			<title><![CDATA[Re: AutoHotkey: Определение языка ввода, переключение раскладок клавиатуры]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=29050#p29050</link>
			<description><![CDATA[<p>Выкладываю код скрипта, умеющего делать следующее:</p><p>- Переключать раскладку клавиатуры, а именно: по нажатию клавиши <strong>Caps Lock</strong> - в другую раскладку, правой клавиши <strong>Alt</strong> - в английскую раскладку, правой клавиши <strong>Win</strong> - в русскую раскладку.</p><p>- Выводить tooltip с указанием текущей раскладки, расположенный чуть правее и чуть выше текстового курсора (правда, в некоторых программах tooltip появляется не совсем там (или совсем не там), где этого ожидает пользователь <img src="//forum.script-coding.com/img/smilies/yikes.png" width="15" height="15" /> )</p><p>- Подавать звуковой сигнал при переключении раскладки (вполне возможно, что многих пользователей он будет только раздражать, так что рано или поздно придется придумать способ его отключения без ручного редактирования скрипта <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" /> )</p><p>- Показывать текущую раскладку с помощью иконок в системном трее</p><p>- Обрабатывать нажатия клавиши <strong>Alt</strong> примерно так (с большой натяжкой <img src="//forum.script-coding.com/img/smilies/wink.png" width="15" height="15" /> ), как это делает <strong>Punto Switcher</strong> (правда, пока эта фича работает только в нескольких программах, специально прописанных в скрипте; новые придется добавлять вручную прямо в код скрипта)</p><div class="codebox"><pre><code>; 2009-10-11  
; very simple Russian-English keyboard layout switcher by Lazytech 

; (my script is largely based on other developers&#039; code and ideas;
; special thanks to people at http://forum.script-coding.com/)

; скрипт выполняется бесплатной программой AutoHotkey, которую
; можно скачать с оф. сайта: http://www.autohotkey.com/

; для нормальной работы скрипта следует поместить в одну и ту же папку 
; файл .ahk (собственно скрипт) и все файлы .ico (иконки для индикации
; раскладки в системном трее: &quot;EN&quot;, &quot;RU&quot; и &quot;??&quot;)  

; Caps Lock   -- переключение раскладки клавиатуры для активного окна
; правая Alt  -- включение английской раскладки для активного окна
; правая Win  -- включение русской раскладки для активного окна

; функции клавиши Caps Lock берут на себя сочетания клавиш  
; Ctrl + Caps Lock  и  Shift + Caps Lock

; для того, чтобы можно было заходить в меню программы, чье окно в данный момент 
; активно, с использованием только клавиатуры (по нажатию левой клавиши Alt,
; поскольку правая клавиша Alt уже задействована в данном скрипте для включения
; английской раскладки), придется прописать в коде скрипта заголовки
; соответствующих программ.

#SingleInstance

Loop
{
    Sleep, 300
    WinGet, NewHWND, ID, A
    if (no_detect_window &lt;&gt; -1) and (LastHWND = NewHWND) 
    {
        Continue
    }
    else
    { 
        LastHWND = %NewHWND%
        WinGet, NewPID, PID, A
        if (LastPID = NewPID)
        {
            Continue
        }
        else
        {
            LastPID = %NewPID%
            new_layout := check_en_ru()    
            if (new_layout = &quot;RU&quot;)
            {
                sound_RU() ; если звук не нужен, можно закомментировать
            }    
            else if (new_layout = &quot;EN&quot;)
            {
                sound_EN() ; если звук не нужен, можно закомментировать
            }
            Sleep, 300
        }
    }    
}

~LAlt::
WinGetTitle, AWinTitle, A
WinTitleLen := StrLen(AWinTitle)
; список заголовков окон можно пополнить вручную:
if (SubStr(AWinTitle, WinTitleLen - 9) = &quot; - Блокнот&quot;) &amp;&amp; (check_en_ru() = &quot;EN&quot;)
{
    switch_en_ru(&quot;RU&quot;)
}
; список заголовков окон можно пополнить вручную:
else if (SubStr(AWinTitle, 1, 11) = &quot;Akelpad - [&quot;) || (SubStr(AWinTitle, 1, 10) = &quot;Aditor - [&quot;) || (SubStr(AWinTitle, 1, 10) = &quot;Lister - [&quot;) &amp;&amp; (check_en_ru() = &quot;RU&quot;)
{
    switch_en_ru(&quot;EN&quot;) 
}
Return

sound_RU()
{
    SoundBeep, 200, 30 ; для полного выключения звука закомментируйте
}

sound_EN()
{
    SoundBeep, 5000, 30 ; для полного выключения звука закомментируйте
}

kbd_msg(text)
{
    no_detect_window := -1
    ToolTip, %text%, A_CaretX + 10, A_CaretY - 20
    SetTimer, KbdRemoveToolTip, -1000
    return
    
    KbdRemoveToolTip:
    ToolTip
    no_detect_window := 1
    return
}

check_en_ru_by_window_id(WinID)
{
  SetFormat, Integer, H
  Locale_En := 0x4090409  ; Английский (американский).
  Locale_Ru := 0x4190419  ; Русский.
  ThreadID:=DllCall(&quot;GetWindowThreadProcessId&quot;, &quot;Int&quot;, WinID, &quot;Int&quot;, &quot;0&quot;)
  InputLocaleID:=DllCall(&quot;GetKeyboardLayout&quot;, &quot;Int&quot;, ThreadID)

    if (store_layout &lt;&gt; InputLocaleID)
    {
      if(InputLocaleID = Locale_En)
        {
            Menu tray, icon, en2.ico
        }
      else if(InputLocaleID = Locale_Ru)
        {
            Menu tray, icon, ru2.ico
        }
        else
        {
            Menu tray, icon, __2.ico
        }
    }
    
    store_layout = InputLocaleID

  if(InputLocaleID = Locale_En)
    {
        return &quot;EN&quot;
    }
  else if(InputLocaleID = Locale_Ru)
    {
        return &quot;RU&quot;
    }
    else
    {
      return &quot;??&quot;
    }
}

check_en_ru()
{
  SetFormat, Integer, H
    WinGet, WinID,, A
    return check_en_ru_by_window_id(WinID)    
}

switch_en_ru(set_layout)
{
    old_layout := check_en_ru()

    if (old_layout = set_layout)
    {
        kbd_msg(set_layout)
        EXIT
    }

    if (old_layout = &quot;RU&quot;)
    {
        set_layout := &quot;EN&quot;
    }
    else
    {
        set_layout := &quot;RU&quot;
    }
    
    if (set_layout = &quot;RU&quot;)
    {
        SendMessage, 0x50,, % Locale_RU,, A
        sound_RU()
    }    
    else if (set_layout = &quot;EN&quot;)
    {
        SendMessage, 0x50,, % Locale_EN,, A
        sound_EN()
    }

    new_layout := check_en_ru()    
    kbd_msg(new_layout)
}

; переключение активного окна в другую раскладку
+Capslock::Capslock 
Capslock:: 
switch_en_ru(&quot;&quot;)
Sleep, 300
return

kbd_en()
{
    ; переключение активного окна в английскую раскладку
    PostMessage, 0x50, 0, 0x4090409,, A
    kbd_msg(&quot;EN&quot;)    
}

kbd_ru()
{
    ; переключение активного окна в русскую раскладку
    PostMessage, 0x50, 0, 0x4190419,, A     
    kbd_msg(&quot;RU&quot;)    
}

; переключаем активное окно в английскую раскладку по нажатию клавиши:
RAlt:: switch_en_ru(&quot;EN&quot;) 

; переключаем активное окно в русскую раскладку по нажатию клавиши:
RWin:: switch_en_ru(&quot;RU&quot;)</code></pre></div><p>Также выкладываю Zip-архив (1,6 Кбайт) с 3 иконками (&quot;en2.ico&quot;, &quot;ru2.ico&quot;, &quot;__2.ico&quot;). Художественный вкус у меня так себе, так что можете переделать иконки под свои запросы. Для этого достаточно изменить расширение файла на <strong>bmp</strong>, отредактировать картинку в любом графическом редакторе (хоть в <strong>MS Paint</strong> <img src="//forum.script-coding.com/img/smilies/wink.png" width="15" height="15" /> ) и поменять расширение файла обратно на <strong>ico</strong> <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" /></p><p>Кстати, так и не понял, почему <strong>AHK</strong> иногда ругается на следующую строку:<br /></p><div class="codebox"><pre><code>SetTimer, RemoveToolTip, Off</code></pre></div><p>Закомментировал, пока всё работает <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" /></p><p>P.S. Поправил скрипт - <strong>teadrinker</strong>, благодарю за подсказку!<br />На всякий случай показываю ниже, что именно было исправлено.</p><p>Было:<br /></p><div class="codebox"><pre><code>kbd_msg(text)
{
    no_detect_window := -1
    ToolTip, %text%, A_CaretX + 10, A_CaretY - 20
    SetTimer, KbdRemoveToolTip, 1000
    return
    
    KbdRemoveToolTip:
    ; SetTimer, RemoveToolTip, Off
    ToolTip
    no_detect_window := 1
    return
}</code></pre></div><p>Стало:<br /></p><div class="codebox"><pre><code>kbd_msg(text)
{
    no_detect_window := -1
    ToolTip, %text%, A_CaretX + 10, A_CaretY - 20
    SetTimer, KbdRemoveToolTip, -1000
    return
    
    KbdRemoveToolTip:
    ToolTip
    no_detect_window := 1
    return
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (architech)]]></author>
			<pubDate>Sun, 11 Oct 2009 16:43:25 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=29050#p29050</guid>
		</item>
		<item>
			<title><![CDATA[Re: AutoHotkey: Определение языка ввода, переключение раскладок клавиатуры]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=9283#p9283</link>
			<description><![CDATA[<p>Облагороженный скрипт из поста №2, для определения идентификатора локали ввода.<br />Тогда я ещё был молодой и глупый. <img src="//forum.script-coding.com/img/smilies/wink.png" width="15" height="15" /><br />Последний параметр в вызове GetKeyboardLayout указывает, что возвращаемое функцией число - беззнаковое (UInt). Без этого некоторые идентификаторы отображаются отрицательными числами.<br /></p><div class="codebox"><pre><code>F11::
  SetFormat, Integer, H
  WinGet, WinID,, A
  ThreadID:=DllCall(&quot;GetWindowThreadProcessId&quot;, UInt, WinID, UInt, 0)
  InputLocaleID:=DllCall(&quot;GetKeyboardLayout&quot;, UInt, ThreadID, UInt)
  MsgBox, %InputLocaleID%
Return</code></pre></div><p>Этот код выводит список идентификаторов локалей ввода, между которыми возможно переключение. Вышеупомянутой проблемы здесь нет, т.к. функция NumGet по умолчанию трактует считываемые числа как беззнаковые целые (UInt).<br /></p><div class="codebox"><pre><code>F11::
  Count:=DllCall(&quot;GetKeyboardLayoutList&quot;, UInt, 0, UInt, 0)
  VarSetCapacity(Buf, Count*4)
  DllCall(&quot;GetKeyboardLayoutList&quot;, UInt, Count, UInt, &amp;Buf)
  List:=&quot;&quot;
  SetFormat, Integer, H
  Loop, % Count
    List.=NumGet(Buf, (A_Index-1)*4) . &quot;`n&quot;
  MsgBox, % List
Return</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (YMP)]]></author>
			<pubDate>Wed, 27 Feb 2008 17:41:28 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=9283#p9283</guid>
		</item>
		<item>
			<title><![CDATA[Re: AutoHotkey: Определение языка ввода, переключение раскладок клавиатуры]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=5955#p5955</link>
			<description><![CDATA[<p>Переключение раскладки при удержании клавиши Right Win (по аналогии с клавишей Shift для изменения регистра символов). Работает с двумя языками. Автор скрипта - <strong>YMP</strong>.<br /></p><div class="codebox"><pre><code>RWin::
  PostMessage, 0x50, 2,,, A  ; Переключить язык.
  KeyWait, RWin              ; Ждать отпускания.
  PostMessage, 0x50, 2,,, A  ; Переключить.
Return</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (The gray Cardinal)]]></author>
			<pubDate>Sat, 10 Nov 2007 07:31:47 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=5955#p5955</guid>
		</item>
		<item>
			<title><![CDATA[Re: AutoHotkey: Определение языка ввода, переключение раскладок клавиатуры]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=1464#p1464</link>
			<description><![CDATA[<p>Циклическое переключение между двумя выбранными языками ввода по клавише Control:<br /></p><div class="codebox"><pre><code>~^Shift:: Exit
~+Ctrl:: Exit
Ctrl::
  SetFormat, Integer, H
  Locale1=0x4090409  ; Английский (американский).
  Locale2=0x4190419  ; Русский.
  WinGet, WinID,, A
  ThreadID:=DllCall(&quot;GetWindowThreadProcessId&quot;, &quot;Int&quot;, WinID, &quot;Int&quot;, &quot;0&quot;)
  InputLocaleID:=DllCall(&quot;GetKeyboardLayout&quot;, &quot;Int&quot;, ThreadID)
  if(InputLocaleID=Locale1)
    SendMessage, 0x50,, % Locale2,, A
  else if(InputLocaleID=Locale2)
    SendMessage, 0x50,, % Locale1,, A
Exit</code></pre></div><p>Две горячих клавиши в начале скрипта нужны для предотвращения ложных срабатываний скрипта от нажатий стандартных клавиш Windows для переключения языка. При этом эти стандартные клавиши продолжают работать.<br />Чтобы определить идентификатор локали для произвольного установленного языка, используйте скрипт ниже (клавиша F11). При этом активное окно должно быть переключено на нужный язык:<br /></p><div class="codebox"><pre><code>F11::
  SetFormat, Integer, H
  WinGet, WinID,, A
  ThreadID:=DllCall(&quot;GetWindowThreadProcessId&quot;, &quot;Int&quot;, WinID, &quot;Int&quot;, &quot;0&quot;)
  InputLocaleID:=DllCall(&quot;GetKeyboardLayout&quot;, &quot;Int&quot;, ThreadID)
  MsgBox, %InputLocaleID%
Exit</code></pre></div><p>Скрипты опубликовал <strong>YMP</strong>.</p>]]></description>
			<author><![CDATA[null@example.com (The gray Cardinal)]]></author>
			<pubDate>Sat, 30 Dec 2006 10:13:20 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=1464#p1464</guid>
		</item>
		<item>
			<title><![CDATA[AutoHotkey: Определение языка ввода, переключение раскладок клавиатуры]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=928#p928</link>
			<description><![CDATA[<p>Иногда хочется заменить стандартные Ctrl+Shift или Alt+Shift для переключения языков на свои произвольные комбинации клавиш.<br />Следующий скрипт обеспечивает переключение на английский с помощью <strong>Win+1</strong>, на русский - с помощью <strong>Win+2</strong>. Можно при желании на Win+3 добавить третью раскладку (если такая есть) и т.д.:<br /></p><div class="codebox"><pre><code>#1:: SendMessage, 0x50,, 0x4090409,, A ; английский
#2:: SendMessage, 0x50,, 0x4190419,, A ; русский</code></pre></div><p>Следующий скрипт обеспечивает переключение на английский с помощью <strong>двойного нажатия левого Ctrl</strong>, на русский - <strong>двойного нажатия правого Ctrl</strong>:<br /></p><div class="codebox"><pre><code>~LControl::
If LControl_Presses &gt; 0
{
    LControl_Presses += 1
    Return
}
LControl_Presses = 1
SetTimer, KeyLControl, 300
Return

KeyLControl:
SetTimer, KeyLControl, Off
If LControl_Presses = 2
{
    SendMessage, 0x50,, 0x4090409,, A ; английский
}
LControl_Presses = 0
Return

~RControl::
If RControl_Presses &gt; 0
{
    RControl_Presses += 1
    Return
}
RControl_Presses = 1
SetTimer, KeyRControl, 300
Return

KeyRControl:
SetTimer, KeyRControl, Off
If RControl_Presses = 2
{
    SendMessage, 0x50,, 0x4190419,, A ; русский
}
RControl_Presses = 0
Return</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (The gray Cardinal)]]></author>
			<pubDate>Tue, 24 Oct 2006 11:31:19 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=928#p928</guid>
		</item>
	</channel>
</rss>
