如何从一个应用程序中 "镜像 "点击到另一个应用程序?

问题描述 投票:0回答:1

我正试图从一个Windows安装的应用程序中捕捉点击。因此,我们的目标是获得与打开的应用程序的宽度和高度相关的点击位置,而不是屏幕的宽度和高度。

例如,假设你在屏幕的上半部分打开了 "Paint",你点击了菜单上的 "Brushes "选项。

例如,你可以使用Python模块pynput很容易地得到点击的位置,但这将得到相对于屏幕大小的位置。所以如果你有一个1920x1080的屏幕,点击位置将在这些坐标之间。然而,我想要的是相对于应用程序(Paint)大小的位置(即在600和900之间;假设Paint是在屏幕左侧打开的)。

这有点难以解释,所以请看下面的图片,它应该可以解释我试图实现的目标。

画面

图片上有两个Paint窗口,上面的那个是我想跟踪点击的窗口。顶部的那个窗口是我想跟踪点击的窗口(在这种情况下,你实际上看不到光标,但它正指向 "刷子 "箭头)。第二个窗口是OpenCV的,它试图显示点击发生的位置(蓝色圆圈),但它与实际应该的位置相差甚远。

下面是我的算法的概述。

  1. 我使用win32gui来获取应用程序(本例中为Paint)的宽度和高度。现在,它可能并不总是我所使用的同一个应用程序,它可能是安装在Windows上的另一个应用程序。它可能是安装在Windows上的另一个应用程序,这就是为什么我使用win32gui。
  2. 然后我得到当前鼠标的位置(这里我只是得到鼠标的位置而不是实际的点击位置,因为它更容易表示,但它是完全一样的东西)。
  3. 最后,我用 "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()
python opencv winapi
1个回答
0
投票

第3个参数的坐标是 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()

结果是:在屏幕上指定点的屏幕坐标转换为客户端区域坐标。enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.