WINAPI SendMessage 到特定区域的 hWnd

WINAPI SendMessage to a hWnd in a specific area

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

嗯,所以我想对这个 hWnd 使用 SendMessage 并将 keyPressed 作为消息传递给第一个和第二个插槽(因为它们不是单独的 windows,我不能占用每个插槽window句柄)。问题在于实现这些偏移量以设置我要发送这些消息的区域。

基本上,我正在为一款离线游戏制作培训师,以练习内存管理方面的内容并了解 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);
    }
}

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

Windows 将鼠标消息发送到基于左上角的 window。所以 window 的左上角是 (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!!!

美中不足的是windows将WM_LBUTTON消息坐标解释为屏幕坐标。在那种情况下,我们必须向后工作。弄清楚我们要在客户区中单击的位置后,我们需要知道该位置的屏幕坐标。在那种情况下,我们使用(一位好心的用户指出它不翻译坐标所以忽略这个位 - 只需发送客户端坐标)

POINT thePointWeWantOnTheClient;
ClientToScreen(hWnd, &thePointWeWantOnTheClient);

并改用这一点。直到明天早上我才能测试这个。

值得指出的是,SendMessage 正在阻塞,因此它会阻塞 GUI。 PostMessage 只是在你想要的消息队列中填充。

您在发送消息时没有指定正确的鼠标坐标。 GetCursorPos() returns当前鼠标在屏幕坐标中的位置,然后在发送鼠标时需要将其转换为客户端坐标发给 window 的消息,例如:

#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,而是直接使用 and/or WM_CHAR。然而,you can’t simulate keyboard input with PostMessage.