如何将点击从一个应用程序“镜像”到另一个应用程序?

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 镜像从一台主机安全地传输到另一台主机?

如何在不使用存储库的情况下将Docker镜像从一个主机复制到另一个主机

试图通过 ipc 将数据从一个电子窗口发送到另一个电子窗口

如何将 iOS 应用程序从一个开发者帐户转移到另一个帐户? [关闭]