1

Тема: AHK: Реакция на сканер штрих-кода

Здравствуйте.
Преамбула - есть программа, принимающая данные со считывателя штрих-кода и обрабатывающая эти данные.
Считыватель подключен по УСБ. Программа видит его через виртуальный COM-порт. После считывания данных в таблице выбирается определенная строка. Дальше необходимо выполнить несколько кликов мышкой и так по кругу. Т.е. положить штрих-сканер, взять мышку, понажимать по кнопкам в программе, положить мышку, взять штрихсканер. ( Приход товара на складе)
Амбула - как отловить факт считывания ? Направьте, пожалуйста, в верном направлении. Пытался отслеживать в таблице изменение ячеек и по факту программировать действия, но что то как то получается не очень.
В скриптах новичек, делаю первые шаги.

2

Re: AHK: Реакция на сканер штрих-кода

andy319 пишет:

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

Это верное направление. Существует событие изменения ячейки. Для новичка будет сложновато разобраться.

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

3 (изменено: andy319, 2024-01-12 19:21:52)

Re: AHK: Реакция на сканер штрих-кода

teadrinker пишет:

Для новичка будет сложновато разобраться.

Глянул. Да, пока мимо кассы.
Тогда в продолжении темы еще спрошу. В программе, с которой я работаю, есть несколько контролов. В каждом из них по нескольку либо кнопок, либо полей ввода. Какие то элементы в контроле активны, какие то нет (можно нажать или нет, серые). Можно ли управлять (обращаться к) конкретно одним из внутренних элементов контрола без использования конструкций - переместить мышку на координату, кликнуть два раза, переместить дальше, ввести текст, вернутся на отслеживание поля на предмет изменения? У меня нет уверенности в таком способе, почему то где то что то и указатель начинает скакать по совсем другим координатам с непредсказуемыми результатами.
Перефразирую - как сделать так что бы нажатия происходили только там где нужно? Делать поиск по картинке?

4

Re: AHK: Реакция на сканер штрих-кода

andy319
АХК вполне способен отслеживать события изменения в контролах, главное знать что проверять. Советую посмотреть инфу о нужных контролах через AhkSpy.ahk. Если контролы имеют постоянные идентификаторы и программа видит в них изменения - всё решаемо.

Win10x64, AHK v1.1.37.01 (Unicode 64-bit), AHK v2.0.17| AHK-Wiki | Переменные и выражения | RegEx101

5 (изменено: Alectric, 2024-01-13 07:25:36)

Re: AHK: Реакция на сканер штрих-кода

andy319 пишет:

Можно ли управлять (обращаться к) конкретно одним из внутренних элементов контрола без использования конструкций

ControlClick

andy319 пишет:

переместить дальше, ввести текст

ControlSetText

andy319 пишет:

вернутся на отслеживание поля на предмет изменения

ControlGetText

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

6 (изменено: andy319, 2024-01-13 17:04:24)

Re: AHK: Реакция на сканер штрих-кода

Как то с контролами я встрял. Не могу въехать никак. Нахожу координаты левого верхнего угла контрола. А как нажать на внутренний элемент контрола? Для примера на картинке кнопка Формулы. Как на ее кликнуть? Или только через нахождение координат по имени контрола и клик координаты плюс смещение по кнопке Формулы?  Напишите пример, пожалуйста.

Post's attachments

Безымянный.png 144.43 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

7

Re: AHK: Реакция на сканер штрих-кода

x:=373
y:=54 ; Найденные координаты из pixelsearch?

x++
y++
Click,%x%,%y%
Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

8

Re: AHK: Реакция на сканер штрих-кода

andy319

а "программа, принимающая данные со считывателя штрих-кода и обрабатывающая эти данные" - это Excel чтоли?))

9 (изменено: andy319, 2024-01-13 19:29:10)

Re: AHK: Реакция на сканер штрих-кода

Alectric , это да, освоено. Но хотелось бы без клика по координатам.
inseption86 - не чисто таблица Ексель, а на базе Ексель сделана программа еще в лохматый конец 90х.  И приходится маяться с вводом кучи нажатий по всему экрану. Хоть сканер штрихкода прикрутили, а то раньше в строке поиска вручную набирали артикл, находили нужную деталь, приходовали ее... Еще смешнее и дольше и больше нажатий с выдачей клиенту. Какие то действия можно сделать по клавишам типа Альт-В и наподобие, какие то только мышкой.Но тут я победил. Ввожу ФИО, дальше все мышка автоматом. Выделяется клиент, выводится все по нему, распечатывается накладная, ставится признак выдачи.
В догонку - столкнулся с нестабильностью работы макроса. Может 10 раз сработать, а на 11 тупануть. Например - посылаем задание на печать, ждем окно прорисовки документа, СTRL-P,
ждем окно диалога настройки принтера, Ентер. Esc. Так вот - окно прорисовалось, а СTRL-P туда не улетело. И картинка висит. Таких моментов довольно много. В разных местах. Не пойму с чем связано.  Возможно приоритет макроса нужно сделать выше? Пропускает. Или Send заменить на SendInput? На компе еще видео с камеры пишется, но проц загружен всего процентов на 25 максимум.

10

Re: AHK: Реакция на сканер штрих-кода

andy319 пишет:

окно прорисовалось, а СTRL-P туда не улетело.

Попробуй WinActivate перед СTRL-P. Настрой SetKeyDelay, SetWinDelay на оптимальные значения (начни с 70мс).

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

11 (изменено: __Михаил__, 2024-01-13 21:22:05)

Re: AHK: Реакция на сканер штрих-кода

andy319
'Формулы' не кнопка, а скорее вкладка и должна запускать с комбинацией 'Alt + Ф' (или другой вариант если 'Ф' занята).

Send !{vk41}  ;Alt + Ф
Win10x64, AHK v1.1.37.01 (Unicode 64-bit), AHK v2.0.17| AHK-Wiki | Переменные и выражения | RegEx101

12 (изменено: Alectric, 2024-01-14 07:24:23)

Re: AHK: Реакция на сканер штрих-кода

Такую кнопку можно нажать через "iAccesibble".
Сейчас поэкспериментировал с Excel, пришлось модифицировать код InfoViewer'а чтобы найти полный путь до кнопки.
Вот результат:

#include,Acc.ahk
; нажатие на кнопку "Формулы" офис 2007
f1::
Acc_Get("DoDefaultAction","4.2.4.1.4.1.4.1.4.1.4.8.1.5",0, "ahk_exe EXCEL.EXE")
exitapp
+ Измененный Accessible Info Viewer
{
  WM_ACTIVATE := 0x06
  WM_KILLFOCUS := 0x08
  WM_LBUTTONDOWN := 0x201
  WM_LBUTTONUP := 0x202
  global	Border := new Outline, Stored:={}, Acc, ChildId, TVobj, Win:={}
}
{
  DetectHiddenWindows, On
  OnExit, OnExitCleanup
  OnMessage(0x200,"WM_MOUSEMOVE")
  ComObjError(false)
  Hotkey, ~LButton Up, Off
}
{
  Gui Main: New, HWNDhwnd LabelGui AlwaysOnTop, Accessible Info Viewer
  Gui Main: Default
  Win.Main := hwnd
  Gui, Add, Button, x160 y8 w105 h20 vShowStructure gShowStructure, Show Acc Structure
  Gui, Add, Button, x95 yp w60 h20 gShowParentStructure,Get Parent

  {
    Gui, Add, Text, x10 y3 w25 h26 Border gCrossHair ReadOnly HWNDh8 Border
    CColor(h8, "White")
    Gui, Add, Text, x10 y3 w25 h4 HWNDh9 Border
    CColor(h9, "0046D5")
    Gui, Add, Text, x13 y17 w19 h1 Border vHBar
    Gui, Add, Text, x22 y8 w1 h19 Border vVBar
  }
  {
    Gui, Font, bold
    Gui, Add, GroupBox, x2 y32 w275 h130 vWinCtrl, Window/Control Info
    Gui, Font
    Gui, Add, Text, x7 y49 w42 h20 Right, WinTitle:
    Gui, Add, Edit, x51 y47 w221 h20 vWinTitle ,
    Gui, Add, Text, x7 y71 w42 h20 Right, Text:
    Gui, Add, Edit, x51 y69 w221 h20 vText ,
    Gui, Add, Text, x7 y93 w42 h20 Right, Hwnd:
    Gui, Add, Edit, x51 y91 w72 h20 vHwnd,
    Gui, Add, Text, x126 y93 w51 h20 vClassText Right, Class(NN):
    Gui, Add, Edit, x178 y91 w94 h20 vClass,
    Gui, Add, Text, x7 y115 w42 h20 Right, Position:
    Gui, Add, Edit, x51 y113 w72 h20 vPosition,
    Gui, Add, Text, x126 y115 w51 h20 Right, Process:
    Gui, Add, Edit, x178 y113 w94 h20 vProcess,
    Gui, Add, Text, x7 y137 w42 h20 Right, Size:
    Gui, Add, Edit, x51 y135 w72 h20 vSize,
    Gui, Add, Text, x126 y137 w51 h20 Right, Proc ID:
    Gui, Add, Edit, x178 y135 w94 h20 vProcID,
  }
  {
    Gui, Font, bold
    Gui, Add, GroupBox, x2 y165 w275 h240 vAcc, Accessible Info
    Gui, Font
    Gui, Add, Text, x7 y182 w42 h20 Right, Name:
    Gui, Add, Edit, x51 y180 w221 h20 vAccName ,
    Gui, Add, Text, x7 y204 w42 h20 Right, Value:
    Gui, Add, Edit, x51 y202 w221 h20 vAccValue ,
    Gui, Add, Text, x7 y226 w42 h20 Right, Role:
    Gui, Add, Edit, x51 y224 w72 h20 vAccRole,
    Gui, Add, Text, x126 y226 w55 h20 Right, ChildCount:
    Gui, Add, Edit, x182 y224 w90 h20 vAccChildCount,
    Gui, Add, Text, x7 y248 w42 h20 Right, State:
    Gui, Add, Edit, x51 y246 w72 h20 vAccState,
    Gui, Add, Text, x126 y248 w55 h20 Right, Selection:
    Gui, Add, Edit, x182 y246 w90 h20 vAccSelection,
    Gui, Add, Text, x7 y270 w42 h20 Right, Action:
    Gui, Add, Edit, x51 y268 w72 h20 vAccAction,
    Gui, Add, Text, x126 y270 w55 h20 Right, Focus:
    Gui, Add, Edit, x182 y268 w90 h20 vAccFocus,
    {
      Gui, Add, Text, x7 y292 w55 h20 Right vAccLocationText, Location:
      Gui, Add, Edit, x65 y290 w207 h20 vAccLocation ,
      Gui, Add, Text, x7 y314 w55 h20 Right, Description:
      Gui, Add, Edit, x65 y312 w207 h20 vAccDescription ,
      Gui, Add, Text, x7 y336 w55 h20 Right, Keyboard:
      Gui, Add, Edit, x65 y334 w207 h20 vAccKeyboard ,
      Gui, Add, Text, x7 y358 w55 h20 Right, Help:
      Gui, Add, Edit, x65 y356 w207 h20 vAccHelp ,
      Gui, Add, Text, x7 y380 w55 h20 Right, HelpTopic:
      Gui, Add, Edit, x65 y378 w207 h20 vAccHelpTopic ,
    }
  }
  {
    Gui, Add, StatusBar, gShowMainGui
    SB_SetParts(70,150)
    SB_SetText("`tshow more", 3)
  }
  {
    Gui Acc: New, ToolWindow AlwaysOnTop Resize LabelAcc HWNDhwnd, Acc Structure
    Win.Acc := hwnd
    Gui Acc: Add, TreeView, w200 h300 vTView gTreeView R17 AltSubmit
    Gui Acc: Show, Hide
  }
  GoSub, ShowMainGui
  WinSet, Redraw, , % "ahk_id" Win.Main
  return
}
ShowMainGui:
{
  if A_EventInfo in 1,2
  {
    WM_MOUSEMOVE()
    StatusBarGetText, SB_Text, %A_EventInfo%, % "ahk_id" Win.Main
    if SB_Text
      if (A_EventInfo=2 and SB_Text:=SubStr(SB_Text,7))
      or if RegExMatch(SB_Text, "Id: \K\d+", SB_Text) {
        ToolTip % "clipboard = " clipboard:=SB_Text
        SetTimer, RemoveToolTip, -2000
    }
  }
  else {
    Gui Main: Default
    if ShowingLess {
      SB_SetText("`tshow less", 3)
      GuiControl, Move, Acc, x2 y165 w275 h240
      GuiControl, Show, AccDescription
      GuiControl, Show, AccLocation
      GuiControl, Show, AccLocationText
      {
        height := 319
        while height<428 {
          height += 10
          Gui, Show, w280 h%height%
          Sleep, 20
        }
      }
      Gui, Show, w280 h428
      ShowingLess := false
    }
    else {
      if (ShowingLess != "") {
        height := 428
        while height>319 {
          height -= 10
          Gui, Show, w280 h%height%
          Sleep, 20
        }
      }
      Gui, Show, w280 h319
      GuiControl, Hide, AccDescription
      GuiControl, Hide, AccLocation
      GuiControl, Hide, AccLocationText
      GuiControl, Move, Acc, x2 y165 w275 h130
      SB_SetText("`tshow more", 3)
      ShowingLess := true
    }
    WinSet, Redraw, , % "ahk_id" Win.Main
  }
return
}

#if Not Lbutton_Pressed
^/::
{
  SetBatchLines, -1
  Lbutton_Pressed := true
  Stored.Chwnd := ""
  Gui Acc: Default
  GuiControl, Disable, TView
  while, Lbutton_Pressed
  GetAccInfo()
  SetBatchLines, 10ms
  return
}
#if Lbutton_Pressed
^/::
{
  Lbutton_Pressed := false
  Gui Main: Default
  Sleep, -1
  GuiControl, , WinCtrl, % (DllCall("GetParent", Uint,Acc_WindowFromObject(Acc))? "Control":"Window") " Info"
  if Not DllCall("IsWindowVisible", "Ptr",Win.Acc) {
    Border.Hide()
    SB_SetText("Path: " GetAccPath(Acc).path, 2)
  }
  else {
    Gui Acc: Default
    BuildTreeView()
    GuiControl, Enable, TView
    WinActivate, % "ahk_id" Win.Acc
    PostMessage, %WM_LBUTTONDOWN%, , , SysTreeView321, % "ahk_id" Win.Acc
  }
  return
}
#if
~Lbutton Up::
{
  Hotkey, ~LButton Up, Off
  Lbutton_Pressed := False
  Gui Main: Default
  if Not CH {
    GuiControl, Show, HBar
    GuiControl, Show, VBar
    CrossHair(CH:=true)
  }
  Sleep, -1
  GuiControl, , WinCtrl, % (DllCall("GetParent", Uint,Acc_WindowFromObject(Acc))? "Control":"Window") " Info"
  if Not DllCall("IsWindowVisible", "Ptr",Win.Acc) {
    Border.Hide()
    SB_SetText("Path: " GetAccPath(Acc).path, 2)
  }
  else {
    Gui Acc: Default
    BuildTreeView()
    GuiControl, Enable, TView
    WinActivate, % "ahk_id" Win.Acc
    PostMessage, %WM_LBUTTONDOWN%, , , SysTreeView321, % "ahk_id" Win.Acc
  }
  return
}
CrossHair:
{
  if (A_GuiEvent = "Normal") {
    SetBatchLines, -1
    Hotkey, ~LButton Up, On
    {
      GuiControl, Hide, HBar
      GuiControl, Hide, VBar
      CrossHair(CH:=false)
    }
    Lbutton_Pressed := True
    Stored.Chwnd := ""
    Gui Acc: Default
    GuiControl, Disable, TView
    while, Lbutton_Pressed
      GetAccInfo()
    SetBatchLines, 10ms
  }
  return
}
OnExitCleanup:
{
  CrossHair(true)
  GuiClose:
  ExitApp
}
ShowParentStructure:
  Par:=Acc_Parent(Acc)
  if !(Par.AccName(0)~="Рабочий стол" or Par.AccName(0)~="Desctop")
    Acc:=Par
  else
  {
    tooltip,Больше нет.
    settimer,RemoveToolTip,-1000
  }
  BuildTreeView()
  return

ShowStructure:
{
  ControlFocus, Static1, % "ahk_id" Win.Main
  if DllCall("IsWindowVisible", "Ptr",Win.Acc) {
    PostMessage, %WM_LBUTTONDOWN%, , , SysTreeView321, % "ahk_id" Win.Acc
    return
  }
  WinGetPos, x, y, w, , % "ahk_id" Win.Main
  WinGetPos, , , AccW, AccH, % "ahk_id" Win.Acc
  WinMove, % "ahk_id" Win.Acc,
    , (x+w+AccW > A_ScreenWidth? x-AccW-10:x+w+10)
    , % y+5, %AccW%, %AccH%
  WinShow, % "ahk_id" Win.Acc
  if ComObjType(Acc, "Name") = "IAccessible"
    BuildTreeView()
  if Lbutton_Pressed
    GuiControl, Disable, TView
  else
    GuiControl, Enable, TView
  PostMessage, %WM_LBUTTONDOWN%, , , SysTreeView321, % "ahk_id" Win.Acc
  return
}
BuildTreeView()
{
  r := GetAccPath(Acc)
  AccObj:=r.AccObj, Child_Path:=r.Path, r:=""
  Gui Acc: Default
  TV_Delete()
  GuiControl, -Redraw, TView
  parent := TV_Add(Acc_Role(AccObj), "", "Bold Expand")
  TVobj := {(parent): {is_obj:true, obj:AccObj, need_children:false, childid:0, Children:[]}}
  Loop Parse, Child_Path, .
  {
    if A_LoopField is not Digit
      TVobj[parent].Obj_Path := Trim(TVobj[parent].Obj_Path "," A_LoopField, ",")
    else {
      StoreParent := parent
      parent := TV_BuildAccChildren(AccObj, parent, "", A_LoopField)
      TVobj[parent].need_children := false
      TV_Expanded(StoreParent)
      TV_Modify(parent,"Expand")
      AccObj := TVobj[parent].obj
    }
  }
  if Not ChildId {
    TV_BuildAccChildren(AccObj, parent)
    TV_Modify(parent, "Select")
  }
  else
    TV_BuildAccChildren(AccObj, parent, ChildId)
  TV_Expanded(parent)
  GuiControl, +Redraw, TView
}
AccClose:
{
  Border.Hide()
  Gui Acc: Hide
  TV_Delete()
  Gui Main: Default
  GuiControl, Enable, ShowStructure
  return
}
AccSize:
{
  Anchor(TView, "wh")
  return
}
TreeView:
{
  Gui, Submit, NoHide
  if (A_GuiEvent = "S")
    UpdateAccInfo(TVobj[A_EventInfo].obj, TVobj[A_EventInfo].childid, TVobj[A_EventInfo].obj_path)
  if (A_GuiEvent = "+") {
    GuiControl, -Redraw, TView
    TV_Expanded(A_EventInfo)
    GuiControl, +Redraw, TView
  }
  return
}
RemoveToolTip:
{
  ToolTip
  return
}
GetAccInfo() {
  global Whwnd
  static ShowButtonEnabled
  MouseGetPos, , , Whwnd
  if (Whwnd!=Win.Main and Whwnd!=Win.Acc) {
    {
      GuiControlGet, SectionLabel, , WinCtrl
      if (SectionLabel != "Window/Control Info")
        GuiControl, , WinCtrl, Window/Control Info
    }
    Acc := Acc_ObjectFromPoint(ChildId)
tooltip % ChildId
    Location := GetAccLocation(Acc, ChildId)
    if Stored.Location != Location {
      Hwnd := Acc_WindowFromObject(Acc)
      if Stored.Hwnd != Hwnd {
        if DllCall("GetParent", Uint,hwnd) {
          WinGetTitle, title, ahk_id %parent%
          ControlGetText, text, , ahk_id %Hwnd%
          class := GetClassNN(Hwnd,Whwnd)
          ControlGetPos, posX, posY, posW, posH, , ahk_id %Hwnd%
          WinGet, proc, ProcessName, ahk_id %parent%
          WinGet, procid, PID, ahk_id %parent%
        }
        else {
          WinGetTitle, title, ahk_id %Hwnd%
          WinGetText, text, ahk_id %Hwnd%
          WinGetClass, class, ahk_id %Hwnd%
          WinGetPos, posX, posY, posW, posH, ahk_id %Hwnd%
          WinGet, proc, ProcessName, ahk_id %Hwnd%
          WinGet, procid, PID, ahk_id %Hwnd%
        }
        {
          GuiControl, , WinTitle, %title%
          GuiControl, , Text, %text%
          SetFormat, IntegerFast, H
          GuiControl, , Hwnd, % Hwnd+0
          SetFormat, IntegerFast, D
          GuiControl, , Class, %class%
          GuiControl, , Position, x%posX%  y%posY%
          GuiControl, , Size, w%posW%  h%posH%
          GuiControl, , Process, %proc%
          GuiControl, , ProcId, %procid%
        }
        Stored.Hwnd := Hwnd
      }
      UpdateAccInfo(Acc, ChildId)
    }
  }
}
UpdateAccInfo(Acc, ChildId, Obj_Path="") {
  global Whwnd
  Gui Main: Default
  Location := GetAccLocation(Acc, ChildId, x,y,w,h)
  {
    GuiControl, , AccName, % Acc.accName(ChildId)
    GuiControl, , AccValue, % Acc.accValue(ChildId)
    GuiControl, , AccRole, % Acc_GetRoleText(Acc.accRole(ChildId))
    GuiControl, , AccState, % Acc_GetStateText(Acc.accState(ChildId))
    GuiControl, , AccAction, % Acc.accDefaultAction(ChildId)
    GuiControl, , AccChildCount, % ChildId? "N/A":Acc.accChildCount
    GuiControl, , AccSelection, % ChildId? "N/A":Acc.accSelection
    GuiControl, , AccFocus, % ChildId? "N/A":Acc.accFocus
    GuiControl, , AccLocation, %Location%
    GuiControl, , AccDescription, % Acc.accDescription(ChildId)
    GuiControl, , AccKeyboard, % Acc.accKeyboardShortCut(ChildId)
    Guicontrol, , AccHelp, % Acc.accHelp(ChildId)
    GuiControl, , AccHelpTopic, % Acc.accHelpTopic(ChildId)
    SB_SetText(ChildId? "Child Id: " ChildId:"Object")
    SB_SetText(DllCall("IsWindowVisible", "Ptr",Win.Acc)? "Path: " Obj_Path:"", 2)
  }
  Border.Transparent(true)
  Border.show(x,y,x+w,y+h)
  Border.setabove(Whwnd)
  Border.Transparent(false)
  Stored.Location := Location
}
GetClassNN(Chwnd, Whwnd) {
  global _GetClassNN := {}
  _GetClassNN.Hwnd := Chwnd
  Detect := A_DetectHiddenWindows
  WinGetClass, Class, ahk_id %Chwnd%
  _GetClassNN.Class := Class
  DetectHiddenWindows, On
  EnumAddress := RegisterCallback("GetClassNN_EnumChildProc")
  DllCall("EnumChildWindows", "uint",Whwnd, "uint",EnumAddress)
  DetectHiddenWindows, %Detect%
  return, _GetClassNN.ClassNN, _GetClassNN:=""
}
GetClassNN_EnumChildProc(hwnd, lparam) {
  static Occurrence
  global _GetClassNN
  WinGetClass, Class, ahk_id %hwnd%
  if _GetClassNN.Class == Class
    Occurrence++
  if Not _GetClassNN.Hwnd == hwnd
    return true
  else {
    _GetClassNN.ClassNN := _GetClassNN.Class Occurrence
    Occurrence := 0
    return false
  }
}
TV_Expanded(TVid) {
  For Each, TV_Child_ID in TVobj[TVid].Children
    if TVobj[TV_Child_ID].need_children
      TV_BuildAccChildren(TVobj[TV_Child_ID].obj, TV_Child_ID)
}
TV_BuildAccChildren(AccObj, Parent, Selected_Child="", Flag="") {
  TVobj[Parent].need_children := false
  Parent_Obj_Path := Trim(TVobj[Parent].Obj_Path, ",")
  for wach, child in Acc_Children(AccObj) {
    if Not IsObject(child) {
      added := TV_Add("[" A_Index "] " Acc_GetRoleText(AccObj.accRole(child)), Parent)
      TVobj[added] := {is_obj:false, obj:Acc, childid:child, Obj_Path:Parent_Obj_Path}
      if (child = Selected_Child)
        TV_Modify(added, "Select")
    }
    else {
      added := TV_Add("[" A_Index "] " Acc_Role(child), Parent, "bold")
      TVobj[added] := {is_obj:true, need_children:true, obj:child, childid:0, Children:[], Obj_Path:Trim(Parent_Obj_Path "," A_Index, ",")}
    }
    TVobj[Parent].Children.Insert(added)
    if (A_Index = Flag)
      Flagged_Child := added
  }
  return Flagged_Child
}
GetAccPath(Acc, byref hwnd="") {
  hwnd := Acc_WindowFromObject(Acc)
  WinObj := Acc_ObjectFromWindow(hwnd)
  WinObjPos := Acc_Location(WinObj).pos
  while Acc_WindowFromObject(Parent:=Acc_Parent(Acc)) = hwnd {
    t2 := GetEnumIndex(Acc) "." t2
    if Acc_Location(Parent).pos = WinObjPos
      return {AccObj:Parent, Path:SubStr(t2,1,-1)}
    Acc := Parent
  }
  while Acc_WindowFromObject(Parent:=Acc_Parent(WinObj)) = hwnd
    t1.="P.", WinObj:=Parent
  return {AccObj:Acc, Path:t1 SubStr(t2,1,-1)}
}
GetEnumIndex(Acc, ChildId=0) {
  if Not ChildId {
    ChildPos := Acc_Location(Acc).pos
    For Each, child in Acc_Children(Acc_Parent(Acc))
      if IsObject(child) and Acc_Location(child).pos=ChildPos
        return A_Index
  }
  else {
    ChildPos := Acc_Location(Acc,ChildId).pos
    For Each, child in Acc_Children(Acc)
      if Not IsObject(child) and Acc_Location(Acc,child).pos=ChildPos
        return A_Index
  }
}
GetAccLocation(AccObj, Child=0, byref x="", byref y="", byref w="", byref h="") {
  AccObj.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), Child)
  return	"x" (x:=NumGet(x,0,"int")) "  "
  .	"y" (y:=NumGet(y,0,"int")) "  "
  .	"w" (w:=NumGet(w,0,"int")) "  "
  .	"h" (h:=NumGet(h,0,"int"))
}
WM_MOUSEMOVE() {
  static hCurs := new Cursor(32649)
  MouseGetPos,,,,ctrl
  if (ctrl = "msctls_statusbar321")
    DllCall("SetCursor","ptr",hCurs.ptr)
}
class Cursor {
  __New(id) {
  this.ptr := DllCall("LoadCursor","UInt",NULL,"Int",id,"UInt")
}
__delete() {
DllCall("DestroyCursor","Uint",this.ptr)
}
}
class Outline {
  __New(color="red") {
    Gui, +HWNDdefault
    Loop, 4 {
      Gui, New, -Caption +ToolWindow HWNDhwnd
      Gui, Color, %color%
      this[A_Index] := hwnd
    }
    this.visible := false
    this.color := color
    this.top := this[1]
    this.right := this[2]
    this.bottom := this[3]
    this.left := this[4]
    Gui, %default%: Default
  }
  Show(x1, y1, x2, y2, sides="TRBL") {
    Gui, +HWNDdefault
    if InStr( sides, "T" )
      Gui, % this[1] ":Show", % "NA X" x1-2 " Y" y1-2 " W" x2-x1+4 " H" 2
    Else, Gui, % this[1] ":Hide"
    if InStr( sides, "R" )
      Gui, % this[2] ":Show", % "NA X" x2 " Y" y1 " W" 2 " H" y2-y1
    Else, Gui, % this[2] ":Hide"
    if InStr( sides, "B" )
      Gui, % this[3] ":Show", % "NA X" x1-2 " Y" y2 " W" x2-x1+4 " H" 2
    Else, Gui, % this[3] ":Hide"
    if InStr( sides, "L" )
      Gui, % this[4] ":Show", % "NA X" x1-2 " Y" y1 " W" 2 " H" y2-y1
    Else, Gui, % this[3] ":Hide"
    self.visible := true
    Gui, %default%: Default
  }
  Hide() {
    Gui, +HWNDdefault
    Loop, 4
      Gui, % this[A_Index] ": Hide"
    self.visible := false
    Gui, %default%: Default
  }
  SetAbove(hwnd) {
    ABOVE := DllCall("GetWindow", "uint", hwnd, "uint", 3)
    Loop, 4
      DllCall(	"SetWindowPos", "uint", this[A_Index], "uint", ABOVE
          ,	"int", 0, "int", 0, "int", 0, "int", 0
          ,	"uint", 0x1|0x2|0x10	)
  }
  Transparent(param) {
    Loop, 4
      WinSet, Transparent, % param=1? 0:255, % "ahk_id" this[A_Index]
    self.visible := !param
  }
  Color(color) {
    Gui, +HWNDdefault
    Loop, 4
      Gui, % this[A_Index] ": Color" , %color%
    self.color := color
    Gui, %default%: Default
  }
  Destroy() {
    Loop, 4
      Gui, % this[A_Index] ": Destroy"
  }
}
CColor(Hwnd, Background="", Foreground="") {
  return CColor_(Background, Foreground, "", Hwnd+0)
}
CColor_(Wp, Lp, Msg, Hwnd) {
  static
  static WM_CTLCOLOREDIT=0x0133, WM_CTLCOLORLISTBOX=0x134, WM_CTLCOLORSTATIC=0x0138
  ,LVM_SETBKCOLOR=0x1001, LVM_SETTEXTCOLOR=0x1024, LVM_SETTEXTBKCOLOR=0x1026, TVM_SETTEXTCOLOR=0x111E, TVM_SETBKCOLOR=0x111D
  ,BS_CHECKBOX=2, BS_RADIOBUTTON=8, ES_READONLY=0x800
  ,CLR_NONE=-1, CSILVER=0xC0C0C0, CGRAY=0x808080, CWHITE=0xFFFFFF, CMAROON=0x80, CRED=0x0FF, CPURPLE=0x800080, CFUCHSIA=0xFF00FF,CGREEN=0x8000, CLIME=0xFF00, COLIVE=0x8080, CYELLOW=0xFFFF, CNAVY=0x800000, CBLUE=0xFF0000, CTEAL=0x808000, CAQUA=0xFFFF00
  ,CLASSES := "Button,ComboBox,Edit,ListBox,Static,RICHEDIT50W,SysListView32,SysTreeView32"
  If (Msg = "") {
    if !adrSetTextColor
    adrSetTextColor   := DllCall("GetProcAddress", "uint", DllCall("GetModuleHandle", "str", "Gdi32.dll"), "str", "SetTextColor")
    ,adrSetBkColor   := DllCall("GetProcAddress", "uint", DllCall("GetModuleHandle", "str", "Gdi32.dll"), "str", "SetBkColor")
    ,adrSetBkMode   := DllCall("GetProcAddress", "uint", DllCall("GetModuleHandle", "str", "Gdi32.dll"), "str", "SetBkMode")
    BG := !Wp ? "" : C%Wp% != "" ? C%Wp% : "0x" SubStr(WP,5,2) SubStr(WP,3,2) SubStr(WP,1,2)
    FG := !Lp ? "" : C%Lp% != "" ? C%Lp% : "0x" SubStr(LP,5,2) SubStr(LP,3,2) SubStr(LP,1,2)
    WinGetClass, class, ahk_id %Hwnd%
    If class not in %CLASSES%
      return A_ThisFunc "> Unsupported control class: " class
    ControlGet, style, Style, , , ahk_id %Hwnd%
    if (class = "Edit") && (Style & ES_READONLY)
      class := "Static"
    if (class = "Button")
      if (style & BS_RADIOBUTTON) || (style & BS_CHECKBOX)
        class := "Static"
      else
        return A_ThisFunc "> Unsupported control class: " class
    if (class = "ComboBox") {
      VarSetCapacity(CBBINFO, 52, 0), NumPut(52, CBBINFO), DllCall("GetComboBoxInfo", "UInt", Hwnd, "UInt", &CBBINFO)
      hwnd := NumGet(CBBINFO, 48)
      %hwnd%BG := BG, %hwnd%FG := FG, %hwnd% := BG ? DllCall("CreateSolidBrush", "UInt", BG) : -1
      IfEqual, CTLCOLORLISTBOX,,SetEnv, CTLCOLORLISTBOX, % OnMessage(WM_CTLCOLORLISTBOX, A_ThisFunc)
      If NumGet(CBBINFO,44)
        Hwnd :=  Numget(CBBINFO,44), class := "Edit"
    }
    if class in SysListView32,SysTreeView32
    {
      m := class="SysListView32" ? "LVM" : "TVM"
      SendMessage, %m%_SETBKCOLOR, ,BG, ,ahk_id %Hwnd%
      SendMessage, %m%_SETTEXTCOLOR, ,FG, ,ahk_id %Hwnd%
      SendMessage, %m%_SETTEXTBKCOLOR, ,CLR_NONE, ,ahk_id %Hwnd%
      return
    }
    if (class = "RICHEDIT50W")
      return f := "RichEdit_SetBgColor", %f%(Hwnd, -BG)
    if (!CTLCOLOR%Class%)
      CTLCOLOR%Class% := OnMessage(WM_CTLCOLOR%Class%, A_ThisFunc)
    return %Hwnd% := BG ? DllCall("CreateSolidBrush", "UInt", BG) : CLR_NONE,  %Hwnd%BG := BG,  %Hwnd%FG := FG
  }
  critical
  Hwnd := Lp + 0, hDC := Wp + 0
  If (%Hwnd%) {
    DllCall(adrSetBkMode, "uint", hDC, "int", 1)
    if (%Hwnd%FG)
      DllCall(adrSetTextColor, "UInt", hDC, "UInt", %Hwnd%FG)
    if (%Hwnd%BG)
      DllCall(adrSetBkColor, "UInt", hDC, "UInt", %Hwnd%BG)
    return (%Hwnd%)
  }
}
CrossHair(OnOff=1) {
  static AndMask, XorMask, $, h_cursor, IDC_CROSS := 32515
  ,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13
  , b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13
  , h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11,h12,h13
  if (OnOff = "Init" or OnOff = "I" or $ = "") {
    $ := "h"
    , VarSetCapacity( h_cursor,4444, 1 )
    , VarSetCapacity( AndMask, 32*4, 0xFF )
    , VarSetCapacity( XorMask, 32*4, 0 )
    , system_cursors := "32512,32513,32514,32515,32516,32642,32643,32644,32645,32646,32648,32649,32650"
    StringSplit c, system_cursors, `,
    Loop, %c0%
      h_cursor   := DllCall( "LoadCursor", "uint",0, "uint",c%A_Index% )
      , h%A_Index% := DllCall( "CopyImage",  "uint",h_cursor, "uint",2, "int",0, "int",0, "uint",0 )
      , b%A_Index% := DllCall("LoadCursor", "Uint", "", "Int", IDC_CROSS, "Uint")
  }
  $ := (OnOff = 0 || OnOff = "Off" || $ = "h" && (OnOff < 0 || OnOff = "Toggle" || OnOff = "T")) ? "b" : "h"
  Loop, %c0%
    h_cursor := DllCall( "CopyImage", "uint",%$%%A_Index%, "uint",2, "int",0, "int",0, "uint",0 )
    , DllCall( "SetSystemCursor", "uint",h_cursor, "uint",c%A_Index% )
}

{ ; Acc Library
  Acc_Init()
  {
  Static	h
  If Not	h
  h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
  }
  Acc_ObjectFromEvent(ByRef _idChild_, hWnd, idObject, idChild)
  {
  Acc_Init()
  If	DllCall("oleacc\AccessibleObjectFromEvent", "Ptr", hWnd, "UInt", idObject, "UInt", idChild, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
  Return	ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
  }
  Acc_ObjectFromPoint(ByRef _idChild_ = "", x = "", y = "")
  {
  Acc_Init()
  If	DllCall("oleacc\AccessibleObjectFromPoint", "Int64", x==""||y==""?0*DllCall("GetCursorPos","Int64*",pt)+pt:x&0xFFFFFFFF|y<<32, "Ptr*", pacc, "Ptr", VarSetCapacity(varChild,8+2*A_PtrSize,0)*0+&varChild)=0
  Return	ComObjEnwrap(9,pacc,1), _idChild_:=NumGet(varChild,8,"UInt")
  }
  Acc_ObjectFromWindow(hWnd, idObject = 0)
  {
  Acc_Init()
  If	DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
  Return	ComObjEnwrap(9,pacc,1)
  }
  Acc_WindowFromObject(pacc)
  {
  If	DllCall("oleacc\WindowFromAccessibleObject", "Ptr", IsObject(pacc)?ComObjValue(pacc):pacc, "Ptr*", hWnd)=0
  Return	hWnd
  }
  Acc_GetRoleText(nRole)
  {
  nSize := DllCall("oleacc\GetRoleText", "Uint", nRole, "Ptr", 0, "Uint", 0)
  VarSetCapacity(sRole, (A_IsUnicode?2:1)*nSize)
  DllCall("oleacc\GetRoleText", "Uint", nRole, "str", sRole, "Uint", nSize+1)
  Return	sRole
  }
  Acc_GetStateText(nState)
  {
  nSize := DllCall("oleacc\GetStateText", "Uint", nState, "Ptr", 0, "Uint", 0)
  VarSetCapacity(sState, (A_IsUnicode?2:1)*nSize)
  DllCall("oleacc\GetStateText", "Uint", nState, "str", sState, "Uint", nSize+1)
  Return	sState
  }
  Acc_Role(Acc, ChildId=0) {
  try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetRoleText(Acc.accRole(ChildId)):"invalid object"
  }
  Acc_State(Acc, ChildId=0) {
  try return ComObjType(Acc,"Name")="IAccessible"?Acc_GetStateText(Acc.accState(ChildId)):"invalid object"
  }
  Acc_Children(Acc) {
  if ComObjType(Acc,"Name")!="IAccessible"
  error_message := "Cause:`tInvalid IAccessible Object`n`n"
  else {
  Acc_Init()
  cChildren:=Acc.accChildCount, Children:=[]
  if DllCall("oleacc\AccessibleChildren", "Ptr", ComObjValue(Acc), "Int", 0, "Int", cChildren, "Ptr", VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*", cChildren)=0 {
  Loop %cChildren%
  i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=3?child:Acc_Query(child)), ObjRelease(child)
  return Children
  }
  }
  error:=Exception("",-1)
  MsgBox, 262148, Acc_Children Failed, % (error_message?error_message:"") "File:`t" (error.file==A_ScriptFullPath?A_ScriptName:error.file) "`nLine:`t" error.line "`n`nContinue Script?"
  IfMsgBox, No
  ExitApp
  }
  Acc_Location(Acc, ChildId=0) {
  try Acc.accLocation(ComObj(0x4003,&x:=0), ComObj(0x4003,&y:=0), ComObj(0x4003,&w:=0), ComObj(0x4003,&h:=0), ChildId)
  catch
  return
  return	{x:NumGet(x,0,"int"), y:NumGet(y,0,"int"), w:NumGet(w,0,"int"), h:NumGet(h,0,"int")
  ,	pos:"x" NumGet(x,0,"int")" y" NumGet(y,0,"int") " w" NumGet(w,0,"int") " h" NumGet(h,0,"int")}
  }
  Acc_Parent(Acc) {
  try parent:=Acc.accParent
  return parent?Acc_Query(parent):
  }
  Acc_Child(Acc, ChildId=0) {
  try child:=Acc.accChild(ChildId)
  return child?Acc_Query(child):
  }
  Acc_Query(Acc) {
  try return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
  }
}

Anchor(i, a = "", r = false) {
  static c, cs = 12, cx = 255, cl = 0, g, gs = 8, gl = 0, gpi, gw, gh, z = 0, k = 0xffff, ptr
  If z = 0
    VarSetCapacity(g, gs * 99, 0), VarSetCapacity(c, cs * cx, 0), ptr := A_PtrSize ? "Ptr" : "UInt", z := true
  If (!WinExist("ahk_id" . i)) {
    GuiControlGet, t, Hwnd, %i%
    If ErrorLevel = 0
    i := t
    Else ControlGet, i, Hwnd, , %i%
  }
  VarSetCapacity(gi, 68, 0), DllCall("GetWindowInfo", "UInt", gp := DllCall("GetParent", "UInt", i), ptr, &gi)
  , giw := NumGet(gi, 28, "Int") - NumGet(gi, 20, "Int"), gih := NumGet(gi, 32, "Int") - NumGet(gi, 24, "Int")
  If (gp != gpi) {
    gpi := gp
    Loop, %gl%
      If (NumGet(g, cb := gs * (A_Index - 1)) == gp, "UInt") {
        gw := NumGet(g, cb + 4, "Short"), gh := NumGet(g, cb + 6, "Short"), gf := 1
        Break
      }
    If (!gf)
      NumPut(gp, g, gl, "UInt"), NumPut(gw := giw, g, gl + 4, "Short"), NumPut(gh := gih, g, gl + 6, "Short"), gl += gs
  }
  ControlGetPos, dx, dy, dw, dh, , ahk_id %i%
  Loop, %cl%
  If (NumGet(c, cb := cs * (A_Index - 1), "UInt") == i) {
    If a =
    {
      cf = 1
      Break
    }
    giw -= gw, gih -= gh, as := 1, dx := NumGet(c, cb + 4, "Short"), dy := NumGet(c, cb + 6, "Short")
    , cw := dw, dw := NumGet(c, cb + 8, "Short"), ch := dh, dh := NumGet(c, cb + 10, "Short")
    Loop, Parse, a, xywh
      If A_Index > 1
        av := SubStr(a, as, 1), as += 1 + StrLen(A_LoopField)
        , d%av% += (InStr("yh", av) ? gih : giw) * (A_LoopField + 0 ? A_LoopField : 1)
    DllCall("SetWindowPos", "UInt", i, "UInt", 0, "Int", dx, "Int", dy
    , "Int", InStr(a, "w") ? dw : cw, "Int", InStr(a, "h") ? dh : ch, "Int", 4)
    If r != 0
      DllCall("RedrawWindow", "UInt", i, "UInt", 0, "UInt", 0, "UInt", 0x0101)
    Return
  }
  If cf != 1
    cb := cl, cl += cs
  bx := NumGet(gi, 48, "UInt"), by := NumGet(gi, 16, "Int") - NumGet(gi, 8, "Int") - gih - NumGet(gi, 52, "UInt")
  If cf = 1
    dw -= giw - gw, dh -= gih - gh
  NumPut(i, c, cb, "UInt"), NumPut(dx - bx, c, cb + 4, "Short"), NumPut(dy - by, c, cb + 6, "Short")
  , NumPut(dw, c, cb + 8, "Short"), NumPut(dh, c, cb + 10, "Short")
  Return, true
}

В Viewerе нужно перетащить крестик на окно экселя, нажать кнопку "Get Parent" несколько раз, пока не высветится "Больше нет.", затем нажать "Show Acc Structure" и вручную пролистать все что там есть до нужной кнопки, внизу программы высветится полный путь до кнопки.

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

13 (изменено: andy319, 2024-01-13 22:29:56)

Re: AHK: Реакция на сканер штрих-кода

__Михаил__ пишет:

с комбинацией 'Alt + Ф'

Да, Михаил, некоторые кнопки можно так нажать, некоторые только мышью...   Подозреваю что на Ексель там много чего накручено ...
Alectric, огого... Не ожидал... Это для меня сильно. Библиотеку скачал, загружаю и получаю ошибку -

Post's attachments

Безымянный1.png 53.29 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

14

Re: AHK: Реакция на сканер штрих-кода

Склоняюсь к мысли остановиться на Click со смещением по координатам контрола.   Казалось все проще...

15

Re: AHK: Реакция на сканер штрих-кода

andy319
Возможно библиотека старая попалась или не туда закинули её.

Win10x64, AHK v1.1.37.01 (Unicode 64-bit), AHK v2.0.17| AHK-Wiki | Переменные и выражения | RegEx101

16 (изменено: andy319, 2024-01-13 22:53:10)

Re: AHK: Реакция на сканер штрих-кода

__Михаил__, засунул в Гугл и что вышло... Я еще поищу...
Рядышком с прочими скриптами.
Но энтузиазм притих немного

17 (изменено: andy319, 2024-01-13 23:11:30)

Re: AHK: Реакция на сканер штрих-кода

Еще помучаю - вопрос - WinText , выделенный синим на картинке, это текст внутри контрола? Если да, то по логике должны искаться координаты этого текста.  Или пардон? Что такое тогда WinText?

Post's attachments

Безымянный2.png 23.25 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

18

Re: AHK: Реакция на сканер штрих-кода

ControlGetPos
Определяет расположение и размеры контрола (элемента управления в окне).

ControlGetPos [, X, Y, Width, Height, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]

+ Цитата из справки AutoHotkey (v1.0.48.05)

Параметры
X, Y Имена выходных переменных, куда будут помещены координаты (в пикселах) верхнего левого угла контрола. Координаты считаются относительно верхнего левого угла указанного окна.
Width, Height Имена выходных переменных, куда будут помещены ширина и высота контрола (в пикселах).
Control Может задаваться как ClassNN (имя класса и номер данного экземпляра) или как имя/текст контрола. Все эти значения можно определить, используя программу Window Spy. При использовании имени/текста параметры их поиска можно задавать командой SetTitleMatchMode. Если параметр пустой, используется верхний контрол окна.

Чтобы указать контрол через его HWND (window handle, идентификатор окна), оставьте параметр Control пустым и задайте ahk_id %ControlHwnd% как значение параметра WinTitle - это работает также и для скрытых контролов, даже если обнаружение скрытых окон (команда DetectHiddenWindows) не включено. HWND, как правило, узнаётся через команды ControlGet Hwnd, MouseGetPos или DllCall.
WinTitle Заголовок или часть заголовка окна (параметры поиска можно задавать командой SetTitleMatchMode). Если этот и следующие 3 параметра опущены, будет использовано последнее найденное окно. Если параметр задан буквой А и следующие 3 параметра опущены, будет использовано активное окно. Чтобы задать окно через его класс, используйте конструкцию ahk_class ТочноеИмяКласса (можно посмотреть программой Window Spy). Чтобы использовать идентификатор процесса (PID), задайте параметр как ahk_pid %ПеременнаяСодержащаяPID%. Чтобы использовать группу окон, задайте параметр как ahk_group ИмяГруппы. Чтобы использовать идентификатор окна, задайте параметр как ahk_id %ПеременнаяСодержащаяID%. Сектор поиска можно сузить, задав несколько критериев, например, My File.txt ahk_class Notepad.
WinText Подстрока из одиночного текстового элемента окна (можно посмотреть программой Window Spy). Скрытые текстовые элементы определяются, если включено определение скрытого текста (команда DetectHiddenText).
ExcludeTitle Окна, чей заголовок включает значение этого параметра, исключаются.
ExcludeText Окна, чей текст включает значение этого параметра, исключаются.

19 (изменено: andy319, 2024-01-14 00:00:44)

Re: AHK: Реакция на сканер штрих-кода

ypppu,

WinText=A1
ControlGetPos , X, Y, Width, Height,,ahk_class XLMAIN, %WinText%
x:=x+2
y:=y+2
MouseMove, %x%, %Y%

Хорошо, но так не работает.
где A1 содержимое ячейки

Control=Edit1
WinText=A1
ControlGetPos , X, Y, Width, Height, %Control%, ahk_class XLMAIN, ;%WinText%

а так работает

20

Re: AHK: Реакция на сканер штрих-кода

Я и не говорил, как должно работать. Я лишь пояснил, за что отвечает параметр WinText в команде ControlGetPos, о чём Вы спросили в #17.

21

Re: AHK: Реакция на сканер штрих-кода

ypppu пишет:

отвечает

Но видимо, ответственности не несёт.

ypppu пишет:

как должно работать.

А все таки - как?

22

Re: AHK: Реакция на сканер штрих-кода

Вам нужно при помощи AutoHotkey отловить событие "USB-считыватель (который в некой программе определяется в качестве виртуального COM-порта) считал штрих-код", чтобы по этому событию AutoHotkey-скрипт  выделил в Excel определённую строку?

23 (изменено: Alectric, 2024-01-14 07:16:39)

Re: AHK: Реакция на сканер штрих-кода

andy319 пишет:

А все таки - как?

WinText - это уточнение для команды ControlGetPos (и любых других команд) какое конкретно искать окно (не элемент окна Control, а именно само окно, содержащее элементы).
Окон с одинаковым WinTitle может быть несколько, чтобы их различать и есть параметр WinText (он может отличаться в окнах с одинаковым WinTitle).

andy319 пишет:

Библиотеку скачал, загружаю и получаю ошибку -

Эта ошибка говорит о том что в коде две функции с одинаковым названием, как я понял ты смешал все в кучу в один файл.
Сохрани код Accessible Info Viewer в отдельный пустой файл и используй его как отдельную программу.

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

24

Re: AHK: Реакция на сканер штрих-кода

Оказывается есть метод по проще получить путь до кнопки: в AhkSpy Есть кнопка "Get path" которая его выдает, но перед этим нужно зафризить окно.

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

25

Re: AHK: Реакция на сканер штрих-кода

Alectric пишет:

В Viewerе нужно перетащить крестик на окно экселя, нажать кнопку "Get Parent" несколько раз, пока не высветится "Больше нет.", затем нажать "Show Acc Structure" и вручную пролистать все что там есть до нужной кнопки, внизу программы высветится полный путь до кнопки.

Сегодня вдруг заработало.

ypppu пишет:

отловить событие "USB-считыватель (который в некой программе определяется в качестве виртуального COM-порта) считал штрих-код"

- это был бы идеальный вариант. Но даже не представляю в какую сторону копать.

Alectric пишет:

в AhkSpy Есть кнопка "Get path"

Обязательно попробую! Спасибо!

26

Re: AHK: Реакция на сканер штрих-кода

andy319 пишет:
ypppu пишет:

отловить событие "USB-считыватель (который в некой программе определяется в качестве виртуального COM-порта) считал штрих-код"

- это был бы идеальный вариант. Но даже не представляю в какую сторону копать.

Думаю в эту:
https://learn.microsoft.com/en-us/windo … tcommevent

27

Re: AHK: Реакция на сканер штрих-кода

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

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

28

Re: AHK: Реакция на сканер штрих-кода

https://stackoverflow.com/questions/915 … are-in-use

29 (изменено: andy319, 2024-01-14 22:44:43)

Re: AHK: Реакция на сканер штрих-кода

Все посмотрел, спасибо, но, к сожалению, все это выходит за рамки моих познаний. 
Изначально мне казалось что получится проще.  Будем сканить строчки на экране и ждать их изменений...
Еще раз, всем спасибо за искреннее желание помочь!
А, да, забыл еще сказать - по итогам считывания комп булькает разными звуками, в зависимости от результата. Может это моя последняя надежда?

30

Re: AHK: Реакция на сканер штрих-кода

А разве сканер не посылает нажатия клавиш, тогда их можно отследить? Я только с такими встречался.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

31

Re: AHK: Реакция на сканер штрих-кода

serzh82saratov он не в режим разрыва клавиатуры включен. А так то наверняка или перевод строки идет или возврат каретки.

32

Re: AHK: Реакция на сканер штрих-кода

andy319 пишет:

наверняка

Проверьте в блокноте, а лучше в AhkSpy, мало ли непечатные отправляет.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

33

Re: AHK: Реакция на сканер штрих-кода

serzh82saratov пишет:

Проверьте в блокноте

Пробовал. Нет.

serzh82saratov пишет:

а лучше в AhkSpy

А вот это надо сделать!

34

Re: AHK: Реакция на сканер штрих-кода

Огромное всем спасибо за помощь и ведении в правильном направлении. Нашел в программе поле, очень неявно реагирующее на факт считывания штрихкода и ControlGetText адекватно на эти изменения реагирует!

35

Re: AHK: Реакция на сканер штрих-кода

andy319 пишет:

комп булькает разными звуками, в зависимости от результата.

Можно только определить что идет звук, а какой именно звук не знаю можно ли.

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

36

Re: AHK: Реакция на сканер штрих-кода

Alectric пишет:

Можно только определить что идет звук

что то мне подсказывает что это то же не совсем просто.

37

Re: AHK: Реакция на сканер штрих-кода

Глаза боятся, а руки делают.

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

38

Re: AHK: Реакция на сканер штрих-кода

Alectric пишет:

а какой именно звук не знаю можно ли.

Можно.
https://forum.script-coding.com/viewtopic.php?id=17258
На ахк такое переписать можно, но сложно и дорого.
Я бы рассчитывал, начиная от 1000$.

39

Re: AHK: Реакция на сканер штрих-кода

OFF:
20 лет назад программой "Горыныч" можно было распознать человеческую речь (правда, сначала надо было надиктовать-обучить), и всё это хозяйство почти не жрало процессор и оперативку. На сегодняшний день наверное уже совсем нетрудно распознать бульканье.

40

Re: AHK: Реакция на сканер штрих-кода

Распознование звуков и речи - 2 разные вещи, поэтому алгоритм горыныча тут не поможет.
Чтобы различить один чих от другого используют fft:
https://ru.wikipedia.org/wiki/%D0%91%D1 … 1%8C%D0%B5
Что и делает программа по моей ссылке.
Можно купить ее за 20 евро и использовать в автохотки через dllcall.

41

Re: AHK: Реакция на сканер штрих-кода

О распозновании речи не идет. Здесь звук идет как реакция на сканирование штрих кода. Нажал кнопку - штрих считался - компьютер булькнул.