发表回复 
等光标位置() — 确保处于输入状态
2019-04-29, 05 : 51 (这个帖子最后修改于: 2019-05-04 03 : 06 by feiyue.)
Rainbow 等光标位置() — 确保处于输入状态
由于AHK内置的获取光标位置变量 A_CaretX、A_CaretY不太可靠,
在360浏览器、QQ或者其他程序中经常出错,造成我们编写自动化
脚本时难以确保已经进入输入状态。所以我写了个函数解决这个问题。Smile


代码: (全选)
;-- 按 【F2】热键测试:点击后等光标位于鼠标附近,1秒超时

F2::
t:=A_TickCount
CoordMode, Mouse, Screen
MouseGetPos, x, y
Click
ok:=等光标位置(x, y, 150, 10, 1)
MsgBox, 4096,
  , % "检测结果:" (ok ? "成功":"失败")
  . "`n消耗时间:" (A_TickCount-t) " 毫秒"
return


;---------------------------
;  等光标位置() -- By FeiYue
;---------------------------
;  参数说明:x,y 为中心点屏幕坐标
;  w,h 为相对于中心点的左右和上下的偏移距离
;  所以左上角-->右下角的范围是(x-w, y-h, x+w, y+h)
;  t 为等待秒数,设为0则不等待只检查一次就返回
;  ClickCount 为鼠标点击几次,设为0则不点击
;  返回值:等待时间内光标处于位置就返回1,否则0
;---------------------------
等光标位置(x, y, w, h, t=0, ClickCount=0)
{
  xywh2xywh(x-w,y-h,2*w+1,2*h+1, x,y,w,h)
  if (w<1 or h<1)
    return, 0
  if (ClickCount)
  {
    cmm:=A_CoordModeMouse
    CoordMode, Mouse, Screen
    MouseMove, x, y, 0
    Click, %x%, %y%, %ClickCount%
    CoordMode, Mouse, %cmm%
  }
  Send {Right}{Left}
  Sleep, 100
  hash:=GetHashFromScreen(x,y,w,h)
  endt:=A_TickCount+Round(t*1000)
  cmc:=A_CoordModeCaret
  Loop {
    CoordMode, Caret, Screen
    cx:=A_CaretX, cy:=A_CaretY+8
    CoordMode, Caret, %cmc%
    if (cx>=x and cx<=x+w-1 and cy>=y and cy<=y+h-1)
      return, 1
    Sleep, 50
    if GetHashFromScreen(x,y,w,h)!=hash
      return, 1
    if (A_TickCount>=endt)
      return, 0
  }
}

;---------------------------
;  GetHashFromScreen() -- By FeiYue
;---------------------------
;  参数说明:x,y 为矩形范围左上角屏幕坐标
;  w,h 为矩形范围的宽度和高度
;  返回值:返回屏幕指定范围的图像哈希值
;---------------------------
GetHashFromScreen(x, y, w, h)
{
  static Ptr:=A_PtrSize ? "UPtr" : "UInt", PtrP:=Ptr "*"
  ListLines, % "Off" (lls:=A_ListLines=0 ? "Off":"On")/0
  bch:=A_BatchLines
  SetBatchLines, -1
  hash:=0, bpp:=32, Stride:=((w*bpp+31)//32)*4
  win:=DllCall("GetDesktopWindow", Ptr)
  hDC:=DllCall("GetWindowDC", Ptr,win, Ptr)
  mDC:=DllCall("CreateCompatibleDC", Ptr,hDC, Ptr)
  ;--------------------
  VarSetCapacity(bi, 40, 0), NumPut(40, bi, 0, "int")
  NumPut(w, bi, 4, "int"), NumPut(h, bi, 8, "int")
  NumPut(1, bi, 12, "short"), NumPut(bpp, bi, 14, "short")
  ;--------------------
  if hBM:=DllCall("CreateDIBSection", Ptr,mDC, Ptr,&bi
    , "int",0, PtrP,ppvBits, Ptr,0, "int",0, Ptr)
  {
    oBM:=DllCall("SelectObject", Ptr,mDC, Ptr,hBM, Ptr)
    DllCall("BitBlt", Ptr,mDC, "int",0, "int",0, "int",w, "int",h
      , Ptr,hDC, "int",x, "int",y, "uint",0x00CC0020|0x40000000)
    hash:=DllCall("ntdll\RtlComputeCrc32", "uint",0
      , Ptr,ppvBits, "uint",Stride*h, "uint")
    DllCall("SelectObject", Ptr,mDC, Ptr,oBM)
    DllCall("DeleteObject", Ptr,hBM)
  }
  DllCall("DeleteDC", Ptr,mDC)
  DllCall("ReleaseDC", Ptr,win, Ptr,hDC)
  SetBatchLines, %bch%
  ListLines, %lls%
  return, hash
}

xywh2xywh(x1,y1,w1,h1,ByRef x,ByRef y,ByRef w,ByRef h)
{
  SysGet, zx, 76
  SysGet, zy, 77
  SysGet, zw, 78
  SysGet, zh, 79
  left:=x1, right:=x1+w1-1, up:=y1, down:=y1+h1-1
  left:=left<zx ? zx:left, right:=right>zx+zw-1 ? zx+zw-1:right
  up:=up<zy ? zy:up, down:=down>zy+zh-1 ? zy+zh-1:down
  x:=left, y:=up, w:=right-left+1, h:=down-up+1
}
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
[+] 2用户表示感谢feiyue
2019-04-29, 10 : 09
RE: 等光标位置() —— 确保已经进入输入状态
测试了下,有点不太稳定。
文件重命名时,按F2直接就跳到下一个文件了。
在记事本中测试,有时可以,有时不行。
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2019-04-29, 10 : 57 (这个帖子最后修改于: 2019-04-29 12 : 52 by feiyue.)
RE: 等光标位置() —— 确保已经进入输入状态
不是函数不稳定,是你还不会用。Smile

重命名时,出现可编辑状态就不用点击了,
但是我的F2热键的例子中又点击了一下,应该改一下。
(由于桌面F2可以重命名,不妨把例子的热键改为F8)

例子中的参数范围是鼠标点击后,检测光标出现在
鼠标位置的左右150像素,上下10像素的小范围中,
如果你自己把鼠标离光标太远,当然超出了范围。
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2019-04-30, 17 : 12
RE: 等光标位置() — 确保处于输入状态
所以使用这个函数时要先预判光标的坐标,然后在坐标周边的指定范围内,去进行判定?
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2019-05-04, 03 : 22 (这个帖子最后修改于: 2019-05-04 03 : 25 by feiyue.)
RE: 等光标位置() — 确保处于输入状态
@fallenyugo 对的。使用时,一般是点击操作后,判断光标在鼠标的坐标附近闪动,就返回成功。
如果不点击,而是发送按键(比如:Tab)那么就要预判光标的坐标,然后在坐标的周边指定范围。
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2019-05-05, 17 : 20
RE: 等光标位置() — 确保处于输入状态
你好 Feiyue,
请问如何获得闪烁光标的实时位置?
返回 x,y的坐标. 

谢谢!
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2019-05-05, 20 : 12
RE: 等光标位置() — 确保处于输入状态
目前只有A_CaretX的方法,但是并不可靠,因为有些软件会屏蔽光标信息,比如QQ。
要找目标编辑框不如找字,如登录,然后计算偏移距离。其实不要光标位置也不影响自动化操作。
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2019-05-07, 10 : 51
RE: 等光标位置() — 确保处于输入状态
在整理一个英文输入法脚本,
有些软件不能识别光标的位置, 所以弹出的输入法候选框位置, 老是偏离光标太多.
有些不方便.
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
发表回复 


论坛跳转:


联系我们 | Autohotkey 中文站 | 回到顶部 | 回到正文区 | 精简(归档)模式 | RSS 聚合