永远庭

Domus Hominis Ludentis

0%

Mathematica 使用 Winapi 的一些注意事项

首先,使用之前别忘记Needs["NETLink\“];InstallNET[];`

DefineDLLFunction

本函数可以用来定义 DLL 中的函数到 Mathematica 中, 格式如下:

1
2
3
GetCursorPos = 
DefineDLLFunction["GetCursorPos", "user32.dll",
"BOOL", {"System.Drawing.Point&"}, ReferencedAssemblies -> {"System.Drawing"}]

{} 中为参数类型列表,用字符串表示,引用传值直接加上 outref 即可,如 {"ref IntPtr"}, 也可以如同上方例子,使用 &; 如果需要用到某些类,又不想 LoadNETAssemble[], 就可以直接使用 ReferencedAssemblies

一些常用 API

鼠标控制

鼠标事件:MouseEvent = DefineDLLFunction["mouse_event", "user32.dll", "int", {"int", "int", "int", "int", "int"}];
第一参数为键,后面4个参数一般直接为0即可。键值如下:

1
2
3
4
5
6
7
8
MOUSEEVENTF_MOVE:表明发生移动。
MOUSEEVENTF_LEFTDOWN:表明接按下鼠标左键。
MOUSEEVENTF_LEFTUP:表明松开鼠标左键。
MOUSEEVENTF_RIGHTDOWN:表明按下鼠标右键。
MOUSEEVENTF_RIGHTUP:表明松开鼠标右键。
MOUSEEVENTF_MIDDLEDOWN:表明按下鼠标中键。
MOUSEEVENTF_MIDDLEUP:表明松开鼠标中键。
MOUSEEVENTF_WHEEL:在Windows NT中如果鼠标有一个轮,表明鼠标轮被移动。移动的数量由dwData给出。

获取鼠标位置: SetCursorPos = DefineDLLFunction["SetCursorPos", "user32.dll", "int", {"int", "int"}];

窗口截图相关

用到的 Api 如下:

1
2
3
4
5
6
7
8
9
GetWindowRect = DefineDLLFunction["GetWindowRect", "user32.dll", "BOOL", {"HWND", "System.Drawing.Rectangle&"}, ReferencedAssemblies->{"System.Drawing"}];
FindWindow=DefineDLLFunction["FindWindow", "user32.dll", "HWND", {"String","String"}];
GetWindowDC=DefineDLLFunction["GetWindowDC", "user32.dll", "IntPtr", {"HWND"}];
CreateCompatibleBitmap=DefineDLLFunction["CreateCompatibleBitmap","gdi32.dll","IntPtr",{"IntPtr","int","int"}];
CreateCompatibleDC=DefineDLLFunction["CreateCompatibleDC","gdi32.dll","IntPtr",{"IntPtr"}];
SelectObject=DefineDLLFunction["SelectObject","gdi32.dll","IntPtr",{"IntPtr","IntPtr"}];
deleteObject=DefineDLLFunction["DeleteObject","gdi32.dll","int",{"IntPtr"}];
deleteDC=DefineDLLFunction["DeleteDC","gdi32.dll","int",{"IntPtr"}];
PrintWindow=DefineDLLFunction["PrintWindow","user32.dll","BOOL",{"IntPtr","IntPtr","UInt32"}];

实际操作过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SnapWindow[name_String:"Minesweeper Clone"]:=Block[
{handle,hscrdc,bptr,bdc,result},
handle=FindWindow[Null,name];
hscrdc=GetWindowDC[handle];
If[GetWindowRect[handle,rect]==1,,Return["Window Not Found!"];];
bptr=CreateCompatibleBitmap[hscrdc,rect@Width-rect@X,rect@Height-rect@Y];
bdc=CreateCompatibleDC[hscrdc];
SelectObject[bdc,bptr];
PrintWindow[handle,bdc,0];
result=Bitmap`FromHbitmap[bptr];
deleteDC[hscrdc];
deleteObject[bptr];
deleteDC[bdc];
Bitmap2Image@result
]

最后一步,需要将 Bitmap转化为 Mathematica 图片,函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    Bitmap2Image[bitmap_]:=Block[{img,width,height,lock,stride,intPtr,totalB,byte,data,},
LoadNETType/@{"System.Drawing.Imaging.ImageLockMode","System.Runtime.InteropServices.Marshal"};
img=result;
width=img[Width];
height=img[Height];
lock=img[LockBits[Rectangle`FromLTRB[0,0,width,height],ImageLockMode`ReadWrite,img[PixelFormat][Format24bppRgb]]];
stride=Abs[lock[Stride]];
intPtr=lock[Scan0];
totalB=stride*height;
byte=NETNew["System.Byte[]",totalB];
Marshal`Copy[intPtr,byte,0,totalB];
data=NETObjectToExpression[byte];
Marshal`Copy[byte,0,intPtr,totalB];
img[UnlockBits[lock]];
img=Image[Map[Reverse/@Partition[#,3]&,Partition[data,width*3,stride]],"Byte"]
];