【干货】如何开发一款游戏修改器?18:MFC DLL动态链接库

文摘   游戏   2025-01-11 00:00   广西  
本期我们要深入研究并测试的是MFC的动态链接库。MFC的动态链接库是可以带有窗口的。我们要添加一个新的项目,选择MFC,并选择MFC的动态链接库。实际上,MFC的动态链接库与上期教程介绍的win32动态链接库具有相似的特性。
// MFC208.cpp : 定义 DLL 应用程序的导出函数。//
#include "stdafx.h"#include "MFC208.h"#include <afxwin.h>
#ifdef _DEBUG#define new DEBUG_NEW#endif

// 此 DLL 的构造函数CMFC208App::CMFC208App(){    // TODO: 在此处添加构造代码,    // 将所有重要的初始化放置在 InitInstance 中}

// 唯一的一个 CMFC208App 对象CMFC208App theApp;

// CMFC208App 初始化BOOL CMFC208App::InitInstance(){    CWinApp::InitInstance();
    return TRUE;}
// 打开窗口函数void CMFC208App::OpenWindow(){    // 创建一个新的CDialog窗口    CDialog dlg(IDD_DIALOG1);    dlg.DoModal(); // 显示对话框}
// MFC208.h : MFC208 DLL 的主头文件
#pragma once
#ifndef __AFXWIN_H__    #error "在包含之前包含 'stdafx.h' 之前包含 'pch.h'"#endif
#include "resource.h"       // 主符号

// CMFC208App// 有关此类实现的信息,请参阅 MFC208.cpp//
class CMFC208App : public CWinApp{public:    CMFC208App();
// 重写public:    virtual BOOL InitInstance();
    // 打开窗口函数声明    void OpenWindow();
    DECLARE_MESSAGE_MAP()};
extern CMFC208App theApp;
在上面的代码中,我们对MFC的动态链接库进行了初始化,添加了一个窗口资源并关联了一个类。通过OpenWindow函数,可以打开该窗口。
生成好动态链接库后,我们要开始考虑如何显示这个窗口了。这个窗口不仅可以显示,还可以添加一些按钮、控件等,以后我们会教大家如何使用这些控件,比如可以在窗口上显示背包物品等等。
在关联好类之后,我们需要实例化这个对象,也就是说,我们通过关联的类名来定义一个变量,然后调用这个变量的成员函数来显示窗口。实例化对象其实就是定义一个变量名,然后通过这个变量名来调用成员函数来实现显示窗口的功能。这个过程看起来可能有些专业术语,但其实非常简单。
在需要显示窗口的地方,我们需要先包含头文件,也就是我们刚才创建的头文件。这个包含可以直接或间接,放在哪里都可以。然后,在使用这个类之前,我们需要先包含这个头文件,然后定义一个变量名,通过这个变量名来调用成员函数来显示窗口。
一般来说,我们可以在 MFC 动态链接库的初始化函数中显示窗口。需要注意的是,显示窗口的方式一般是模态的,也就是说,它会阻塞主线程的执行。如果要使用非模态方式,就需要将窗口挂在主线程上,但在我们当前的情况下,这个条件并不成立。
我们可以使用模态的方式来显示窗口。模态的方式会自动创建一个消息循环,而不依赖主线程的消息循环,也能够成功显示窗口。如果你要挂在主线程里面的话,不要用 ShowWindow,而是要用 DoModal 才能够显示成为模态窗口。
接下来我们要测试一下这个动态链接库。我们可以将它注入到游戏里面,或者在控制台里调用一下。你也可以将这个名字改成 "MFC20",然后设置为启动项。需要注意的是,在注入到游戏里面时,如果不是在新的线程里面创建,很可能会卡住游戏窗口。我们需要为其准备一个独立的线程来避免这个问题。
要解决这种问题,我们需要创建一个独立的线程。首先,我们可以写一个新的函数,然后将这个代码放到新的线程里面执行。在这个新的线程中,我们需要加上 AFX_MANAGE_STATE 宏,以确保窗口资源可以被正确找到。然后,我们可以调用这个函数,这样就不会阻塞游戏的主线程了。
要正确调用这个函数,我们需要使用 AfxBeginThread 函数来创建一个新的线程。创建线程的回调函数并不重要,只需要填写正确的参数即可。
由于参数过多,我们只需知道第三个参数,因此填写显示窗口函数即可。你可以将其命名为ABC,也可以是其他名称。函数格式是固定的,第一个参数是 DWORD,第二个参数是 HINSTANCE,一般我们用宏 WPI 来表示。这实际上就是之前在讲汇编时的内屏障。在这个函数里,我们可以直接调用汇编代码。
创建好后,我们可以将其载入窗口,但窗口将在一个独立的线程中运行,而不是主线程。这样,如果我们再次注入游戏,游戏窗口就不会被卡住。同时,我们的代码注入器也不会被卡住了。
接下来,我们可以在测试代码中直接写汇编代码。比如,如果我们想测试登录游戏并使用物品,我们可以将代码写在这里。需要注意的是,有时候这行代码可能会出现 bug,所以最好先测试一下。最后,我们可以进入游戏进行测试。需要注意的是,只有在动态链接库中注入代码后,我们才能像上面那样写。如果没有在目标进程空间中,这样写是无效的。
那么本期教程就先到这里,下期我们再深入。


暮色的狐
这是一只高强度上网冲浪、高质量输出内容的狐狸。主打ACGN杂谈、技术干货分享、第九艺术鉴赏、网梗百科解析、情感树洞鸡汤、正能量价值观~
 最新文章