WINAPI 将消息发送到特定区域中的 hWnd

WINAPI SendMessage to a hWnd in a specific area

本文关键字:区域 hWnd 消息 WINAPI      更新时间:2023-10-16

所以基本上我得到了一个窗口处理程序,它是一个包含 16 个插槽的 Pic(矩形)。

好吧,所以我想使用SendMessage到这个hWnd,并给一个keyPress作为消息发送到第一个和第二个插槽(因为它们不是单独的窗口,所以我不能拿每个插槽窗口句柄)。问题在于实现这些偏移量以设置我要发送这些消息的区域。

基本上,我正在为离线游戏制作一个训练器,以练习内存管理并学习WINAPI的工作原理。这是代码(不包括 DllMain 函数)。

#include <windows.h>
#include <stdio.h>
#define VIDAACTUAL 0x70D27E
#define VIDAMAX 0x70D27C
#define MANAACTUAL 0x70D282
#define MANAMAX 0x70D280
void AutoPot(){
    Sleep(5000); //Giving myself time to place the cursor.
    POINT P;
    GetCursorPos(&P);
    HWND hwnd = WindowFromPoint(P);
    Sleep(50);
    while (1){
        WORD hpMax = *(WORD*)(VIDAMAX);
        WORD hpAct= *(WORD*)(VIDAACTUAL);
        WORD mpMax = *(WORD*)(MANAMAX);
        WORD mpAct = *(WORD*)(MANAACTUAL);
        if (hpAct != 0)
        {
            if (hpAct != hpMax)
            {
                SendMessage(hwnd, WM_LBUTTONUP, 0, 0);
                //SendMessage(hwnd, WM_LBUTTONDBLCLK, 0, 0);
                //SendMessage(hwnd, VK_SPACE, 0, 0);
            }
            else if (mpAct!= mpMax && mpMax != 0){ //Giving priority to red pots.
                SendMessage(hwnd, WM_LBUTTONUP, 0,0);
                //SendMessage(hwnd, WM_LBUTTONDBLCLK, 0,0);
                //SendMessage(hwnd, VK_SPACE, 0, 0);
            }
        }
        Sleep(50);
    }
}

那么,有没有办法选择hWnd内的特定区域来发送这些消息?

发送消息时未指定正确的鼠标坐标。 GetCursorPos() 返回屏幕坐标中的当前鼠标位置,然后您需要在向窗口发送鼠标消息时将其转换为客户端坐标,例如:

#include <windows.h>
#include <stdio.h>
#define VIDAACTUAL 0x70D27E
#define VIDAMAX 0x70D27C
#define MANAACTUAL 0x70D282
#define MANAMAX 0x70D280
void AutoPot()
{
    Sleep(5000); //Giving myself time to place the cursor.
    POINT P;
    GetCursorPos(&P);
    HWND hwnd = WindowFromPoint(P);
    ScreenToClient(hwnd, &P); // <-- here
    Sleep(50);
    while (1){
        WORD hpMax = *(WORD*)(VIDAMAX);
        WORD hpAct= *(WORD*)(VIDAACTUAL);
        WORD mpMax = *(WORD*)(MANAMAX);
        WORD mpAct = *(WORD*)(MANAACTUAL);
        if (hpAct != 0)
        {
            if (hpAct != hpMax)
            {
                PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(P.x, P.y));
                //PostMessage(hwnd, WM_LBUTTONDBLCLK, 0, MAKELPARAM(P.x, P.y));
            }
            else if ((mpAct != mpMax) && (mpMax != 0)) //Giving priority to red pots.
            {
                PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(P.x, P.y));
                //PostMessage(hwnd, WM_LBUTTONDBLCLK, 0, MAKELPARAM(P.x, P.y));
            }
        }
        Sleep(50);
    }
}

仅供参考,VK_SPACE不是有效的消息标识符(其值为 0x20 ,与WM_SETCURSOR消息的值相同)。您必须改用WM_KEYDOWNWM_KEYUP,和/或直接使用WM_CHAR。 但是,不能使用 PostMessage 模拟键盘输入。

Windows 将鼠标消息发送到基于左上角的窗口。因此,窗口的左上角是 (0,0)。如果您知道要向其发送消息的项目的位置,请在发送消息中传递它们。如果没有,你必须调用getClientRect(hWnd...)并做一些数学:)

//we get the client rect
RECT rect;
GetClientRect(hWnd, &rect);
//rect = { LONG top, left, right bottom }
//i guess here we divide the rect into 4x4 squares (no idea of your layout)
//so pick a square to get xpos and ypos
int x, y; //can't calculate these i have no idea of your layout
LPARAM lParam = MAKELPARAM(x, y);
PostMessage(hWnd, WM_LBUTTONDOWN, 0, lParam); //NOT SendMessage!!!

美中不足的是,窗口将WM_LBUTTON消息坐标解释为屏幕坐标。在这种情况下,我们必须向后工作。在确定了我们要在工作区中单击的位置后,我们需要知道屏幕坐标。在这种情况下,我们使用(一位好心的用户指出它不会转换坐标,所以忽略这一点 - 只需发送客户端坐标)

POINT thePointWeWantOnTheClient;
ClientToScreen(hWnd, &thePointWeWantOnTheClient);

并改用这一点。直到明天早上我才有机会对此进行测试。

值得指出的是,SendMessage 正在阻止,因此它将阻止 GUI。PostMessage只是填充到您想要的消息队列中。