Как получить данные сообщения от обратного вызова dll, вызванного с python обратно на python - PullRequest
1 голос
/ 19 февраля 2020

У меня есть программа Python и Dll, которая вызывается для установки ловушки для получения определенных сообщений windows. Я получаю сообщения в виде сообщения, что очень хорошо. Теперь я хочу перенести данные этого сообщения обратно в вызывающий файл python для дальнейшего анализа данных. Теперь я видел много разных подходов к этому. некоторые ppl делают это с 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.

1 Ответ

0 голосов
/ 10 марта 2020

Вы можете использовать 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()

Отладка:

1

Наконец, координаты мыши будут распечатаны. Вы можете обрабатывать их в Python в соответствии с координатами мыши.

...