我对 delphi 不太熟悉,今天看了有关发送自定义消息的内容,有一个问题不明白,
大家帮我看看吧 !如果要发送一个自定义消息,可以这样做:1.定义消息常量
  const
    WM_MESSAGETEST = WM_USER + 100;2 在 Form1 的 public 中定义消息处理过程:
  procedure WM_MessageTest(var AMessage : TMessage); message WM_MYMSG;
  procedure TForm1.WM_MessageTest(var AMessage: TMessage); 
  begin
    ShowMessage('收到消息!');
    //这里继续做一个需要10秒种的事情
  end;3 在需要发送消息的地方:
  PostMessage(Form1.Handle, WM_MYMSG ,0, 0);问题:   要发送自定义消息,就必须知道窗口的句柄,既然知道了窗口的句柄,那么
就应该存在窗口实例的,我不通过发送消息也可以做到,比如这样:   
  Form1.WM_MessageTest;  
  我原来以为 PostMessage 发送了消息立刻返回,继续执行发送消息后的的代码,
  但是我做了一个测试,发现,必须等到消息处理过程执行完了之后才会执行发送消息代码 PostMessage(..) 后面的代码.我用 SendMessage(...) 测试也是这样。  procedure TForm1.Button1Click(Sender: TObject);
  begin
    PostMessage(Form1.Handle, WM_MYMSG ,0, 0);
    ShowMessage('测试'); //为什么到消息过程执行完成后才执行这里???
  end;  发送消息和直接调用方法有什么区别? 
  发送自定义消息有什么好处呢?

解决方案 »

  1.   

    一般来说, 在同一应用程序内, 直接调用比发送消息方便.而发送消息比直接调用灵活, 可以应用在窗体与窗体之间, 应用程序与应用程序之间进行信息参数的传递和控件.如调用Notepad的菜单, 关闭最前面的窗体等.自定义消息是为了更方便地传递自已的参数和与其它Windows消息区分开来.
      

  2.   

    谢谢大家的关注!Focus(老鱼):
    // 但如果发送消息的话,可以不必等返回结果
    // 直接运行发送消息这句下面的程序可是我做了一个测试,发现是等到消息处理过程执行完了才执行下一句的。
      procedure TForm1.Button1Click(Sender: TObject);
      begin
        PostMessage(Form1.Handle, WM_MYMSG ,0, 0);
        ShowMessage('测试'); //上面的消息过程执行完成后才执行???
      end;你可以试试看,发送完消息后并不会立即执行下面的ShowMessage('测试'); 
    而是执行完了消息处理过程后才执行的。
      

  3.   

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      tag:=1;
      s:='2222';
      postmessage(self.handle,wm_paint,0,0);
      showmessage(s);
    end;procedure TForm1.FormPaint(Sender: TObject);
    begin
      if tag=1 then
        begin
          s:='1111';
          tag:=0;
        end;
    end;
    请你试试这个过程
    结果是2222
      

  4.   

    louislingjjw(云 意) :
    这是因为ShowMessage实质调用了Application.HandleMessage
    HandleMessage先检查消息队列里有没有消息,有的话就执行
    所以限执行消息处理过程
    我试用MessageBox也是一样,估计也差不多
    这样就能看出差别了unit tt;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;const
        WM_MYMSG = WM_USER + 100;type
      TMainForm = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
        procedure WM_MessageTest(var AMessage : TMessage); message WM_MYMSG;
      public
        { Public declarations }
      end;var
      MainForm: TMainForm;implementation{$R *.dfm}procedure TMainForm.WM_MessageTest(var AMessage: TMessage);
    begin
     Memo1.Lines.Add('收到消息');end;procedure TMainForm.Button1Click(Sender: TObject);
    begin
      PostMessage(Handle, WM_MYMSG ,0, 0);
      Memo1.Lines.Add('单击');
    end;end.可以看到Memo1里出现的是
    单击
    收到消息
      

  5.   

    Focus(老鱼) :
      PostMessage()发送了消息后就返回,结果自然是 2222
      如果SendMessage()则是等消息处理完了再返回,那么结果就是 1111
      

  6.   

    wx1452():
       你是怎么知道“ShowMessage实质调用了Application.HandleMessage”?   之所以我上面会出现那种情况,是因为我上面的 Button1Click 
    我是在另一个线程中做的。
      

  7.   

    看源码阿procedure ShowMessage(const Msg: string);
    begin
      ShowMessagePos(Msg, -1, -1);
    end;procedure ShowMessagePos(const Msg: string; X, Y: Integer);
    begin
      MessageDlgPos(Msg, mtCustom, [mbOK], 0, X, Y);
    end;function MessageDlgPos(const Msg: string; DlgType: TMsgDlgType;
      Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer): Integer;
    begin
      Result := MessageDlgPosHelp(Msg, DlgType, Buttons, HelpCtx, X, Y, '');
    end;
    function MessageDlgPosHelp(const Msg: string; DlgType: TMsgDlgType;
      Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer;
      const HelpFileName: string): Integer;
    begin
      with CreateMessageDialog(Msg, DlgType, Buttons) do
        try
          HelpContext := HelpCtx;
          HelpFile := HelpFileName;
          if X >= 0 then Left := X;
          if Y >= 0 then Top := Y;
          if (Y < 0) and (X < 0) then Position := poScreenCenter;
          Result := ShowModal;
        finally
          Free;
        end;
    end;然后注意ShowModalfunction TCustomForm.ShowModal: Integer;
    var
      WindowList: Pointer;
      SaveFocusCount: Integer;
      SaveCursor: TCursor;
      SaveCount: Integer;
      ActiveWindow: HWnd;
    begin
      CancelDrag;
      if Visible or not Enabled or (fsModal in FFormState) or
        (FormStyle = fsMDIChild) then
        raise EInvalidOperation.Create(SCannotShowModal);
      if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
      ReleaseCapture;
      Include(FFormState, fsModal);
      ActiveWindow := GetActiveWindow;
      SaveFocusCount := FocusCount;
      Screen.FSaveFocusedList.Insert(0, Screen.FFocusedForm);
      Screen.FFocusedForm := Self;
      SaveCursor := Screen.Cursor;
      Screen.Cursor := crDefault;
      SaveCount := Screen.FCursorCount;
      WindowList := DisableTaskWindows(0);
      try
        Show;
        try
          SendMessage(Handle, CM_ACTIVATE, 0, 0);
          ModalResult := 0;
          repeat
            Application.HandleMessage;
            if Application.FTerminate then ModalResult := mrCancel else
              if ModalResult <> 0 then CloseModal;
          until ModalResult <> 0;
          Result := ModalResult;
          SendMessage(Handle, CM_DEACTIVATE, 0, 0);
          if GetActiveWindow <> Handle then ActiveWindow := 0;
        finally
          Hide;
        end;
      finally
        if Screen.FCursorCount = SaveCount then
          Screen.Cursor := SaveCursor
        else Screen.Cursor := crDefault;
        EnableTaskWindows(WindowList);
        if Screen.FSaveFocusedList.Count > 0 then
        begin
          Screen.FFocusedForm := Screen.FSaveFocusedList.First;
          Screen.FSaveFocusedList.Remove(Screen.FFocusedForm);
        end else Screen.FFocusedForm := nil;
        if ActiveWindow <> 0 then SetActiveWindow(ActiveWindow);
        FocusCount := SaveFocusCount;
        Exclude(FFormState, fsModal);
      end;
    end;然后Application.HandleMessage调用ProcessMessage
    function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
    var
      Handled: Boolean;
    begin
      Result := False;
      if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
      begin
        Result := True;
        if Msg.Message <> WM_QUIT then
        begin
          Handled := False;
          if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
          if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and
            not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
          begin
            TranslateMessage(Msg);
            DispatchMessage(Msg);
          end;
        end
        else
          FTerminate := True;
      end;
    end;
    就是这样,不知对不
      

  8.   

    可以加一TApplicationEvents,更能看出效果unit tt;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, AppEvnts, StdCtrls;const
        WM_MYMSG = WM_USER + 100;type
      TMainForm = class(TForm)
        Memo1: TMemo;
        Button1: TButton;
        ApplicationEvents1: TApplicationEvents;
        procedure Button1Click(Sender: TObject);
        procedure ApplicationEvents1Message(var Msg: tagMSG;
          var Handled: Boolean);
      private
        { Private declarations }
        procedure WM_MessageTest(var AMessage : TMessage); message WM_MYMSG;
      public
        { Public declarations }
      end;var
      MainForm: TMainForm;implementation{$R *.dfm}procedure TMainForm.Button1Click(Sender: TObject);
    begin
      PostMessage(Handle, WM_MYMSG ,0, 0);
      ShowMessage('单击消息');
      Memo1.Lines.Add('单击');
    end;procedure TMainForm.WM_MessageTest(var AMessage: TMessage);
    begin
      Memo1.Lines.Add('收到消息');
    end;procedure TMainForm.ApplicationEvents1Message(var Msg: tagMSG;
      var Handled: Boolean);
    begin
      if Msg.message = WM_MYMSG then
        Memo1.Lines.Add(IntToStr(WM_MYMSG)); 
    end;end.
      

  9.   

    自定义消息可以这样使用啊unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type  Twowmessage = record
          msg:cardinal;
          wowstr:string;
      end;  TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }  public
        { Public declarations }
      end; Tdog = class
       private
        procedure wow(var message:Twowmessage); message 100;
     end;
    var
      Form1: TForm1;implementationprocedure Tdog.wow(var message:Twowmessage);
    begin
    showmessage(message.wowstr);
    end;{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    var
      msg:Twowmessage;
    begin
      with Tdog.Create do
      try
       msg.msg:=100;
       msg.wowstr:='minjianq is here';
       dispatch(msg);
      finally
      free;
      end;end;
    end.
      

  10.   

    louislingjjw(云 意) :
    看关键的地方就可,其他没关的不用去看
    真正遇到问题的在去看
      

  11.   

    wx1452():
      其实,我是想做一个多线程的查询,里面就要用到发送消息,我也是刚刚学写的,我不知道怎么写那个那个 execute,才会最合理,因为从数据库服务器上取数据时,可能时间会很长,如果用单线程,查询时是无法点击界面的,如果查询时间超过了5秒钟,那几乎是很难忍受的,我测试了一下,从数据库上取数据和把查询到的数据显示在界面上最耗时间,你说怎么写那个 Execute方法比较合理?我查询主要要做 4 件事情:var
      ClientDataset1: TClientDataset; 
      List1: TList; //用来存放记录(先将记录转换为指针)1 OpenDataSet;   //ClientDataset1.open;
    2 GetOneRecord;  //将ClientDataset1中的一条记录(转为指针)存放到 List1 中。
    3 MoveDataSet;   //处理下一条 ClientDataset1.Next;
    4 DisPlayResult; //将查询结果显示在 ListView 上。
                     //ListView.OwnerData := True 处理 OnData() 事件来显示
      

  12.   

    louislingjjw(云 意):
    不好意思,没有弄过,不怎么懂
      

  13.   

    louislingjjw(云 意):
    呵呵,不用客气