;---------------------------------------
; 调用Api函数的通用模板 v1.0 By FeiYue
;
; 使用方法:在类中添加各个Api的参数类型模板就可以简单调用了
;
; 参数类型模板规则:
; 模板的函数名区分大小写,简写类型的前面可以加u,后面可以加*
; 返回类型写在最前面接“=”符号,后面的参数类型个数必须准确
; 各参数类型用逗号隔开允许空格,Cdecl调用模式在返回类型前加C
;---------------------------------------
/* 比如调用这个WinAPI函数
int MessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
);
*/
; 类的原型对象调用的例子
Api.MessageBox(0, "调用1", "Tip", 0)
; 类的实例对象调用的例子
DLL:=new Api("User32.dll"), DLL.MessageBox(0, "调用2", "Tip", 0)
; 类里面的包装函数调用的例子
Api.msgbox("调用3"), (new Api()).msgbox("调用4")
;======== 下面是通用的类模板代码 ========
Class Api extends ApiBaseClass
{
;-- 如果AHK可以不写的DLL,就可以不用New对象而用Api原型对象来调用
__New(dll:="")
{
this.dll:=dll
if (dll) and !DllCall("GetModuleHandle", "Str",dll)
DllCall("LoadLibrary", "Str",dll)
}
;-- 为了方便调用,可以添加包装函数
msgbox(s:="OK", title:="Tip", flag:=0)
{
this.MessageBox(0, s, title, flag)
}
}
Class ApiBaseClass
{
__Call( func
;-- 前面10个参数允许由ByRef参数变量直接返回数值
, ByRef a1:="" , ByRef a2:=""
, ByRef a3:="" , ByRef a4:=""
, ByRef a5:="" , ByRef a6:=""
, ByRef a7:="" , ByRef a8:=""
, ByRef a9:="" , ByRef a10:="", arg* )
{
;-- 用于参数这些类型已经足够了,其他char、short只用于数据结构
;-- 对于输入的参数都可以不必加u前缀,对于输出的*类型要注意加u
static type:={ "":"Ptr"
, i:"Int", i64:"Int64", f:"Float", d:"Double"
, p:"Ptr", s:"Str", as:"AStr", ws:"WStr" }
;-- 在下面可以添加各个Api的参数类型模板,可以简写也可以全写
;-- 没有参数的不要写“=”符号只写返回类型,无返回值可不写返回类型
static typeinfo:={ "":""
, MessageBox : "i=p,s,s,i"
, MessageBoxA : "i=p,as,as,i"
, MessageBoxW : "i=p,ws,ws,i"
, "":"" }
;-- 将简写的类型转换为完整的AHK类型
t:=RegExReplace(typeinfo[func], "\s")
, t:=StrSplit(StrReplace(t, "=", ","), ",")
, C:=(InStr(t.1,"C") ? "Cdecl ":"")
, t.1:=RegExReplace(t.1, "i)C(decl)?")
Loop, % t.Count()
if (k:=type[Trim(v:=t[A_Index],"uU*")])
t[A_Index]:=(InStr(v,"u") ? "U":"") k (InStr(v,"*") ? "*":"")
C.=t.RemoveAt(1), r:=f:=""
;-- 调用时不区分大小写,但是模板的函数名区分大小写
For k,v in typeinfo
if (k=func) and (f:=(this.dll ? this.dll "\" k : k))
Break
;-- 10个以内的参数类型个数一定要准确
Switch ( Round(t.Count()) )
{
Case 0: r:=DllCall(f, C)
Case 1: r:=DllCall(f, t.1,a1, C)
Case 2: r:=DllCall(f, t.1,a1, t.2,a2, C)
Case 3: r:=DllCall(f, t.1,a1, t.2,a2, t.3,a3, C)
Case 4: r:=DllCall(f, t.1,a1, t.2,a2, t.3,a3, t.4,a4, C)
Case 5: r:=DllCall(f, t.1,a1, t.2,a2, t.3,a3, t.4,a4, t.5,a5, C)
Case 6: r:=DllCall(f, t.1,a1, t.2,a2, t.3,a3, t.4,a4, t.5,a5, t.6,a6, C)
Case 7: r:=DllCall(f, t.1,a1, t.2,a2, t.3,a3, t.4,a4, t.5,a5, t.6,a6, t.7,a7, C)
Case 8: r:=DllCall(f, t.1,a1, t.2,a2, t.3,a3, t.4,a4, t.5,a5, t.6,a6, t.7,a7, t.8,a8, C)
Case 9: r:=DllCall(f, t.1,a1, t.2,a2, t.3,a3, t.4,a4, t.5,a5, t.6,a6, t.7,a7, t.8,a8, t.9,a9, C)
Case 10: r:=DllCall(f, t.1,a1, t.2,a2, t.3,a3, t.4,a4, t.5,a5, t.6,a6, t.7,a7, t.8,a8, t.9,a9, t.10,a10, C)
;-- 超过10个参数的类型可以只写11个,后面默认用“Ptr”类型
Default:
v:=[]
Loop, % arg.Count()
v.Push((10+A_Index>t.Count() ? "Ptr":t[10+A_Index]), arg[A_Index])
v.Push(C)
r:=DllCall(f, t.1,a1, t.2,a2, t.3,a3, t.4,a4, t.5,a5, t.6,a6, t.7,a7, t.8,a8, t.9,a9, t.10,a10, v*)
}
return r
}
}
暂无讨论,说说你的看法吧