API函数 postmessage 初探

来源:互联网 发布:网络销售成功案例 编辑:程序博客网 时间:2024/06/05 16:45
Postmessage函数

Fuction:

   该函数将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回,是异步消息模式。

Syntax:

 B00L PostMessage(

    HWND hWnd,

    UINT Msg,

    WPARAM wParam,

    LPARAM lParam); 

Parameters:

         hWnd:其窗口程序接收消息的窗口的句柄。

   Msg:指定被寄送的消息类型。

 wParam:指定附加的消息特定的信息。

  IParam:指定附加的消息特定的信息。

Return value :

  如果函数调用成功,返回非零值:如果函数调用失败,返回值是零。

 

以上是此函数的用法,在读此文章前最好看下异步函数调用 以便文章的理解。

一般而言,如果我们想对某一窗口进行文本投递(发送字符串)或者进行一些外部操作(模拟按钮、鼠标点击)且不考虑返回结果的话,postmessage函数就是一个好的选择。下面分别从发送字符,发送字符串和模拟鼠标点击来进行分析:

一、发送字符

 

 procedure SendChar(); var   h:HWND;   S:char; begin   S := 'd';   postmessage(h,WM_CHAR,ord(S),0); end;

发送字符d到指定窗口。

 

 二、发送字符串

 procedure Send(); var   mess:string; begin   mess:='Hello World!';   postmessage(WinHandle,WM_CHAR,Integer(PChar(Mess)),0);   //Do Something end;

这里,我们发送了字符串起始地址的值到指定句柄中,一般这样就可以了,但是有时你会发现当字符串长度很大时会出现字符串信息不全或者不对,如果发送的汉字的话甚至会出现乱码的情况,这又是什么原因呢?

下面是接收的代码:

 procedure Recieve(Var ms:TMessage); var   mess:string; begin   mess:=PChar(ms.WParam); end;

这时候就可以获得接收到的字符串。

 分析:出现这种现象主要是由于postmessage是异步消息模式造成的,它只负责把消息投递到指定窗体就立刻返回,而不管这个消息有没有被窗体处理掉。 仔细查看Send函数,你会发现postmessage执行完后,该过程就结束,那么这个局部变量mess就会被回收,它所占用的内存空间里面的值可能会被其他数据占用,从而导致在Revcieve的时候,接收到的值可能不正确,接收到的消息地址存放的内容可能不是原来的字符串了。

 如:Hello World!*&**

 那么,如何才能避免这种情况?

     首先,我们应该手动申请一段内存空间,在堆上申请的内存需要自己手动释放。

     我们使用New方法来申请内存,使用Dispose来释放申请的内存。

     然后将程序改动一下! 

  procedure Send();  var    mess:string;    ps:PString;  begin    New(ps)    mess:='Hello World!';    ps^:=mess;    postmessage(WinHandle,WM_CHAR,Integer(ps),0);  end;

   再来看接收端: 
 procedure Recieve(Var ms:TMessage); var   mess:string;   PS:PString; begin   PS:=PString(Mess.WParam);   mess:=PS^;   //Do Something   Dispose(PS); end;

 这样,就不会造成由于内存空间释放而产生乱码了!其实还有个方法,就是在mess定义的时候把它定义为全局变量,这样mess不会被系统所释放直到应用程序结束。另外一个比较有技巧的方法就是从发生字符的方法衍生过来的,可以采用循环的把字符串的字符一个个发送出去以达到发送字符串的效果,这也是后来才想到的,方法代码如下:
 
  procedure SendString();  var    h:HWND;    s:string;    i:integer;  begin    s := 'This is a string' ;    for i:=1 to length(s) do    Postmessage(h,WM_CHAR,ord(s[i]),0);  end;
、发送鼠标消息 
 procedure ClickCtl(h:HWND); var   pos:integer; begin   pos := X + Y * 65536;  //点击的坐标   postmessage(h,WM_MOUSEMOVE,2,pos);   //移动鼠标   postmessage(h,WM_LBUTTONDOWN,1,pos); //左键按下   postmessage(h,WM_LBUTTONUP ,0,pos);  ///左键释放 end;

上面的代码产生鼠标左键单击的效果,这里简单的说下这里postmessage函数第三个参数,这里表示的是功能键的状态, 2:移动 1:按下 0:释放,如果要去不是很高的话一般填写0就可以了。第四个参数是鼠标相对于窗体所在的坐标位置,是一个无符号的32位数,如果不需要点击的很精确的话,此参数可设置为0。其他的按键消息参数如下,改下第2个参数就可以了:
 

 WM_LBUTTONDBLCLK = &H203   //左键双击

 WM_LBUTTONDOWN = &H201    //左键按下

 WM_LBUTTONUP = &H202         //左键松开

 WM_MBUTTONDBLCLK = &H209   //双击鼠标中键
 WM_MBUTTONDOWN = &H207  
 WM_MBUTTONUP = &H208
 WM_RBUTTONDBLCLK = &H206   //双击右键
 WM_RBUTTONDOWN = &H204
 WM_RBUTTONUP = &H205