前段时间在捣鼓RPG Maker XP,学习一下里边的Win32API函数
这个函数可以在RMXP的引擎中调用dll中的函数,不仅可以调用系统dll(如user32.dll),也可以调用我们自己写的dll
Win32API.new("dll名", "导出函数名", '参数', '返回值')
在参数与返回值中,可以使用:
V(void),无;I(integer),整型;L(long),长整型;P(pointer),指针类型
但值得注意的是,由于RMXP是32位的,integer和long都是32位,没有区别,并且RMXP只能读取32位的dll,对于64位dll会Runtime Error
如果具有多个参数的情况下,只需要按顺序在字符串填入即可,比如:
Win32API.new("name.dll", "funcname", 'III', 'P')
‘III’表示需要调用的这个导出函数的参数是3个整型,返回值是指针类型
此外,由于其没有向我们提供float的参数,如果需要传入float,需要做一个转换
//test1.cpp
#include <windows.h>
extern "C" __declspec(dllexport) int func1(float *a) {
float b = *a + 1.5;
return *(int*)&b;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) {
return TRUE;
}
# Ruby
a = 2.1
b = [a].pack("e")
f = Win32API.new('test1.dll','func1','P','I')
c = f.call(b)
d = [c].pack("l").unpack("e")
p d[0]
得到输出:3.59999990463257
上面代码的原理是首先将2.1打包为一个二进制字符串数据(这里的“e“表示格式为float),然后将打包后的字符串传入函数,字符串是指针类型所以使用”P“进行传参,在dll层中将其强制解析为一个int后返回,刚才提到了RMXP没有float,所以我们需要通过int进行中转,使用这种方式不会影响原数据的二进制
返回到Ruby层后,由于返回的是一个int,所以需要先按照int类型pack成一个二进制字符串数据,随后直接将这个二进制数据解析成float,比较麻烦
一点小实际应用
下面的内容可能需要一点逆向芝士?制作RMXP游戏的动态标题效果
我们可以去查文档去找到我们所需功能的函数,可以使用http://www.yfvb.com/help/win32sdk/webhelpleft.htm
我们可以搜索到

可以看到参数需要窗口句柄和修改的标题字符串,我们再去搜索获取窗口句柄的函数

我们可以在Graphics.update里循环调用我们的修改标题的函数,具体如下:
$GetForegroundWindow = Win32API.new("user32.dll", "GetForegroundWindow", "V", "L")
$SetWindowText = Win32API.new("user32.dll", "SetWindowText", "IP" , "I")
$hwnd = $GetForegroundWindow.call
class << Graphics
alias ex4r26li0_update_20260319 update
def update
ex4r26li0_update_20260319
$SetWindowText.call($hwnd, Time.now.to_s)
end
end
但是我们运行发现,程序会把标题再改回去,这里我们需要对RGSS103J.dll进行修改
RGSS103J.dll加了壳,脱一下后找到Import的函数直接搜索上面的修改标题的函数

NOP掉相关语句


这时我们发现标题已经不会被修改回去了

肥肠号
妃常皓