26

Re: AHK: Замена стандартного элемента управления "Hotkey"

А теперь нажатые модификаторы при деактивации не залипают?

Вроде как нет. Но в воздухе летает что то потустороннее. Как то подглючивает, но пока не могу выразить.
---
И ещё, запись хоткеев как vk sc кода работает не для всех кнопок:

vk26sc148:: MsgBox Up ; Кнопка вверх. Она такая не одна.

надо бы как то по другому их записывать

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

27

Re: AHK: Замена стандартного элемента управления "Hotkey"

serzh82saratov пишет:

Но в воздухе летает что то потустороннее.

Ага, нашёл там ошибочку, исправил уже.

И ещё, запись хоткеев как vk sc кода работает не для всех кнопок:

Да, у меня на цифровой клавиатуре тоже срабатывает. Надо подумать.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

28

Re: AHK: Замена стандартного элемента управления "Hotkey"

Этот вариант работает у вас на х64?

+ открыть спойлер

#SingleInstance Force
Gui, Add, Edit, Center ReadOnly w300 gShow vMyHotkey1 
HF_Hotkey( "MyHotkey1")
Gui, Show
return

Show:  
    Gui Show, , %  A_GuiControl " = " %A_GuiControl% 
    return
    
GuiClose:
    ExitApp
   

HF_Hotkey(HF_Control)  { ;***
    Global
    Loop, Parse, HF_Control, |
    {
        RegExMatch(A_LoopField, "S)(.*:)?\s*(.*)", HF_D)
        GuiControlGet, HF_D3, % HF_D1 "Hwnd", % HF_D2
        HF_D3 := Ceil(HF_D3), HF_Control_%HF_D3% := HF_D2
    }
    If !HF_IsStart 
    {
        SetBatchLines -1
        #InstallKeybdHook
        #InstallMouseHook
        #HotkeyInterval 200
        #MaxHotkeysPerInterval 200
        HF_MButtons := {"vkA4":"Alt","vkA5":"Alt","vkA2":"Ctrl","vkA3":"Ctrl","vkA0":"Shift","vkA1":"Shift","vk5B":"Win","vk5C":"Win"}
        HF_P := {"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
        HF_Buttons := "|vkBA|vkBB|vkBC|vkBD|vkBE|vkBF|vkC0|vkDB|vkDC|vkDD|vkDE|vk41|vk42|vk43|vk44|vk45|vk46|vk47|vk48"
                    . "|vk49|vk4A|vk4B|vk4C|vk4D|vk4E|vk4F|vk50|vk51|vk52|vk53|vk54|vk55|vk56|vk57|vk58|vk59|vk5A|"     ; 37 Letter Buttons 
        HF_PressName := "WheelRight|WheelLeft|MButton|WheelDown|WheelUp|XButton1|XButton2" 
        #IF HF_State
        #IF
        Hotkey, IF, HF_State 
        Loop, Parse, HF_PressName, |
            Hotkey, %A_LoopField%, HF_PressName, P3 UseErrorLevel
        Loop, 128
            Hotkey % ((A_Index-1)//32)+1 "Joy" Mod(A_Index-1,32)+1, HF_PressName, P3 UseErrorLevel
        Hotkey, IF  
        OnExit, HF_Exit 
        OnMessage(0x111, "HF_WaitControl")
        HF_IsStart := 1
    }
    Return 
    
    HF_PressName: 
        HF_KeyName := HF_Hotkey := A_ThisHotkey , HF_DelStr := ""
        HF_Prefix := HF_PCtrl HF_PAlt HF_PShift HF_PWin
        %HF_ControlVarName% := HF_Prefix HF_Hotkey
        HF_WriteText := HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName = ""
        ? "Нет" : HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName
        SendMessage, 0xC, 0, &HF_WriteText, , ahk_id %HF_ControlHandle%
        Return 
        
    HF_Exit:
        DllCall("UnhookWindowsHookEx", Ptr, HF_State)
        Send {LButton Up}{LCtrl Up}{RCtrl Up}{LShift Up}{RShift Up}{LAlt Up}{RAlt Up}{LWin Up}{RWin Up}
        ExitApp
} ;**

HF_WaitControl( HF_Param, HF_Handle) { ;***
    Global 
    If HF_Control_%HF_Handle% <>
    {
        If (HF_Param >> 16 = 0x100)    ;    EN_SETFOCUS
        {
            HF_ControlVarName := HF_Control_%HF_Handle%
            HF_ControlHandle := HF_Handle
            HF_State := DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
                                , Int, 13    ;    13 - WH_KEYBOARD_LL
                                , Ptr, RegisterCallback("HF_Write", "Fast")
                                , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
                                , UInt, 0, Ptr)
            HF_DelStr := ""
            PostMessage,0x00B1,,,, ahk_id %HF_ControlHandle%    ;    EM_SETSEL := 0x00B1
            Send, {LButton Up}
            Return
        }
        If (HF_Param >> 16 = 0x200)    ;    EN_KILLFOCUS
        {
            DllCall("UnhookWindowsHookEx" , Ptr, HF_State)
            HF_MCtrl := HF_MAlt := HF_MShift := HF_MWin := HF_Prefix := HF_State := ""
            HF_PCtrl := HF_PAlt := HF_PShift := HF_PWin := ""
            If (HF_DelStr = 1)
                SendMessage, 0xC, 0, "Нет", , ahk_id %HF_ControlHandle%
            Send {LShift Up}{RShift Up}
            Return
        }
    }
    If (HF_Param >> 16 = 0x200)    ;    EN_KILLFOCUS
    { 
        DllCall("UnhookWindowsHookEx", Ptr, HF_State)
        HF_MCtrl := HF_MAlt := HF_MShift := HF_MWin := HF_Prefix := HF_State := ""
        HF_PCtrl := HF_PAlt := HF_PShift := HF_PWin := ""
        Send {LShift Up}{RShift Up}
    }
    Return
} ;**

HF_Write(HF_nCode, HF_wParam, HF_lParam)  { ;***
    Global 
    SetFormat, IntegerFast, H
    HF_VkCode := "vk" SubStr( NumGet(HF_lParam+0, 0, "UInt"), 3)  
        HF_D := NumGet(HF_lParam+0, 8, "UInt") & 1
        HF_D := HF_D << 8 | NumGet(HF_lParam+0, 4, "UInt") 
    HF_SCCode := "sc" SubStr(HF_D, 3)
    IF (HF_wParam = 0x100 || HF_wParam = 0x104)    ;    WM_KEYDOWN := 0x100, WM_SYSKEYDOWN := 0x104
    {
        IF HF_IsMod := HF_MButtons[HF_VkCode]
            GoTo, HF_PressMod
        GoTo, HF_Write
    }
    IF HF_IsMod := HF_MButtons[HF_VkCode]
        GoTo, HF_PressMod_Up
    Return 1

    HF_PressMod_Up:
        HF_M%HF_IsMod% := HF_P%HF_IsMod% := ""
        If ( HF_Hotkey != "" )
            Return 1
        GoTo, HF_Write

    HF_PressMod:
        If ( HF_M%HF_IsMod% != "" )
            Return 1
        HF_M%HF_IsMod% := HF_IsMod "+" , HF_P%HF_IsMod% := HF_P[HF_IsMod]

    HF_Write:
        ( HF_IsMod != "" ) ? ( HF_KeyName := HF_Hotkey := HF_Prefix := "" , HF_DelStr := 1 )
        : ( HF_KeyName := GetKeyName(HF_VkCode HF_SCCode) , HF_DelStr := ""
        , HF_Hotkey := InStr(HF_Buttons, "|" HF_VkCode "|") ? HF_VkCode : HF_KeyName
        , HF_Prefix := HF_PCtrl HF_PAlt HF_PShift HF_PWin )
        %HF_ControlVarName% := HF_Prefix HF_Hotkey
        HF_WriteText := HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName = "" ? "Нет" 
        : HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName
        SendMessage, 0xC, 0, &HF_WriteText, , ahk_id %HF_ControlHandle%
        Return 1
} ;**

    ; -------------------------------------- Read --------------------------------------

HF_Read(Key, Section, Path) { ;***
    Global HF_DelStr := ""
    IniRead, Key, % Path, % Section, % Key, % A_Space
    If Key =
        Return "Нет" 
    Return    HF_ReadVar(Key)
} ;**

HF_ReadVar(Key) { ;***
    RegExMatch(Key, "S)^([\^\+!#]*)\{?(.*?)}?$", K)
    Return    (InStr(K1,"^")?"Ctrl+":"")(InStr(K1,"!")?"Alt+":"")
            . (InStr(K1,"+")?"Shift+":"")(InStr(K1,"#")?"Win+":"")
            . (InStr(K2,"vk") ? GetKeyName(K2) : K2)
} ;**

HF_ReadToSend(Key, Section = "", Path = "") { ;***
    If (Section <> "")
        IniRead, Key, % Path, % Section, % Key, % A_Space
    Return RegExReplace( Key, "S)[^\^!\+#].*", "{$0}")
} ;** 
По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

29

Re: AHK: Замена стандартного элемента управления "Hotkey"

Со СТРАШНЫМИ глюками.
Если нажать модификатор и отпустить, не нажимая завершающий символ, затем кликнуть мышью по нижележащему окну, твоё остаётся на поверхности, и активируется снова. Вторым кликом утопить его удаётся. Если же кликнуть мышью вне его, удерживая модификаторы, окно вообще невозможно деактивировать. К тому же, в нём остается один из модификаторов с плюсом. После выхода из программы остаются залипшими ранее нажатые модификаторы.

А у тебя же тоже Win7 64, у тебя лучше работает?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

30

Re: AHK: Замена стандартного элемента управления "Hotkey"

Мой вариант с исправленными недостатками:

Gui, Add, Edit, hwndhEdit1 gHotkey w150 h20 Center
Gui, Add, Edit, hwndhEdit2 gHotkey w150 h20 Center
Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show

global InfoArray := {}   ; будем использовать глобальный массив для передачи информации
HotkeyInit(hEdit1, hEdit2)   ; передаём в функцию хендлы нужных контролов через запятую
return

Hotkey:
   if (InfoArray.HK = "")
      return
   
   GuiControl, %A_Gui%:, ShowHotkey, % InfoArray.HK
   InfoArray.HK := ""
;  Hotkey, % HotkeyString, HKLabel, On   ; раскомментировать для установки хоткея
   return
   
HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(handles*)
{
   InfoArray := {handles: handles}
   
   hGui := DllCall("GetParent", Ptr, handles.1, Ptr)
   ControlGetFocus, FocusedClassNN, ahk_id %hGui%
   GuiControlGet, FocusedHwnd, %hGui%:Hwnd, % FocusedClassNN
   
   for k,v in handles
   {
      ControlSetText,, Нет, % "ahk_id" v
      if (FocusedHwnd = v)
         InfoArray.hHook := SetWindowsHookEx()
            , InfoArray.hControl := v
   }
   
   SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , prevMessage, prevKey, EndKey
   
   SetBatchLines, -1
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt")
   vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))

   if (Message = prevMessage && key = prevKey)
      Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
   prevMessage := Message, prevKey := key
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   if (sc = 0x145)
      key := "NumLock"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         if EndKey
            InfoArray.keys := EndKey := ""
         
         if !InStr(InfoArray.keys, key)
            InfoArray.keys := key . " + " . InfoArray.keys
      }
      else
      {
         if (SubStr(InfoArray.keys, -1) = "+ " || InfoArray.keys = "")
            InfoArray.keys .= key
         else
            InfoArray.keys := RegExReplace(InfoArray.keys, "(.*?)\S+$", "$1" key)
         
         InfoArray.EndKey := "vk" . SubStr(vk, 3)  . "sc" . SubStr(sc, 3)
      }
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         InfoArray.keys := RegExReplace(InfoArray.keys, key . " \+ ")
      else if (InfoArray.keys != "")
         EndKey := 1
         
      if !EndKey
         SetTimer, SetText, -10
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   SetTimer, SetText, -10
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   keys := InfoArray.keys
   if (keys != "" && keys != "Нет" && Substr(keys, -1) != "+ ")
   {
      String := RegExReplace(keys, "\s")
      Loop, parse, String, +
      {
         IsSym := ""
         for k,v in {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
            if InStr(A_LoopField, k) && A_LoopField != "CtrlBreak"
               HKString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         if !IsSym
         {
            if StrLen(A_LoopField) > 1
            {
               if InStr(A_LoopField, "Num")
                  HKString .= RegExReplace(InfoArray.EndKey, ".*(s.*)", "$1")
               else
                  HKString .= A_LoopField
            }
            else
               HKString .= RegExReplace(InfoArray.EndKey, "(.*)s.*", "$1")
         }
      }
      InfoArray.HK := HKString
   }
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" InfoArray.hControl
   return
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   for k,v in InfoArray.handles
      if (hwnd = v)
         IsValue := 1, InfoArray.hControl := v
   
   if (IsValue && !InfoArray.hHook)
      InfoArray.hHook := SetWindowsHookEx()
   else if (!IsValue && InfoArray.hHook)
   {
      DllCall("UnhookWindowsHookEx", Ptr, InfoArray.hHook)
      InfoArray.keys := InfoArray.hHook := ""
      
      for k,v in InfoArray.handles
      {
         ControlGetText, Text,, ahk_id %v%
         if SubStr(Text, -1) = "+ "
            ControlSetText,, Нет, ahk_id %v%
      }
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

31

Re: AHK: Замена стандартного элемента управления "Hotkey"

Со СТРАШНЫМИ глюками.

Ага и у меня также. Более того после работы такого чуда перестают работать все хоткеи АНК Ничего не пойму. Подскажи, что за...

Мой вариант с исправленными недостатками:

Теперь хорошо. Что то такое ещё есть... но чуть чуть.

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

32

Re: AHK: Замена стандартного элемента управления "Hotkey"

serzh82saratov пишет:

Более того после работы такого чуда перестают работать все хоткеи АНК

teadrinker пишет:

После выхода из программы остаются залипшими ранее нажатые модификаторы.

serzh82saratov пишет:

Что то такое ещё есть... но чуть чуть.

А отсюда поподробнее можно? Мы же не картину обсуждаем!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

33 (изменено: serzh82saratov, 2013-08-15 23:23:53)

Re: AHK: Замена стандартного элемента управления "Hotkey"

А отсюда поподробнее можно? Мы же не картину обсуждаем!

Если бы я мог заменять субъективное - объективным... Что то не совсем так, а может я и ошибаюсь. Тут практика нужна, а на неё не всегда есть время. Как бы того не хотелось

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

34

Re: AHK: Замена стандартного элемента управления "Hotkey"

А что конкретно побудило сказать тебя, что что-то не так?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

35

Re: AHK: Замена стандартного элемента управления "Hotkey"

После выхода из программы остаются залипшими ранее нажатые модификаторы.

Не наводит на мысли. Увы

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

36

Re: AHK: Замена стандартного элемента управления "Hotkey"

Ну, если какой-то модификатор остаётся в неотжатом состоянии, горячая клавиша, не рассчитанная на применение с этим модификатором, работать не будет.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

37

Re: AHK: Замена стандартного элемента управления "Hotkey"

Почему в моём коде, после клика, мимо окна (деактивация) снова происходит активация окна скрипта (кстати такого не было точно, на версиях до AutoHotkey v1.1.11.00). Я всю голову сломал. Пусть весь мой код случайный набор символов. Но почему??

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

38

Re: AHK: Замена стандартного элемента управления "Hotkey"

Может, сообщение SendMessage, 0xC активирует окно? Закомментируй его и проверь.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

39

Re: AHK: Замена стандартного элемента управления "Hotkey"

Вот ведь (какая-то согласная и...) ...
А ведь отказался при тестах кода от всех остальных вариантов GuiControl, ControlSetText и.т.п.
Спасибо!

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

40 (изменено: serzh82saratov, 2013-08-19 01:52:09)

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker пишет:

Со СТРАШНЫМИ глюками.

teadrinker пишет:

Может, сообщение SendMessage, 0xC активирует окно?

http://xbmc.ru/forum/images/smilies/facepalm.gif http://xbmc.ru/forum/images/smilies/facepalm.gif http://xbmc.ru/forum/images/smilies/facepalm.gif У меня в наглядном примере в метке поля ввода команда Gui Show меняла заголовок, когда SendMessage меняла поле ввода, запускалась метка поля ввода и Gui Show активировала окно. Пипец нубская ошибка. Пойду напьюсь
---------------
Проверь пожалуйста такой вариант:

+ открыть спойлер

#SingleInstance Force
Gui, +AlwaysOnTop +HWNDhGui
Gui, Add, Edit, Center ReadOnly w300 gShow vMyHotkey1 
Gui, Add, Edit, Center ReadOnly w300 gShow vMyHotkey2
HF_Hotkey( "MyHotkey1|MyHotkey2")
Gui, Show
return

Show:  
    Str := A_GuiControl " = " %A_GuiControl% 
    SendMessage, 0xC, 0, &Str, , ahk_id %hGui% 
    return
    
GuiClose:
    ExitApp
  

HF_Hotkey(HF_Control)  { ;***
    Global
    Loop, Parse, HF_Control, |
    {
        RegExMatch(A_LoopField, "S)(.*:)?\s*(.*)", HF_D)
        GuiControlGet, HF_D3, % HF_D1 "Hwnd", % HF_D2
        HF_D3 := Ceil(HF_D3), HF_Control_%HF_D3% := HF_D2
    }
    If !HF_IsStart 
    {
        SetBatchLines -1 
        #HotkeyInterval 200
        #MaxHotkeysPerInterval 200
        HF_MButtons := {"vkA4":"Alt","vkA5":"Alt","vkA2":"Ctrl","vkA3":"Ctrl","vkA0":"Shift","vkA1":"Shift","vk5B":"Win","vk5C":"Win"}
        HF_P := {"Alt":"!","Ctrl":"^","Shift":"+","Win":"#"}
        HF_Buttons := "|vkBA|vkBB|vkBC|vkBD|vkBE|vkBF|vkC0|vkDB|vkDC|vkDD|vkDE|vk41|vk42|vk43|vk44|vk45|vk46|vk47|vk48"
                    . "|vk49|vk4A|vk4B|vk4C|vk4D|vk4E|vk4F|vk50|vk51|vk52|vk53|vk54|vk55|vk56|vk57|vk58|vk59|vk5A|"     ; 37 Letter Buttons 
        HF_PressName := "WheelRight|WheelLeft|MButton|WheelDown|WheelUp|XButton1|XButton2" 
        #IF HF_State
        #IF
        Hotkey, IF, HF_State 
        Loop, Parse, HF_PressName, |
            Hotkey, %A_LoopField%, HF_PressName, P3 UseErrorLevel
        Loop, 128
            Hotkey % ((A_Index-1)//32)+1 "Joy" Mod(A_Index-1,32)+1, HF_PressName, P3 UseErrorLevel
        Hotkey, IF   
        OnMessage(0x111, "HF_WaitControl")
        HF_IsStart := 1
    }
    Return 
    
    HF_PressName: 
        HF_KeyName := HF_Hotkey := A_ThisHotkey , HF_DelStr := ""
        HF_Prefix := HF_PCtrl HF_PAlt HF_PShift HF_PWin
        %HF_ControlVarName% := HF_Prefix HF_Hotkey
        HF_WriteText := HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName = ""
        ? "Нет" : HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName
        SendMessage, 0xC, 0, &HF_WriteText, , ahk_id %HF_ControlHandle%
        Return  
} ;**

HF_WaitControl( HF_Param, HF_Handle) { ;***
    Global 
    If HF_Control_%HF_Handle% <>
    {
        If (HF_Param >> 16 = 0x100)    ;    EN_SETFOCUS
        {
            HF_ControlVarName := HF_Control_%HF_Handle%
            HF_ControlHandle := HF_Handle
            HF_State := DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
                                , Int, 13    ;    13 - WH_KEYBOARD_LL
                                , Ptr, RegisterCallback("HF_Write", "Fast")
                                , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
                                , UInt, 0, Ptr)
            HF_DelStr := ""
            PostMessage,0x00B1,,,, ahk_id %HF_ControlHandle%    ;    EM_SETSEL := 0x00B1
            Send, {LButton Up}
            Return
        }
        If (HF_Param >> 16 = 0x200)    ;    EN_KILLFOCUS
        {
            DllCall("UnhookWindowsHookEx" , Ptr, HF_State)
            HF_MCtrl := HF_MAlt := HF_MShift := HF_MWin := HF_Prefix := HF_State := ""
            HF_PCtrl := HF_PAlt := HF_PShift := HF_PWin := ""
            If (HF_DelStr = 1)
                SendMessage, 0xC, 0, "Нет", , ahk_id %HF_ControlHandle%
            Send {LShift Up}{RShift Up}
            Return
        }
    }
    If (HF_Param >> 16 = 0x200)    ;    EN_KILLFOCUS
    { 
        DllCall("UnhookWindowsHookEx", Ptr, HF_State)
        HF_MCtrl := HF_MAlt := HF_MShift := HF_MWin := HF_Prefix := HF_State := ""
        HF_PCtrl := HF_PAlt := HF_PShift := HF_PWin := ""
        Send {LShift Up}{RShift Up}
    }
    Return
} ;**

HF_Write(HF_nCode, HF_wParam, HF_lParam)  { ;***
    Global
    Critical
    SetFormat, IntegerFast, H
    HF_VkCode := "vk" SubStr( NumGet(HF_lParam+0, 0, "UInt"), 3)   
        HF_D := NumGet(HF_lParam+0, 8, "UInt") & 1
        HF_D := HF_D << 8 | NumGet(HF_lParam+0, 4, "UInt") 
    HF_SCCode := "sc" SubStr(HF_D, 3)  
    IF (HF_wParam = 0x100 || HF_wParam = 0x104)    ;    WM_KEYDOWN := 0x100, WM_SYSKEYDOWN := 0x104
    {
        IF HF_IsMod := HF_MButtons[HF_VkCode]
            GoTo, HF_PressMod
        GoTo, HF_Write
    }
    IF HF_IsMod := HF_MButtons[HF_VkCode]
        GoTo, HF_PressMod_Up
    Return 1

    HF_PressMod_Up:
        HF_M%HF_IsMod% := HF_P%HF_IsMod% := ""
        If ( HF_Hotkey != "" )
            Return 1
        GoTo, HF_Write

    HF_PressMod:
        If ( HF_M%HF_IsMod% != "" )
            Return 1
        HF_M%HF_IsMod% := HF_IsMod "+" , HF_P%HF_IsMod% := HF_P[HF_IsMod]

    HF_Write:
        ( HF_IsMod != "" ) ? ( HF_KeyName := HF_Hotkey := HF_Prefix := "" , HF_DelStr := 1 )
        : ( HF_KeyName := GetKeyName(HF_VkCode HF_SCCode) , HF_DelStr := ""
        , HF_Hotkey := InStr(HF_Buttons, "|" HF_VkCode "|") ? HF_VkCode : HF_KeyName
        , HF_Prefix := HF_PCtrl HF_PAlt HF_PShift HF_PWin )
        %HF_ControlVarName% := HF_Prefix HF_Hotkey
        HF_WriteText := HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName = "" ? "Нет" 
        : HF_MCtrl HF_MAlt HF_MShift HF_MWin HF_KeyName
        SendMessage, 0xC, 0, &HF_WriteText, , ahk_id %HF_ControlHandle%
        Return 1
} ;**

    ; -------------------------------------- Read --------------------------------------

HF_Read(Key, Section, Path) { ;***
    Global HF_DelStr := ""
    IniRead, Key, % Path, % Section, % Key, % A_Space
    If Key =
        Return "Нет" 
    Return    HF_ReadVar(Key)
} ;**

HF_ReadVar(Key) { ;***
    RegExMatch(Key, "S)^([\^\+!#]*)\{?(.*?)}?$", K)
    Return    (InStr(K1,"^")?"Ctrl+":"")(InStr(K1,"!")?"Alt+":"")
            . (InStr(K1,"+")?"Shift+":"")(InStr(K1,"#")?"Win+":"")
            . (InStr(K2,"vk") ? GetKeyName(K2) : K2)
} ;**

HF_ReadToSend(Key, Section = "", Path = "") { ;***
    If (Section <> "")
        IniRead, Key, % Path, % Section, % Key, % A_Space
    Return RegExReplace( Key, "S)[^\^!\+#].*", "{$0}")
} ;** 

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

41

Re: AHK: Замена стандартного элемента управления "Hotkey"

Ладно, уже завтра, сегодня отдыхаю

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

42

Re: AHK: Замена стандартного элемента управления "Hotkey"

Сейчас работает вроде нормально. Один небольшой недостаток — активируем окно, нажимаем несколько модификаторов, удерживая деактивируем — появляется "нет" — активируем снова — в окне остаётся лишь последний из нажатых модификаторов. Тут должно быть либо чтобы оставалось " нет", либо чтобы присутствовали все ранее нажатые.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

43

Re: AHK: Замена стандартного элемента управления "Hotkey"

появляется "нет" — активируем снова

остаётся лишь последний из нажатых модификаторов

Не видел такого. Имеется ввиду что например если последний из нажатых модификаторов альт, то после активации нажимаем кнопку, и пишется альт+кнопка?

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

44

Re: AHK: Замена стандартного элемента управления "Hotkey"

Нет, именно то, что я написал. Нажимаем только модификаторы, например Ctrl + Alt, удерживаем, деактивируем, продолжая удерживать, снова активируем — в окне остаётся только Alt.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

45

Re: AHK: Замена стандартного элемента управления "Hotkey"

Понял.

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

46

Re: AHK: Замена стандартного элемента управления "Hotkey"

В твоём варианте, если удерживать только модификаторы и активировать другой зарегистрированный Edit, то модификаторы останутся прописанными вместо слова "нет".

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.26.01 (Unicode 32-bit).

47

Re: AHK: Замена стандартного элемента управления "Hotkey"

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

Удалось подправить свой вариант так, что он лишён вышеуказанных недостатков, а также не имеет ни одной глобальной переменной.

Gui, Add, Edit, hwndhEdit1 gHotkey w150 h20 Center
fn := HotkeyInit(hEdit1)   ; fn — ссылка на функцию, которая будет получать строку с горячей клавишей

Gui, Add, Edit, vShowHotkey w150 h20 Center
Gui, Show
return

Hotkey:
   GuiControl, %A_Gui%:, ShowHotkey, % HotkeyString := fn.()
;  Hotkey, % HotkeyString, HKLabel, On UseErrorLevel ; раскомментировать для установки хоткея
   return

HKLabel:
   MsgBox, Вы нажали горячую клавишу %A_ThisHotkey%
   return

GuiClose:
   ExitApp

HotkeyInit(handle)
{
   if !IsObject(Create.array.handles)
      SetWinEventHook(0x8005, 0x8005, 0, RegisterCallback("HookProc", "F"),0,0,0)   ; EVENT_OBJECT_FOCUS := 0x8005
         , Create.array.handles := []
   
   Create.array.handles.Insert(handle)
   ControlSetText,, Нет, % "ahk_id" handle
   
   return Func("GetHkString")
}

Class Create
{
   static array := {}
}

GetHkString()
{
   HotkeyString := Create.array.HK
   Create.array.HK := ""
   return HotkeyString
}

SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
   return DllCall("SetWinEventHook" , UInt, eventMin
                                    , UInt, eventMax
                                    , Ptr, hmodWinEventProc
                                    , Ptr, lpfnWinEventProc
                                    , UInt, idProcess
                                    , UInt, idThread
                                    , UInt, dwFlags, Ptr)
}

HookProc(hWinEventHook, event, hwnd)
{
   for k,v in Create.array.handles
      if (hwnd = v)
         IsValue := 1, Create.array.hControl := v
   
   if (IsValue && !Create.array.hHook)
      Create.array.hHook := SetWindowsHookEx()
   else if (!IsValue && Create.array.hHook)
   {
      DllCall("UnhookWindowsHookEx", Ptr, Create.array.hHook)
      Create.array.keys := Create.array.hHook := ""
   }
   
   for k,v in Create.array.handles
   {
      ControlGetText, Text,, ahk_id %v%
      if SubStr(Text, -1) = "+ "
         ControlSetText,, Нет, ahk_id %v%
   }
}

SetWindowsHookEx()
{
   Return DllCall("SetWindowsHookEx" . (A_IsUnicode ? "W" : "A")
      , Int, WH_KEYBOARD_LL := 13
      , Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
      , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
      , UInt, 0, Ptr)
}

LowLevelKeyboardProc(nCode, wParam, lParam)
{
   static WM_KEYDOWN := 0x100, WM_KEYUP := 0x101, WM_SYSKEYDOWN := 0x104, WM_SYSKEYUP := 0x105
      , EndKey, prevMessage, prevKey
   
   SetBatchLines, -1
   SetFormat, IntegerFast, H
   Message := wParam, Extended := NumGet(lParam+0, 8, "UInt") & 1
   sc := Extended << 8 | NumGet(lParam+0, 4, "UInt")
   vk := NumGet(lParam+0, 0, "UInt")
   key := GetKeyName("vk" SubStr(vk, 3) "sc" SubStr(sc, 3))
   
   if (Message = prevMessage && key = prevKey)
      Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   prevMessage := Message, prevKey := key
   
   if key in LControl,RControl
      key := SubStr(key, 1, 1) . "Ctrl"
   if (sc = 0x145)
      key := "NumLock"
   
   if (Message = WM_KEYDOWN || Message = WM_SYSKEYDOWN)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
      {
         EndKey ? Create.array.keys := EndKey := ""
         
         if !InStr(Create.array.keys, key)
            Create.array.keys .= key . " + "
      }
      else
      {
         if (SubStr(Create.array.keys, -1) = "+ " || Create.array.keys = "")
            Create.array.keys .= key
         else
            Create.array.keys := RegExReplace(Create.array.keys, "(.*?)\S+$", "$1" key)
         
         Create.array.LastKey := "vk" . SubStr(vk, 3)  . "sc" . SubStr(sc, 3)
      }
   }
   
   if (Message = WM_KEYUP || Message = WM_SYSKEYUP)
   {
      if key in LCtrl,RCtrl,LAlt,RAlt,LShift,RShift,LWin,RWin
         Create.array.keys := RegExReplace(Create.array.keys, key . " \+ ")
      else if (Create.array.keys != "")
         EndKey := 1
         
      if !EndKey
         SetTimer, SetText, -10
      
      Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
   }

   SetTimer, SetText, -10
   Return nCode < 0 ? DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam) : 1
   
SetText:
   keys := Create.array.keys, LastKey := Create.array.LastKey
   if (keys != "" && keys != "Нет" && Substr(keys, -1) != "+ ")
   {
      Loop, parse, keys, +, % " "
      {
         IsSym := ""
         for k,v in {Ctrl: "^", Alt: "!", Shift: "+", Win: "#"}
            if InStr(A_LoopField, k) && A_LoopField != "CtrlBreak"
               HKString .= (SubStr(A_LoopField, 1, 1) = "L" ? "<" : ">") . v, IsSym := 1
         
         if !IsSym
         {
            if StrLen(A_LoopField) > 1
               HKString .= InStr(A_LoopField, "Num") ? RegExReplace(LastKey, ".*(s.*)", "$1") : A_LoopField
            else
               HKString .= RegExReplace(LastKey, "(.*)s.*", "$1")
         }
      }
      Create.array.HK := HKString
   }
   ControlSetText,, % keys = "" ? "Нет" : keys, % "ahk_id" Create.array.hControl
   return
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

48

Re: AHK: Замена стандартного элемента управления "Hotkey"

teadrinker, все определяет, только с мультимедиа-клавишами странно себя ведет:
Например, связка модификатор+Volume_Mute остается, только если бысто отпустить клавиши, иначе сбрасывается.
С остальными клавишами порядок.

49

Re: AHK: Замена стандартного элемента управления "Hotkey"

К сожалению, не могу это проверить, у меня клавиатура ещё старая, без медийных клавиш. По идее нужно посмотреть, какие значения vk, sc, key они выдают в функции LowLevelKeyboardProc().

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

50 (изменено: Irbis, 2013-08-20 22:56:44)

Re: AHK: Замена стандартного элемента управления "Hotkey"

sc = 0x100
vk = 0xAD
key = Volume_Mute

sc для всех MM-клавиш одинаковое, vk с 0xA6 (Browser_Back)