【问题标题】:Python win32api SendMesagePython win32api 发送消息
【发布时间】:2013-02-09 12:13:32
【问题描述】:

我试图澄清 win32api。我只是做了一个简单的例子。获取记事本窗口,将鼠标移动到一个位置,单击并写入一个字符串。但它不起作用。有什么问题?
谁能帮我澄清一下 lParam 参数是什么?
它是做什么的,它是什么类型的,它应该是什么样子?

import win32api, win32con, win32gui, win32ui, win32service, os, time



def f_click(pycwnd):
        x=300
        y=300
        lParam = y <<15 | x
        pycwnd.SendMessage(win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, lParam);
        pycwnd.SendMessage(win32con.WM_LBUTTONUP, 0, lParam);

def get_whndl():
        whndl = win32gui.FindWindowEx(0, 0, None, 'NB.txt - Notepad')
        return whndl

def make_pycwnd(hwnd):       
        PyCWnd = win32ui.CreateWindowFromHandle(hwnd)
        return PyCWnd
        
def send_input_hax(pycwnd, msg):
    f_click(pycwnd)
    for c in msg:
        if c == "\n":
            pycwnd.SendMessage(win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
            pycwnd.SendMessage(win32con.WM_KEYUP, win32con.VK_RETURN, 0)
        else:
            pycwnd.SendMessage(win32con.WM_CHAR, ord(c), 0)
    pycwnd.UpdateWindow()
        
whndl = get_whndl()
pycwnd = make_pycwnd(whndl)
msg = "It works !\n"
send_input_hax(pycwnd,msg)

【问题讨论】:

    标签: python winapi pywin32 sendmessage


    【解决方案1】:

    记事本的主窗口内还有另一个窗口,您需要向它发送消息。您可以使用 Microsoft Spy++ 工具查看此“隐藏”窗口,也可以像这样获取所有子窗口:

    def callback(hwnd, hwnds):
        if win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
            hwnds[win32gui.GetClassName(hwnd)] = hwnd
        return True
    
    hwnds = {}
    win32gui.EnumChildWindows(whndl, callback, hwnds)
    

    我们正在寻找的窗口具有“编辑”类名称,它是记事本唯一启用且可见的子窗口。所以你的代码会这样工作:

    import win32api, win32con, win32gui, win32ui, win32service, os, time
    
    
    def f_click(pycwnd):
        x=300
        y=300
        lParam = y <<15 | x
        pycwnd.SendMessage(win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, lParam);
        pycwnd.SendMessage(win32con.WM_LBUTTONUP, 0, lParam);
    
    def get_whndl():
        whndl = win32gui.FindWindowEx(0, 0, None, 'NB.txt - Notepad')
        return whndl
    
    def make_pycwnd(hwnd):       
        PyCWnd = win32ui.CreateWindowFromHandle(hwnd)
        return PyCWnd
    
    def send_input_hax(pycwnd, msg):
        f_click(pycwnd)
        for c in msg:
            if c == "\n":
                pycwnd.SendMessage(win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
                pycwnd.SendMessage(win32con.WM_KEYUP, win32con.VK_RETURN, 0)
            else:
                pycwnd.SendMessage(win32con.WM_CHAR, ord(c), 0)
        pycwnd.UpdateWindow()
    
    whndl = get_whndl()
    
    def callback(hwnd, hwnds):
        if win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
            hwnds[win32gui.GetClassName(hwnd)] = hwnd
        return True
    hwnds = {}
    win32gui.EnumChildWindows(whndl, callback, hwnds)
    whndl = hwnds['Edit']
    
    pycwnd = make_pycwnd(whndl)
    msg = "It works !\n"
    send_input_hax(pycwnd,msg)
    

    lParam 是 int 并且您在此处看到的是技巧,它允许您通过单个参数传递多个值。假设我们需要将两位数传递给一个只接受一个参数的函数。我们可以将它们作为两位数发送并在函数内部拆分。同样,按位移位 (

    >>> x = 300
    >>> y = 300
    >>> lParam = y << 15 | x
    >>> lParam & 0x7FFF # x
    0: 300
    >>> lParam >> 15 # y
    1: 300
    

    您可以在WikipediaPython Wiki 中阅读有关按位运算的更多信息。

    【讨论】:

    • 谢谢,您的解释和 wiki 为我澄清了它,它现在可以工作了。是的,记事本有另一个子窗口。但我会说一下lParam。它是一个只有 4 个字节的数字,所以要获得正确的 lParam 值,我应该将整数(x=300,y=300)的坐标转换为 2 个字节的数字(WORD),而不是按正确的顺序连接它们(低字是x, 高是 y)。顺便说一句,在 C++ 中有宏 MAKELPARAM(),所以你也可以通过使用 ctypes 模块在 python 中调用它。
    • 不应该是lParam = y &lt;&lt; 16 | x吗?
    • @mFoxRU 刚查了win api docs,我觉得你是对的,docs说它是低位词和高位词,词的意思是16位。仅在这种情况下有效,因为 300 是偶数(最后有 0)。 15 是在最初的问题中,我并没有想太多
    • @mFoxRU 是的,我尝试使用 15 并且坐标已关闭。使用 16 修复它
    猜你喜欢
    • 2021-06-10
    • 2021-06-06
    • 2015-05-14
    • 1970-01-01
    • 2013-02-12
    • 2017-04-02
    • 2015-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多