【问题标题】:SendMessage click (works only if the mouse is over the button)SendMessage 单击(仅当鼠标悬停在按钮上时才有效)
【发布时间】:2020-07-18 03:03:51
【问题描述】:

我以前做过,但是用这个特定的按钮,它不起作用!

如果我点击按钮手动创建一个新窗口(小地图): Image

/////// 但是以编程方式我可以看到按钮上的动画,就好像它被点击了gif

但是窗口(小地图)不显示

            int x = 9, y = 8;
            IntPtr lParam = (IntPtr)((y << 16) | x);
            WinAPIs.PostMessage(button, WinAPIs.WM_LBUTTONDOWN, (IntPtr)0x01, lParam);
            WinAPIs.PostMessage(button, WinAPIs.WM_LBUTTONUP, IntPtr.Zero, lParam);

只有当我的代码发送消息时鼠标悬停在按钮上才会创建小地图。

这是 YouTube 上的 10 秒视频:Video

注意:视频中,我没有用鼠标点击按钮, 我刚刚将其悬停。

UPDATE1: Spy++ Messages Image

UPDATE2: 游戏使用 GetCursorPos 和 WindowFromPoint 来获取光标下窗口的句柄并将其与按钮的句柄进行比较,我需要弄清楚如何挂钩 WindowFromPoint 以发送按钮的即使游戏在后台也能处理。

【问题讨论】:

  • 评论不用于扩展讨论;这个对话是moved to chat
  • 好的,所以我对游戏进行了逆向工程,它使用 GetCursorPos 和 WindowFromPoint 来检查按钮句柄与我发送的消息,所以现在我需要想办法挂钩 WindowFromPoint 发送按钮的句柄,即使它不在前台。

标签: c# winapi sendmessage postmessage deviare


【解决方案1】:

我找到了答案,

首先,我必须对游戏进行逆向工程,

我发现它是使用 WindowFromPoint 来获取当前光标位置下的窗口句柄并将其与按钮的句柄进行比较。

意味着当游戏在后台时机器人将无法工作。

所以我必须弄清楚如何挂钩 WindowFromPoint 调用并更改返回值,这样即使游戏在后台,我也可以发送按钮的句柄

我使用这个库来做到这一点:Deviare

这里是Quickstart 的使用方法。

这是我的代码:

using System;
using System.Windows.Forms;
using Nektra.Deviare2;

public partial class Form1 : Form
{
    private NktSpyMgr _spyMgr;
    public Form1()
    {
        InitializeComponent();

        _spyMgr = new NktSpyMgr();
        _spyMgr.Initialize();
        _spyMgr.OnFunctionCalled += new DNktSpyMgrEvents_OnFunctionCalledEventHandler(OnFunctionCalled);
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        //Search for the game process
        var processes = System.Diagnostics.Process.GetProcessesByName("Conquer");
        int processID = 0;
        if (processes.Length < 1)
        {
            MessageBox.Show("Couldn't find Conquer", "Error");
            Environment.Exit(0);
        }
        else
        {
            //Found the game
            processID = processes[0].Id;
        }

        //Hook WindowFromPoint with 'flgOnlyPostCall' meaning OnFunctionCalled will be triggered after the api call and before the value returns to the game
        NktHook hook = _spyMgr.CreateHook("user32.dll!WindowFromPoint", (int)(eNktHookFlags.flgRestrictAutoHookToSameExecutable | eNktHookFlags.flgOnlyPostCall));
        hook.Hook(true);
        hook.Attach(processID, true);
        
        //Now send the button click and It works.
        int x = 9, y = 8;
        IntPtr lParam = (IntPtr)((y << 16) | x);
        WinAPIs.PostMessage((IntPtr)0x1D02D0, WinAPIs.WM_LBUTTONDOWN, (IntPtr)0x01, lParam);
        WinAPIs.PostMessage((IntPtr)0x1D02D0, WinAPIs.WM_LBUTTONUP, IntPtr.Zero, lParam);
    }

    private static void OnFunctionCalled(NktHook hook, NktProcess process, NktHookCallInfo hookCallInfo)
    {
        INktParam pRes = hookCallInfo.Result();

        //change the return value to whatever you want.. 0x1D02D0 here for example
        pRes.Value = new IntPtr(0x1D02D0);
    }
}

【讨论】:

    猜你喜欢
    • 2013-12-25
    • 1970-01-01
    • 2022-08-06
    • 2017-12-15
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多