WinForm自动化测试工具开发札记(3)

Win32到.NET API调用技巧
本文探讨了从Win32到.NET环境中API调用的方法,特别是如何处理Win32的数据类型和结构体。通过实例展示了如何获取鼠标所在窗口的信息,并分析了.NET平台下指针的使用技巧。
2006年03月24日 18:03:00

技术攻关
从今天开始准备P0中所需技术的Demo,有了Demo就知道原理了,正式开始写的时候就没那么头大了.

捕捉窗口的技术
目的:得到当前鼠标位置是哪个窗口.
以前学过一点点Win32,知道在Windows操作系统中,所有你见到的东西--无论是窗体还是控件,都是"窗口",是窗口,就会与一个WindowClass相关联.这个WindowClass,虽然有Class字样,但要注意,Win32编程用的是C语言,所以不是OO中的那个Class.
下班前,照着书写了一个小程序,把代码贴在下面,大家可以自己运行一下.运行的时候,把鼠标四处移动一下.这个程序会以每秒一次的速率捕捉当前鼠标所指的窗口,并将窗口的标题(如果有)输出到命令行.

//------水之真谛
//------http://blog.youkuaiyun.com/FantasiaX

using
System;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;

namespace RnP
{
[StructLayout(LayoutKind.Sequential)]
public struct Win32Point
{
public int x;
public int y;
}


class Program
{
[DllImport("user32.dll")]
private static extern bool GetCursorPos( ref Win32Point win32Point);

[DllImport("user32.dll")]
private static extern uint WindowFromPoint(Win32Point win32Point);

[DllImport("user32.dll")]
private static extern int GetWindowText(uint windowHandle, StringBuilder windowText, int maxChars);

static void Main (string[] args)
{
Win32Point p= new Win32Point();
while (true)
{
GetCursorPos(ref p);
uint u = WindowFromPoint(p);
StringBuilder sb = new StringBuilder(20);
GetWindowText(u, sb, 20);
Console.WriteLine(sb.ToString());
Thread.Sleep(1000);
}
}
}
}

技术分析
昨天说来着,最头疼的一件事情是如何对付那些Win32里的数据类型.这些类型除了简单类型外,有很多是结构体.在从Win32到.NET的转换中,要用到MarshalAs这个Attribute,今天还注意到了另一个Attribute,那就是 [StructLayout(LayoutKind.Sequential)],
不过查过MSDN才知道,这个Attribute加不加无所谓--这是默认值.
今天最大的收获在这句里:
[DllImport("user32.dll")]
private static extern bool GetCursorPos( ref Win32Point win32Point);


我们可以对照一下其Win32的原型:
BOOL GetCursorPos( LPPOINT lpPoint );

这个函数只接受一个参数,也就是LPPOINT,是一个指针类型.原来我想的是:指针吗,一个地址而已,转换成uint类型就行了.可后来想想,这是个于驴的智商相当想法,因为.NET平台(托管代码情况下,不考虑不安全代码)根本不支持指针,所以就算拿到这个以uint表达的指针也没用,因为你无法通过这个"指针"访问其代表的内存.呵呵,切身地开始怀念C语言了...自由与安全永远是冲突的.
遂,从书找到上面的代码,不过我稍微做了一点改动.通过使用 ref Win32Point win32Point 一个参数, .NET平台巧妙地避开(或者说是"跳过")了指针,直接把一个Win32Point类型的参数"灌"进一个变量中了.
是不是可以这样理解:
当从Win32向.NET转换API函数的时候,如果遇到[out]类型指针参数ptr_T时,就使用 ref T 作为参数.明天我可能试着在RECT类型上试验一下:p
刚才在调试的时候,发现这个问题:
Win32Point p= new Win32Point();

必需显式地赋值,也就是说去掉new Win32Point()是不行的.按理说是可以的.因为按照常识,
int x;

Int32 x = new Int32();
x=0;
是等效的.
不知道是不是.NET的Bug.

我又试了试改成这

[DllImport("user32.dll")]
private static extern bool GetCursorPos( out Win32Point win32Point);

也就是把ref 改成了out,就可以了.
当然,下面的代码也要改成
........
Win32Point p;//= new Win32Point();
........
GetCursorPos(out p);


哈哈,这下简单了:以后就记住-------- Win32的[out]参数,对应.NET的out参数就OK啦!
有所得,收工啦!!!
大家周末快乐撒!


法律声明:本文章受到知识产权法保护,任何单位或个人若需要转载此文,必需保证文章的完整性(未经作者许可的任何删节或改动将视为侵权行为)。请务必注明文章出处为优快云以保障网站的权益,请务必注明文章作者为刘铁猛并向bladey@tom.com发送邮件,标明文章位置及用途。转载时请将此法律声明一并转载,谢谢!



Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=637682


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值