如何将点击从一个应用程序“镜像”到另一个应用程序?
Posted
技术标签:
【中文标题】如何将点击从一个应用程序“镜像”到另一个应用程序?【英文标题】:How to 'mirror' clicks from one application to another one? 【发布时间】:2020-05-13 02:53:00 【问题描述】:我正在尝试从 Windows 安装的应用程序中捕获点击。所以目标是获得相对于打开的应用程序宽度和高度的点击位置;不是屏幕宽度和高度。
例如,假设您在屏幕的上半部分打开了“绘画”,然后单击菜单上的“画笔”选项。
例如,您可以使用 Python 模块 pynput 轻松获得点击位置,但这会根据屏幕尺寸获得位置。所以如果你有一个 1920x1080 的屏幕,点击位置将在这些坐标之间。但是,我想要相对于应用程序(Paint)大小的位置(即在 600 和 900 之间;假设 Paint 在屏幕左侧打开)。
这有点难以解释,所以请看下面的图片,它应该解释我想要完成的事情。
Image
图像有两个画图窗口。顶部是我要跟踪点击的窗口(在这种情况下,您实际上看不到光标,但它正指向“画笔”箭头)。第二个窗口来自 OpenCV,并试图显示点击发生的位置(蓝色圆圈),但它与实际位置相去甚远。
这是我的算法的概述:
-
我正在使用 win32gui 获取应用程序(在本例中为画图)的宽度和高度。现在
它可能并不总是我可能使用的同一个应用程序。它可能是另一个安装在 Windows 上的应用程序,这就是我使用 win32gui 的原因。
然后我得到当前的鼠标位置(这里我只是得到鼠标位置而不是实际的点击位置,因为它更容易表示,但它是完全相同的)
最后,我使用“mss”截取应用程序的屏幕截图并将其传递给 OpenCV,以便在其上绘制鼠标位置。这是我得到错误位置的地方。
import ctypes
import win32gui
import cv2
import mss
import time
import numpy as np
## Set countdown to have enough time to put the mouse in the correct position
for i in range(5, 0, -1):
print(i)
time.sleep(1)
## Get application width and height
ctypes.windll.user32.SetProcessDPIAware() ## No idea why but I must set this, otherwise I get wrong results from win32gui.GetWindowRect()
hwnd = win32gui.FindWindow(None, "Untitled - Paint")
left, top, right, bottom = win32gui.GetWindowRect(hwnd)
left = left + 8
width = right - left - 8
height = bottom - top - 8
monitor = "top": top, "left": left, "width": width, "height": height
print(width, height)
## Get current mouse screen position
x, y = win32gui.GetCursorPos()
print(x, y)
## Grab a screenshoot of the application
with mss.mss() as sct:
screen = sct.grab(monitor)
img = np.array(screen)
img = cv2.rectangle(img, (0, 0), (width, height), (255, 0, 0), 2) ## Drawing rectangle around screenshot of the application
img = cv2.circle(img, (x*width//1920, y*height//1080), 20, (255, 0, 0), -1) ## Drawing set of points from the current mouse screen position
cv2.imshow('window', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
【问题讨论】:
【参考方案1】:的第三个参数是cv2.circle
与背景图片相关的圆心坐标(img
)。
您可以使用ScreenToClient
将屏幕上指定点的屏幕坐标转换为客户区坐标。
import ctypes
import win32gui
import cv2
import mss
import time
import numpy as np
## Set countdown to have enough time to put the mouse in the correct position
for i in range(5, 0, -1):
print(i)
time.sleep(1)
## Get application width and height
ctypes.windll.user32.SetProcessDPIAware() ## No idea why but I must set this, otherwise I get wrong results from win32gui.GetWindowRect()
hwnd = win32gui.FindWindow(None, "Untitled - Paint")
left, top, right, bottom = win32gui.GetWindowRect(hwnd)
left = left + 8
width = right - left - 8
height = bottom - top - 8
monitor = "top": top, "left": left, "width": width, "height": height
print(width, height)
## Get current mouse screen position
x, y = win32gui.GetCursorPos()
print(x, y)
## Grab a screenshoot of the application
with mss.mss() as sct:
screen = sct.grab(monitor)
img = np.array(screen)
img = cv2.rectangle(img, (0, 0), (width, height), (255, 0, 0), 2) ## Drawing rectangle around screenshot of the application
pos = win32gui.ScreenToClient(hwnd,(x,y))
x = pos[0]
y = pos[1]
print(x, y)
img = cv2.circle(img, (x, y), 20, (255, 0, 0), -1) ## Drawing set of points from the current mouse screen position
cv2.imshow('window', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
【讨论】:
以上是关于如何将点击从一个应用程序“镜像”到另一个应用程序?的主要内容,如果未能解决你的问题,请参考以下文章
如何将数据从一个 Fragment 发送到另一个 Fragment?
如何将 Firebase iOS 中的数据从 TableViewController 传递到另一个 ViewController
Docker+SSH,如何定期将 docker 镜像从一台主机安全地传输到另一台主机?