1

Тема: AHK: неправильная обработка жестов

Здравствуйте. Есть проблема.
Что нужно:
Реализация управления жестами в разных браузерах (хром, фф, опера, ie).
Для начала, необходимы следующие жесты:
ПКМ+жест вверх = новая вкладка (ctrl+t)
ПКМ+жест вниз = закрыть вкладку (ctrl+w)
ПКМ+жест вправо = переключиться на вкладку справа (ctrl+tab)
ПКМ+жест влево =  переключиться на вкладку слева (ctrl+shift+tab)
ПКМ+жест (вниз+вверх) = свернуть окно (WinMinimize, A)

Моя реализация

#SingleInstance force
CoordMode, Mouse

#if MouseIsOverBrowser()
  ~RButton::
    global trace := ""  ; trace of the mouse in each CLOCK
    global completeTrace := ""  ; ful-length trace of the mouse
    
    preX := XPos
    preY := YPos

    while GetKeyState("RButton") {
      sleep, 50
      MouseGetPos, XPos, YPos
      ;ToolTip, % XPos " - " YPos

      dx := XPos - preX
      dy := YPos - preY
      ;ToolTip, % dx " - " dy
      
      ; UP = U, DOWN = D, LEFT = L, RIGHT = R
      ignoreZone := 5

      if ((abs(dx) > abs(dy)) and (abs(dx) > ignoreZone)) {
        if (dx < 0) {
          trace := "L"
        } else if (dx > 0) {
          trace := "R"
        }
      } else if ((abs(dy) > abs(dx)) and (abs(dy) > ignoreZone)) {
        if (dy < 0) {
          trace := "U" 
        } else if (dy > 0) {
          trace := "D" 
        }
      } else {
        trace := ""
      }

      StringRight, lastChar, completeTrace, 1
      if (lastChar != trace) {
        completeTrace .= trace 
      }
      ;ToolTip, % completeTrace
      
      preX := XPos
      preY := YPos
    }
    ;ToolTip, % completeTrace

    ; write here nessesary action
    if (completeTrace == "L") {
      Send {Ctrl Down}{Shift Down}{Tab}{Shift Up}{Ctrl Up}
      tooltip, left
    }
    if (completeTrace == "R") {
      Send {Ctrl Down}{Tab}{Ctrl Up}
      tooltip, right
    }
    if (completeTrace == "U") {
      Send {Ctrl Down}{SC014}{Ctrl Up}
      tooltip, up
    }
    if (completeTrace == "D") {
      Send {Ctrl Down}{w}{Ctrl Up}
      tooltip, down
    }
    if (completeTrace == "DU") {
      WinMinimize, A
      tooltip, minimize
    }

    completeTrace := ""
    trace := ""
  return
#if

MouseIsOverBrowser()
{
  global
  MouseGetPos, XPos, YPos, WinID, WinControl
  if  (WinActive("ahk_class Chrome_WidgetWin_1")
      or WinActive("ahk_class MozillaWindowClass")
      or WinActive("ahk_class OperaWindowClas") ; опера идет нахер большими шагами со своим встроенным обработчиком мыши...
      or WinActive("ahk_class IEFrame")) {
    return 1
  } else {
    return 0
  }
}

;Esc::ExitApp

Проблемы:
Идеально работает только в Internet Explorer.
В других браузерах проблемы - tooltip всплывает всегда, значит жест отрабатывается как надо.
Но вот действие (сочетание кнопок) может выполниться, а может и нет, при этом WinMinimize, A выполняется всегда.

В чем может быть проблема?

2 (изменено: gleam, 2012-08-20 22:40:12)

Re: AHK: неправильная обработка жестов

Ответ найден - фокус забирало контекстное меню.

Финальная версия (вдруг кому-то понадобится ) ниже:

#SingleInstance force
CoordMode, Mouse

#if MouseIsOverBrowser()
  ~RButton::
    global moved := 0
    global trace := ""  ; trace of the mouse in each CLOCK
    global completeTrace := ""  ; ful-length trace of the mouse
    
    preX := XPos
    preY := YPos

    while GetKeyState("RButton") {
      sleep, 100
      MouseGetPos, XPos, YPos
      ;ToolTip, % XPos " - " YPos

      dx := XPos - preX
      dy := YPos - preY
      ;ToolTip, % dx " - " dy
      
      ; UP = U, DOWN = D, LEFT = L, RIGHT = R
      ignoreZone := 2 ;anti cursor-shaking

      if ((abs(dx) >= abs(dy)) and (abs(dx) >= ignoreZone)) {
        if (dx < 0) {
          trace := "L"
        } else if (dx > 0) {
          trace := "R"
        }
      } else if (abs(dy) >= ignoreZone) {
        if (dy < 0) {
          trace := "U" 
        } else if (dy > 0) {
          trace := "D" 
        }
      } else {
        trace := ""
      }

      StringRight, lastChar, completeTrace, 1
      if (lastChar != trace) {
        completeTrace .= trace 
        moved := 1
      }
      ;ToolTip, % completeTrace
      
      preX := XPos
      preY := YPos
    }
    ;ToolTip, % completeTrace
    if (completeTrace) {
      Send {Esc} ; close context menu
    }
    
    ; write here nessesary action
    if (completeTrace == "L") {
      Send {Ctrl Down}{Shift Down}{Tab}{Shift Up}{Ctrl Up}
      ;tooltip, left tab
    }
    else if (completeTrace == "R") {
      Send {Ctrl Down}{Tab}{Ctrl Up}
      ;tooltip, right tab
    }
    else if (completeTrace == "U") {
      Send {Ctrl Down}{SC014}{Ctrl Up}
      ;tooltip, new tab
    }
    else if (completeTrace == "D") {
      Send {Ctrl Down}{SC011}{Ctrl Up}
      ;tooltip, close tab
    }
    else if (completeTrace == "DU") {
      WinMinimize, A
      ;tooltip, minimize
    }
  return
  
  RButton UP::
    if (moved) {
      sleep, 10
      Send, {Esc}
    } 
  return
#if

MouseIsOverBrowser()
{
  global
  MouseGetPos, XPos, YPos, WinID, WinControl
  if  (WinActive("ahk_class Chrome_WidgetWin_1")
      or WinActive("ahk_class MozillaWindowClass")
      or WinActive("ahk_class OperaWindowClass") ; беда со вкладками
      or WinActive("ahk_class IEFrame")) {
    return 1
  } else {
    return 0
  }
}

3

Re: AHK: неправильная обработка жестов

Комментарии:

WinActive("ahk_class НекийКласс") каждый вызов подразумевает поиск активного окна и определение его класса, если использовать эту функцию в условии с множеством OR — скорость выполнения этого участка кода будет зависеть от позиции в строке вызова функции с подходящим параметром. Способ избежать этого: либо определение класса активного окна и однократного сравнения его со строкой содержащей список всех подходящих под условие окон, либо использование предварительного GroupAdd и однократного WinActive("ahk_group GroupName") в условии.

#if MouseIsOverBrowser() — директива воздействующая на нижележащие метки горячих клавиш, но не более, ~RButton:: и нижележащий код оперируют глобальными переменными, поэтому global в данном фрагменте кода делает переменные «супер-глобальными», а это не востребовано.

4

Re: AHK: неправильная обработка жестов

Ух, спасибо большое

Я правильно вас понял?

GroupAdd, Browsers, ahk_class Chrome_WidgetWin_1
GroupAdd, Browsers, ahk_class OperaWindowClass ; беда со вкладками
GroupAdd, Browsers, ahk_class MozillaWindowClass
GroupAdd, Browsers, ahk_class IEFrame

MouseIsOverBrowser()
{
  global
  MouseGetPos, XPos, YPos, WinID, WinControl
  if (WinActive("ahk_group Browsers")) {
    return 1
  } else {
    return 0
  }
}

Век живи - век учись!
А еще замечания по коду будут?

5

Re: AHK: неправильная обработка жестов

MouseIsOverBrowser возвращает 1 или 0, подразумевается true и false, число не равное нулю интерпретируется как «не false т.е. true».
Поэтому можно использовать return WinActive("ahk_group Browsers") если же возвращать нужно именно булево значение то return !!WinActive("ahk_group Browsers")