【问题标题】:How to get message data from a dll Callback called from python back to python如何从从python调用的dll回调中获取消息数据回到python
【发布时间】:2020-06-04 03:14:26
【问题描述】:

我有一个 Python 程序和 Dll,它被调用来设置一个挂钩来接收某些 Windows 消息。我正在以消息框的形式收到消息,这非常好。现在我想将此消息数据传输回调用 python 文件以进行进一步的数据分析。现在我看到了很多不同的方法。一些人用 ctypes 来做,其他人用进程间通信来做。我只想知道实现实时通信最可行的方法是什么。我也是一个 C 的菜鸟,所以这没有帮助。

DLL:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <zmq.h>
HHOOK tHook;
HMODULE hinstDLL;
LRESULT CALLBACK meconnect(int code, WPARAM wParam, LPARAM lParam) {
    if (code == HC_ACTION) {
        LPMSG data = (LPMSG)lParam;
        UINT message = data->message;
        switch (message)
        {
        case WM_POINTERUPDATE:
            if (!IS_POINTER_INCONTACT_WPARAM(wParam))
                break;
        case WM_POINTERDOWN:
        case WM_POINTERUP:
            //Here will be some more data extraction like coordinates or Pointertype
        }
        return(CallNextHookEx(tHook, code, wParam, lParam));
    }
}
extern "C" __declspec(dllexport) BOOL SetHook()
{
    tHook = SetWindowsHookEx(WH_GETMESSAGE, meconnect, hinstDLL, 0);

    if (tHook == NULL)
        return FALSE;
    else
        return TRUE;
}
extern "C" __declspec(dllexport) BOOL UnHook()
{
    return UnhookWindowsHookEx(tHook);
}


BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        hinstDLL = hModule;
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Python:

def pointer_msg_loop():
    global lib
    lib = cdll.LoadLibrary(r'PATH\MessagesDll\x64\Release\HOOKDLL.dll')
    print(lib)
    #res = lib.ConnectServer()
    res = lib.SetHook()
    pythoncom.PumpMessages()
    res = lib.UnHook()

最好的办法是从 dll 接收数据结构,因为在 python 中我可以比在 C 中更好地提取数据。

【问题讨论】:

    标签: python c winapi dll hook


    【解决方案1】:

    您可以使用PostMessage 发送自定义消息。

    在DLL代码中需要添加:

    #define WM_RETICULATE_SPLINES (WM_USER + 0x0001)
    
    case WM_POINTERUP:
                //Here will be some more data extraction like coordinates or Pointertype
                //PostMessage will send mouse coordinates
                PostMessage(data->hwnd, WM_RETICULATE_SPLINES, data->wParam, data->lParam);
            }
    

    python 代码示例:

    要获取自定义消息,需要创建一个窗口,然后在回调函数中接受自定义消息。

    import win32api, win32con, win32gui 
    import win32gui_struct 
    import ctypes 
    from ctypes import * 
    GUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}" 
    WM_RETICULATE_SPLINES =  (win32con.WM_USER + 0x0001)
    class MyWindow: 
    
        def __init__(self): 
            win32gui.InitCommonControls() 
            self.hinst = win32api.GetModuleHandle(None) 
            className = 'MyWndClass' 
            message_map = { 
            win32con.WM_DESTROY: self.OnDestroy, 
            win32con.WM_DEVICECHANGE: self.OnDeviceChange, 
            win32con.WM_CREATE: self.OnCreate, 
            WM_RETICULATE_SPLINES: self.RETICULATE, 
            } 
            className = 'MyWndClass' 
            wc = win32gui.WNDCLASS() 
            wc.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW 
            wc.lpfnWndProc = message_map 
            wc.lpszClassName = className 
            win32gui.RegisterClass(wc) 
            style = win32con.WS_OVERLAPPEDWINDOW 
            self.hwnd = win32gui.CreateWindow(className,'My win32api app',style,win32con.CW_USEDEFAULT,win32con.CW_USEDEFAULT,300,300,0,0,self.hinst,None) 
            # register for a device notification - we pass our service handle 
            # instead of a window handle. 
            filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE(GUID_DEVINTERFACE_USB_DEVICE) 
            self.hdn = win32gui.RegisterDeviceNotification(self.hwnd, filter, 4) 
            win32gui.ShowWindow(self.hwnd, win32con.SW_SHOW) 
            win32gui.UpdateWindow(self.hwnd)    
        def OnDestroy(self, hwnd, message, wparam, lparam): 
            win32gui.UnregisterDeviceNotification(self.hdn) 
            win32gui.PostQuitMessage(0) 
            return True 
        def OnDeviceChange(self, hwnd, message, wparam, lparam): 
            ctypes.windll.user32.MessageBoxW(0, "DeviceChange", "Message", 1) 
            return True 
        def OnCreate(self, hwnd, message, wparam, lparam): 
            ctypes.windll.user32.MessageBoxW(0, "Create", "Message", 1) 
            return True 
        def RETICULATE(self, hwnd, message, wparam, lparam): 
            x = lparam & 0xffff
            y = (lparam >> 16) & 0xffff
            print(x,y)
            return True 
    
    
    w = MyWindow() 
    lib = cdll.LoadLibrary(r'D:\path\Debug\Dll_5.dll')
    res = lib.SetHook()
    win32gui.PumpMessages()
    lib.UnHook()
    

    调试:

    最后,鼠标坐标将被打印出来。你可以根据鼠标坐标在Python中处理它们。

    【讨论】:

    • @Oliver Braun 嗨,这个答案对您有用吗?如果您有任何问题,请告诉我。
    猜你喜欢
    • 1970-01-01
    • 2013-11-23
    • 2014-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多