Project1

标题: 求推荐Win32API的相关教程 [打印本页]

作者: 大葱有营养    时间: 2020-8-24 19:14
标题: 求推荐Win32API的相关教程
有一点ruby脚本基础,但是对Win32API相关一窍不通,看别人这方面脚本也看不懂,想从头开始学,苦于没有路子
查了下发现XP和VA区图书馆的Win32API教程都没了(晴兰大大的,好像相关帖子都没了,是不是出啥事了,不敢多问……)
看大家都说要看手册,不过光看手册感觉又多又杂不够清晰,不知道有没有相关教程资源可供自学,希望大大们能分享一下,不好意思这里伸手党了,希望海涵。
作者: KB.Driver    时间: 2020-8-24 20:54
本帖最后由 KB.Driver 于 2020-8-24 20:57 编辑

rgss自动加载了win32api,不考虑外置库的话,可以直接用这个。

常量 = Win32API.new(DLL名, 函数名, 参数数组, 返回值)

1、首先,你需要从dll里加载函数。
虽然我们也可以用外置的dll,但最常用的还是user32.dll

2、需要函数名,这个一般就需要查手册了,手册可以看这个、
http://www.yfvb.com/help/win32sdk/webhelpleft.htm
这个的好处是中文的,缺点就是不够新不够全。如果有版本要求请找英文的文档。
进去以后点“API参考”-“函数”然后找你需要的函数。

打个比方,在这里找到这样一个函数:

它的功能是返回当前正在被使用的窗口的句柄(hwnd)
句柄是一个long整数,用来唯一标识窗口

接下来我们怎么调用它?

3、参数数组
这个函数比较简单,从手册得知它的参数是void(无)
表示参数的类型时, L代表Long P代表Pointer I代表Int V代表Void (在实际使用的时候HResult和各种Handle都是Long,字符串是P)
那么我们就写'V',这里大写小写其实都没有关系
只有一个参数时一般用字符串就行,但是有多个参数时要用字符串数组比如["L", "P"]或者%W{ L P }

4、返回值
从手册已经得知返回的句柄是long,那么我们写'L'

5、测试
根据上面的分析,要载入这个函数,我们就这样写
RUBY 代码复制
  1. GetForegroundWindow = Win32API.new("user32.dll", "GetForegroundWindow", "V", "L")

之后要调用函数时,我们使用
函数名.call(参数)
这里我们可以用hwnd = GetForegroundWindow.call,因为不需要参数所以不用写括号,但要记得把返回值赋值给变量。

6、动手
那么获得了窗口的句柄有什么用呢?
我们可以修改窗口的标题,修改窗口的位置与显示状态(最大、最小化……)
下面就试着修改标题吧。

我们先找到文档:


接着载入函数:
RUBY 代码复制
  1. SetWindowText = Win32API.new("user32.dll", "SetWindowText", %W{ L P }, "I")

还记得吗?字符串体现为P,因为字符串是字符指针。而BOOL体现为I,因为C语言的逻辑变量是用1和0表示的。

下面就来试着修改游戏的标题吧:

RUBY 代码复制
  1. GetForegroundWindow = Win32API.new("user32.dll", "GetForegroundWindow", "V", "L")
  2. SetWindowText = Win32API.new("user32.dll", "SetWindowText", %W{ L P }, "I")
  3.  
  4. $hwnd = GetForegroundWindow.call
  5.  
  6. class << Graphics
  7.   alias cld99_update_win32api update
  8.   def update
  9.     @count ||= 0
  10.     @count += 1
  11.     SetWindowText.call($hwnd, "Time:"+ Time.now.to_s)
  12.     if @count > 10000
  13.       SceneManager.exit
  14.     end
  15.   end
  16. end


好像写的比较糟糕,因为我发现Graphics自身的update会重新把标题修改回去……晕

总之基础的是这些,还有调数据的会用到Cstruct,需要String#pack和Array.unpack,如果用到再学也可以。
这些都是网上有资料的,查ruby调win32api就有了。



作者: SixRC    时间: 2020-8-24 22:07
楼上写的好认真
补充一点点
Win32API.new(DLL名, 函数名, 参数数组, 返回值)   中
dll 后缀可省略
参数数组可以直接写成 "ll" 这样
有意义的参数类型只有 l p 因为RM是32位 i l n 都是32位整形 没有任何区别 同时 v 可以直接省略 或传 nil

对于不需要的返回值可以直接传 空字符串 / nil  因为不需要 例如返回bool 假如不去判断是否成功 就不需要这个结果 当然写别的也完全没问题 就是偷懒时候可以省略

有一点非常要注意的是
假如返回值是短型 short  那么必须手动把返回值的高16位截掉  因为RM的ruby版本 是不支持 s 的 只有 l  
决定数据类型的是处理它的方式
特殊情况下若保留多余的高16位 而你以为收到短整型 其实有多余信息 程序会崩

许多涉及字符串的win32api 都有两个版本 一个A ansi 一个W utf16le
SetWindowText 就是  没有指定 ruby默认用A版本
然后 ansi 在中文是 GB2312 RM是utf8  假如传中文就会乱码 需要先转码
作者: guoxiaomi    时间: 2020-8-25 21:17
本帖最后由 guoxiaomi 于 2020-8-25 21:33 编辑
SixRC 发表于 2020-8-24 22:07
楼上写的好认真
补充一点点
Win32API.new(DLL名, 函数名, 参数数组, 返回值)   中


尝试了一下传入 float / float* 和 double*,
  1. #define EXPORT __declspec(dllexport)

  2. EXPORT int fun1(float a)
  3. {
  4.     return a * a;
  5. }

  6. EXPORT int fun2(float *a)
  7. {
  8.     return (*a) * (*a);
  9. }

  10. EXPORT int fun3(double *a)
  11. {
  12.     return (*a) * (*a);
  13. }
复制代码

然后3个方法这样调用应该是没啥问题的……
  1. fun1 = Win32API.new("main.dll", "fun1", "i", "i")
  2. fun2 = Win32API.new("main.dll", "fun2", "p", "i")
  3. fun3 = Win32API.new("main.dll", "fun3", "p", "i")
  4. x = 2.5

  5. p fun1.call([x].pack("e").unpack("L")[0])
  6. p fun2.call([x].pack("e"))
  7. p fun3.call([x].pack("E"))
复制代码

返回值:666

返回float值好像出了问题……算了不管了

作者: SixRC    时间: 2020-8-25 23:15
本帖最后由 SixRC 于 2020-8-25 23:24 编辑
guoxiaomi 发表于 2020-8-25 21:17
尝试了一下传入 float / float* 和 double*,

然后3个方法这样调用应该是没啥问题的……


直接返回float值是不行啊
汇编有堆栈 通用寄存器 浮点数堆栈
32位默认情况下 调用函数时 参数入堆栈(包括浮点数) 返回时 一般把返回值放在寄存器 eax 中
而返回浮点数值 则是把返回值放在浮点数堆栈

所以假如写一个接口 返回值是 float  ruby端因为没考虑这个 只会取 eax 的值 而直接无视浮点数堆栈
所以要返回也很简单嘛 就是转换一下类型传回去 ruby端再转换一下
C 代码复制
  1. EXPORT int fun4(float *a)
  2. {
  3.     float t = (*a) * (*a);
  4.     return *(int *)&t;
  5. }

RUBY 代码复制
  1. fun4 = Win32API.new("a.dll", "fun4", "p", "i")
  2. x = 2.5
  3. s = fun4.call([x].pack("e"))
  4. p [s].pack("l").unpack("e")


不过直接传一个空字符串进去当输出缓存 或者直接输出到输入的内存里 会更方便吧





欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1