Windows下的鼠标经常会显示出不同的样子以提示当前的操作,所以对于很多程序来说截取鼠标指针当前的图片并进行分析是很有用处的,下面分析两种截取鼠标指针的图片的方法并给出一个示范程序。
截取鼠标指针的图片首先要取得鼠标的句柄,然后用API函数DrawIconEx将其绘制在画布上,注意在Windows下鼠标指针(Cursor)和图标(Icon)是没有区别的,利用DrawIconEx的第七个参数istepIfAniCur可以将动态光标的不同帧绘制在画布上,具体的应用可以查看MSDN。
取得鼠标的句柄的第一种方法是利用API函数GetCursorInfo,很奇怪在MSDN6.0中查不到这个函数, 无论鼠标是否停留在本进程的窗口上,利用这个函数都可以取得鼠标的信息,示范代码如下:
//方案1
function Fun1: HCURSOR;
var
hCur : TCursorInfo;
begin
ZeroMemory(@hCur,sizeof(hCur));
hCur.cbSize:=SizeOf(hCur);
GetCursorInfo(hCur);
result:=hCur.hCursor;
end;
function Fun1: HCURSOR;
var
hCur : TCursorInfo;
begin
ZeroMemory(@hCur,sizeof(hCur));
hCur.cbSize:=SizeOf(hCur);
GetCursorInfo(hCur);
result:=hCur.hCursor;
end;
取得鼠标的句柄的第二种方法是利用API函数GetCursor,一般情况下,只有当鼠标停留在本进程的窗口上,这个函数才返回正确的鼠标句柄,否则只返回默认的鼠标句柄,也就是小箭的样子,不过可以利用API函数AttachThreadInput将两个进程进行输入绑定,这样当鼠标停留在其它进程的窗口上,就或以返回正确的鼠标句柄,示范代码如下:
//方案2
function Fun2: HCURSOR;
var
wid : HWND;
tid : DWORD;
begin
wid:=GetForegroundWindow; //获取最前面的窗口
tid:=GetWindowThreadProcessId(wid,nil); //获取窗口所在的进程
AttachThreadInput(GetCurrentThreadId,tid,true);
result:=GetCursor;
AttachThreadInput(GetCurrentThreadId,tid,false);
end;
function Fun2: HCURSOR;
var
wid : HWND;
tid : DWORD;
begin
wid:=GetForegroundWindow; //获取最前面的窗口
tid:=GetWindowThreadProcessId(wid,nil); //获取窗口所在的进程
AttachThreadInput(GetCurrentThreadId,tid,true);
result:=GetCursor;
AttachThreadInput(GetCurrentThreadId,tid,false);
end;
显然第一种方法要优于第二种方法。获得鼠标句柄后的绘制就简单了,绘制后的分析属于图片分析技术这里就不讨论了。我做的示范程序如下: