分享

消息的发送

 独孤求财 2012-03-20

消息的发送

时间:2011-5-26来源:yang 作者: peng点击: 4次

1。在应用程序内发送消息
调用perform(),sendmessage(),postmessage()函数,使消息常量的值为
WM USER+100~$7FFF

2。在应用程序之间发送消息
调用registerWindowMessage()函数,这个函数能够确保每个应用程序使用一致的消息序号。RegisterWindowMessage()需要传递一个以null结束的字符串,并返回一个范围从
$C000~$FFFFF的新的消息常量。在要发送消息的应用程序之间,每个应用程序都必须传递相同的字符串给RegisterWindowMessage(),而WINDOWS也会返回相同的消息常量,这可以确保给定的字符串返回整个系统中惟一的消息常量,这样就可以放心地向所有窗口发送消息。

3。广播消息
Twincontrol的派生对象可以调用broadcast()向它的子组件广播一个消息,当需要向一组组件发送相同的消息时,便可以使用这种技术。
还可以利用sendmessage,postmessage实现广播消息,此时只需要将hwnd参数设为HWND BROADCAST,它代表向所有的窗口发送消息。



2007-3-2 12:04:19    
 发表评语»»»    

 2007-7-7 13:48:03    ding

 
 2007-7-9 15:38:33    Perform()
V C L的P e r f o r m ( )方法适用于所有的T C o n t r o l派生对象。P e r f o r m ( )可以向任何一个窗体或控件发送
消息,只需要知道窗体或控件的实例。P e r f o r m ( )需要传递3个参数:消息标识符、w P a r a m和l P a r a m。
P e r f o r m ( )是这样声明的:
要给一个窗体或控件发送一个消息,可以参照下面的代码:
调用了P e r f o n n ( )后,它要等消息得到处理后才返回。P e r f o r m ( )把3个参数组装成T M e s s a g e记录,
然后调用D i s p a t c h ( )方法把消息传递给Wi n d o w s的消息系统。

sendMessage()和PostMessage()
有的时候,可能需要向一个窗口发送一个消息,而又不知道这个窗口的实例。例如,可能要给一
个非D e l p h i的窗口发送一个消息,而只有这个窗口的句柄。幸运的是, Wi n d o w s有两个A P I函数可以
实现这一点: S e n d M e s s a g e ( )和P o s t M e s s a g e ( )。这两个函数几乎是一样的,它们的区别是: S e n d M e -
s s a g e ( )直接把一个消息发送给窗口过程,等消息被处理后才返回。P o s t M e s s a g e ( )只是把消息发送到消
息队列,然后立即返回。
S e n d M e s s a g e ( )和P o s t M e s s a g e ( )是这样声明的:
hwnd是接收消息的窗口的句柄。
Msg是消息标识符。
wParam是3 2位的特定附加信息。
lParam是3 2位的特定附加信息。
注意尽管S e n d M e s s a g e ( )和P o s t M e s s a g e ( )调用方式完全一样,但它们的返回值不一样。
S e n d M e s s a g e ( )返回此消息被处理的结果值,而P o s t M e s s a g e ( )返回一个布尔值,表示消息是否已被放到消息队列中。

用户自定义的消息
有些情况下,一个应用程序可能需要向自己发送消息,或者在两个应用程序之间发送消息。这时
你会有这样一个问题:“为什么要发送消息而不是直接调用一个过程”。这个问题问得好,有这样几个
答案。首先,消息可以让你不需要知道接收者的确切类型。同时,消息可以有选择地处理。如果接收
者对消息没有做任何处理,不会造成任何后果。最后,消息可以广播给多个接收者,而要同时调用几
个过程则比较困难。
1. 在应用程序内发送消息
一个应用程序要发送消息给自己是很容易的,只要调用P e r f o r m ( )、S e n d M e s s a g e ( )或P o s t M e s s a g e ( ),
并且使消息常量的值为WM_USER + 100到$ 7 F F F (这个范围是Wi n d o w s为用户自定义消息保留的)
const
  SX_MYMESSAGE = WM_USER + 100;

BEGIN
  SOMEFORM.PERFORM(SX_MYMESSAGE, 0, 0);
//OR
SENDMESSAGE(SOMEFORM.HANDLE, SX_MYMESSAGE, 0, 0);
//OR
POSTMESSAGE(SOMEFORM.HANDLE, SX_MYMESSAGE, 0, 0);
.
.
.
然后声明和定义一个普通的消息处理过程来处理S X _ M Y M E S S A G E消息:
TFORM1=CLASS(TFORM)
.
.
.
PRIVATE
  PROCEDURE SXMYMESSAGE(VAR MSG: TMESSAGE); MESSAGE SX_MYMESSAGE;
END;

PROCEDURE TFORM1.SXMYMESSAGE(VAR MSG: TMESSAGE);
BEGIN
  SHOWMESSAGE(‘HELLO‘);
END;

正如你看到的那样,处理用户自定义的消息与处理标准的Wi n d o w s消息几乎没有什么不同。真正
的关键在于:必须声明一个消息常量,它的值必须从WM_USER + 100开始。最好为自定义的消息起
一个表明它的用途的名字。
注意除非应用程序已经建立了相应的消息处理过程,否则,不要发送自定义的消息。由于每
个窗口都可以独立地定义消息常量的值,因此,发送自定义消息具有潜在的危险,除非在接受
处理时非常地小心。

 
 2007-7-9 16:15:04    //在发送数据窗体中
var
  ds: TCopyDataStruct;
  hd: THandle;
  begin
    ds.cbData := Length(mmContent.Lines.Text) + 1;
    GetMem(ds.lpData, ds.cbData); //为传递的数据区分配内存
    StrCopy(ds.lpData, PChar(mmContent.Lines.Text));
    Hd := FindWindow(nil, ‘函数库‘); // 获得接受窗口的句柄
    if Hd <> 0 then
      SendMessage(Hd, WM_COPYDATA, Handle,
        Cardinal(@ds)); // 发送WM_COPYDATA消息
    FreeMem(ds.lpData); //释放资源
  end

 
 2007-7-9 16:23:23    //截取最小(大)化消息
 procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;

  procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
  begin
    if (Msg.CmdType = SC_MINIMIZE) or
       (Msg.CmdType = SC_MAXIMIZE) then
      MessageBeep(0);
    DefaultHandler(Msg);
  end;

 
 2007-9-28 17:20:09    WIN32应用程序进行交互的最简单的方法WIN32应用程序进行交互的最简单的方法

WM_COPYDATA消息

TcopyDataStruct结构类型指针
dwData 是一个32位的附加参数
cbData 表示要传递的数据区的大小
lpData 表示要传递的数据区的指针

SendData程序向GetData程序发送消息,并传递edit1中的字符串;GetData在收到消息后,把SendData发送的字符串接受下来,并显示在相应的edit1中

SendData程序:
……
var
  Form1: TForm1;
implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: Tobject);
var
  ds: TCopyDataStruct;
  hd: Thandle;
begin
  ds.cbData := Length (Edit1.Text) + 1;
  GetMem (ds.lpData, ds.cbData ); //为传递的数据区分配内存
  StrCopy (ds.lpData, Pchar (Edit1.Text));
  Hd := FindWindow (nil, ‘Form2‘); // 获得接受窗口的句柄
  if Hd <> 0 then
   SendMessage (Hd, WM_COPYDATA, Handle, Cardinal(@ds)) // 发送WM_COPYDATA消息
  else
    ShowMessage (‘目标窗口没找到!‘);
  FreeMem (ds.lpData); //释放资源
end;

StrCopy(Dest,Source :pChar):Pchar;
字符串拷贝。函数不进行长度检查,且目的区域的大小不小于length(source)+1个字符。如果希望进行长度检查,请使用strlcopy()函数。

GetData程序:
TForm2 = class(Tform)
  Edit1: Tedit;
private
  { Private declarations }
public
  { Public declarations }
  procedure Mymessage(var t:TWmCopyData);message WM_COPYDATA;
end;

var
  Form2: TForm2;

implementation

procedure TForm2.Mymessage(var t:TWmCopyData);
begin
  Edit1.text:=StrPas(t.CopyDataStruct^.lpData);//接受数据并显示。
end;

StrPas(Str:Pchar):String;
将以0结束(null结束)的字符串str转换成pascal格式的字符串。

 
 2007-9-30 14:44:14    全局原子Win32系统中,为了实现信息共享,系统维护了一张全局原子表。每个原子中存放了一些共享数据。关于对原子的操作,有一组专门的API函数
GlobalAddAtom 在表中增加全局原子
GlobalDeleteAtom 在表中删除全局原子
GlobalFindAtom 在表中搜索全局原子
GlobalGetAtomName 从表中获取全局原子

program Pvdde;
uses
  Forms,shellapi,Windows,dialogs,dde in ‘dde.pas‘ {Form1};

{$R *.RES}

begin
  if GlobalFindAtom(Pchar(‘PDDE_IS_RUNNING‘)) = 0 then  //避免二次启动
  begin
    K:=GlobalAddAtom(Pchar(‘PDDE_IS_RUNNING‘));
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
  end
  else
  begin
    //传递二次启动时的参数到第一个实例
    H := FindWindow(Pchar(‘TForm1‘), Pchar(‘资料保密 严禁外传‘));
    if ParamCount > 0 then
    begin
      L := GlobalAddAtom(Pchar(ParamStr(1)));
      if H<>0 then
      SendMessage(H, WM_MYMESSAGE, 0, L);
      { 传递原子句柄 }
      GlobalDeleteAtom(L); { 使用后释放 }
    end;
    Application.Terminate;
  end;
end;

end.

在相应的窗口单元dde.pas增加对自定义消息WM_MYMESSAGE的处理:
procedure TForm1.MyMessage(var T:Tmessage);
{对 WM_MYMESSAGE消息进行处理 }
var
  P: Array [0..255] of char;
begin
  GlobalGetAtomName(T.Lparam, P,255); { 接受数据到p数组中 }
  ...
end;

使用存储映象文件
 

这种方法相对较复杂一些。

当Win95与Winows Nt向内存中装载文件时,使用了特殊的全局内存区。在该区域内,应用程序的虚拟内存地址和文件中的相应位置一一对应。由于所有进程共享了一个用于存储映象文件的全局内存区域,因而当两个进程装载相同模块(应用程序或DLL文件)时,它们实际可以在内存‘">发现违禁文字,本页之后内容忽

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多