pywin32在画图中绘制图形

pywin32在画图中绘制图形

获取画图的窗口句柄

  • 由于画图程序的特殊性,与之前的浏览器窗口不同,其在主窗口下还有多个子窗口,我通过spy++软件找到了绘图区窗口的信息。在这里插入图片描述

  • 可以看出这个绘图子窗口的caption为空,只有一个class(这个值也是会变的),尝试了几次使用FindWindow()函数并没有什么用,直接将handle值赋值后下次开机有是不同的句柄号。于是我们只能通过找画图这个父句柄来获取绘图子窗口的句柄
    窗口结构

  • 因为绘图子窗口句柄会变化所以我们需要找到不变化的它的上一级即class为’MSPaintView’的窗口再获取到它子窗口句柄组的第一个。

    '''
    获得parent的所有子窗口句柄
     返回子窗口句柄列表
     '''
    def get_child_windows(parent):
        if not parent:
            return
        hwndChildList = []
        win32gui.EnumChildWindows(parent, lambda hwnd, param: param.append(hwnd),  hwndChildList)
        return hwndChildList
    hwnd0 = win32gui.FindWindow( None,"无标题 - 画图")  #获取画图窗口句柄
    
    for childh in get_child_windows(hwnd0):
        clsname = win32gui.GetClassName(childh)
        if clsname == 'MSPaintView':
            hwnd = get_child_windows(childh)[0]
            break
    #获取绘图区子窗口句柄
    
  • 这样我们就获取到了绘图区的窗口句柄了,下面就是让它画图,我们拿鼠标画图的时候按住左键,然后再拖动鼠标,这里要考虑到我们绘制图形的连续性比较复杂,这里就简单地用快速画点的方式去绘制吧。

点击事件

  • 鼠标点击大致有两种方式.一种就是真实地移动你的物理鼠标即模拟你使用鼠标移动和点击等等行为,第二种是向窗口发送鼠标事件,显然我们会更喜欢后者。(只是懒得找移动鼠标代码了)

    def clickLeftCur(mX, mY):  #在(mX,mY)处单击一哈
        win32gui.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, 0, mX + mY * 65536)#左键按下
        time.sleep(0.00000001) #象征性地延时100ns不过对于电脑来说还是挺长的呢 
        win32gui.PostMessage(hwnd, win32con.WM_LBUTTONUP, 0, mX + mY * 65536)#左键起来
    

绘制图形

  • 现在万事具备了,我们来绘制一个圆吧,

    R=100 #半径
    cX=300	
    cY=300	#圆心坐标
    for i in range(1000): #将圆分为1000个点
        clickLeftCur(int(cX+R*math.sin(2*math.pi*(i/1000))),int(cY+R*math.cos(2*math.pi*(i/1000))))
    cv2.imshow('paint',window_capture(hwnd))#再用上次学的显示一下图片
    

在这里插入图片描述

完整代码

import win32gui, win32ui, win32con, win32api
import cv2
import numpy as np
import math
import time


def clickLeftCur(mX, mY):  #单击
    win32gui.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, 0, mX + mY * 65536)
    time.sleep(0.000000001)
    win32gui.PostMessage(hwnd, win32con.WM_LBUTTONUP, 0, mX + mY * 65536)


def window_capture(hwnd):
    hwndDC = win32gui.GetWindowDC(hwnd)
    # 根据窗口句柄获取窗口的设备上下文DC(Divice Context)
    mfcDC = win32ui.CreateDCFromHandle(hwndDC)
    # 根据窗口的DC获取mfcDC
    saveDC = mfcDC.CreateCompatibleDC()
    # mfcDC创建可兼容的DC
    saveBitMap = win32ui.CreateBitmap()
    # 创建bigmap准备保存图片
    rctA = win32gui.GetWindowRect(hwnd)
    w = rctA[2] - rctA[0]
    h = rctA[3] - rctA[1]
    #获取图片大小
    # 截取从左上角(0,0)长宽为(w,h)的图片

    saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
    # 为bitmap开辟空间
    saveDC.SelectObject(saveBitMap)
    # 高度saveDC,将截图保存到saveBitmap中
    saveDC.BitBlt((0, 0), (w, h), mfcDC, (0, 0), win32con.SRCCOPY)

    signedIntsArray = saveBitMap.GetBitmapBits(True)
    img = np.frombuffer(signedIntsArray, dtype="uint8")
    img.shape = (h, w, 4)
    #bit图转mat图

    win32gui.DeleteObject(saveBitMap.GetHandle())
    mfcDC.DeleteDC()
    saveDC.DeleteDC()
    #释放内存
    return cv2.cvtColor(img, cv2.COLOR_RGBA2RGB)  #转为RGB图返回
    
def get_child_windows(parent):
    '''
    获得parent的所有子窗口句柄
     返回子窗口句柄列表
     '''
    if not parent:
        return
    hwndChildList = []
    win32gui.EnumChildWindows(parent, lambda hwnd, param: param.append(hwnd),  hwndChildList)
    return hwndChildList

hwnd0 = win32gui.FindWindow( None,"无标题 - 画图")  #获取画图窗口句柄

for childh in get_child_windows(hwnd0):
    clsname = win32gui.GetClassName(childh)
    if clsname == 'MSPaintView':
        hwnd = get_child_windows(childh)[0]
        break

#获取绘图区子窗口句柄
R=100
cX=300
cY=300
for i in range(1000):
    clickLeftCur(int(cX+R*math.sin(2*math.pi*(i/1000))),int(cY+R*math.cos(2*math.pi*(i/1000))))
cv2.imshow('paint',window_capture(hwnd))
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

相逢丶笑呵呵

学废了吗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值