2012-02-01 17 views
3

WM_COPYDATAによってアプリケーション間で文字列メッセージを送信するコンポーネントを作成しようとしています。 私はトラップWM_COPYDATAをたいと思いますが、これは動作しません:DelphiコンポーネントからWM_COPYDATAをキャッチ

TMyMessage = class(TComponent) 
private 
{ Private declarations } 
… 
protected 
{ Protected declarations } 
… 
procedure WMCopyData(var Msg : TMessage); message WM_COPYDATA; 
… 
end; 

Googleの多くの検索、WndProcメソッドを使用して、いくつかの参照を発見しました。私はそれを試しましたが、どちらもうまくいきません。

TMyMessage = class(TComponent) 
… 
protected 
{ Protected declarations } 
… 
procedure WMCopyData(var Msg : TMessage); message WM_COPYDATA; 
procedure WndProc(var Msg: TMessage); 
… 
end; 
… 
procedure TMyMessage.WndProc(var Msg: TMessage); 
begin 
    //inherited; 
    if Msg.Msg = WM_COPYDATA then 
    WMCopyData(Msg); 
end; 

助けてください、何が間違っていますか?

+0

メッセージの受信者のみがメインフォームすることができ(I guess) – opc0de

+0

@TLamaコンポーネントやコントロールにはメッセージループがありません。スレッドにはメッセージループがあります。 –

答えて

1

あなたの問題は、TComponentはウィンドウコンポーネントではありません。 WM_COPYDATAはウィンドウメッセージであり、ウィンドウプロシージャを介して配信されます。したがって、ウィンドウハンドルが必要です。これらのいずれかを取得するには、AllocateHwndを使用してください。

type 
    TMyComponent = class(TComponent) 
    private 
    FWindowHandle: HWND; 
    procedure WndProc(var Msg: TMessage); 
    public 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 
    end; 

constructor TMyComponent.Create(AOwner: TComponent); 
begin 
    inherited; 
    FWindowHandle := AllocateHwnd(WndProc); 
end; 

destructor TMyComponent.Destroy; 
begin 
    DeallocateHwnd(FWindowHandle); 
    inherited; 
end; 

procedure TMyComponent.WndProc(var Msg: TMessage); 
begin 
    if Msg.Msg=WM_COPYDATA then 
    //do domething 
    else 
    Msg.Result := DefWindowProc(FWindowHandle, Msg.Msg, Msg.WParam, Msg.LParam); 
end; 

メッセージを送信している間は、ウィンドウハンドルを取得する方法を見つける必要があります。

+0

私はウィンドウhadleを割り当てますが、それはWM_COPYDATAをトラップすることができますか、またはコンポーネントに直接メッセージを送信する必要がありますか? –

+0

私はその質問を理解していません。私の前提は、2つのプロセスが関わっているということです。それは事実ですか? –

+0

I * think *Gömeが私たちに言っていることは、このコンポーネントがそれが置かれていると仮定しているフォームのように、このコンポーネントが他のどこかで送られたメッセージを傍受することであるということです。しかし、その場合、wm_CopyDataハンドラを直接書くのではなく、コンポーネントユーザーがコンポーネントを使用する理由がわかりません。 –

3

これまでのことは問題ありませんが、最初にメッセージをコンポーネントに配信する必要があります。それにはウィンドウハンドルが必要です。 AllocateHWndに電話し、コンポーネントのWndProcメソッドを渡します。ウィンドウハンドルが返されます。これは、コンポーネントが破棄されたときに破棄する必要があります。

constructor TMyMessage.Create(AOwner: TComponent); 
begin 
    inhreited; 
    FHandle := AllocateHWnd(WndProc); 
end; 

destructor TMyMessage.Destroy; 
begin 
    DeallocateHWnd(FHandle); 
    inherited; 
end; 

直接ではなく、各メッセージのためのテスト、あなたはTObjectがあなたのためにそれをやらせることができます。これがDispatchメソッドの目的です。 TMessageレコードを渡し、対応するメッセージハンドラメソッドを見つけて呼び出します。そのようなハンドラがない場合は、代わりにDefaultHandlerを呼び出します。オーバーライドはDefWindowProcを呼び出すことができます。

procedure TMyMessage.WndProc(var Message); 
begin 
    Dispatch(Message); 
end; 

procedure TMyMessage.DefaultHandler(var Message); 
begin 
    TMessage(Message).Result := DefWindowProc(Self.Handle, TMessage(Message).Msg, 
    TMessage(Message).WParam, TMessage(Message).LParam); 
end; 
+0

すべてのコンポーネントが 'WM_COPYDATA'を探すのであれば' WndProc'を実装するのはなぜですか? –

+1

@David特別な理由はありません。私は質問に 'WndProc'を実装し、' WMCopyData'メソッドへの処理を延期していたので、メッセージIDを手動で確認する必要はありませんでした。メッセージが1つしかない場合は、最初に別々の 'WMCopyData'メソッドを書くのはあまり意味がないので、' Dispatch'メソッドと 'DefaultHandler'メソッドは役に立ちません。 –

1

私はそれをこのように行った:スレッドで実行されている

私のWebモジュールは、メインフォーム上のメモに文字列を送信する必要があります。

procedure TWebModuleWebServices.WebModuleCreate(Sender: TObject); 
begin 
    FReceiverFromWS := FindWindow(PChar('TFormWebServices'),PChar(cFormCaption + FormWebServices.Instance)); // Search by class name and caption of receiving form 
    // ==> you could to that without form caption, but I need to distinguish between running services 
    if FReceiverFromWS = 0 then 
     begin 
     Assert(False,'CopyData receiver NOT found!'); // Probably TFormWebServices not yet created 
     Exit; 
     end; 
end; 

メッセージ送信する: FReceiverFromWSは

で作成THandleメイン形態において

procedure TWebModuleWebServices.SendAMessage(Msg: String); 
// Windows will guarantee that the data sent in the COPYDATASTRUCT will exist until  after the WM_COPYDATA message 
// has been carried out. As such, we must use SendMessage() to send a WM_COPYDATA message. We cannot use PostMessage(). 
var 
    lCopyDataStruct: TCopyDataStruct; 
begin 
    lCopyDataStruct.dwData := 0; 
    lCopyDataStruct.cbData := 1 + Length(Msg); 
    lCopyDataStruct.lpData := PChar(Msg); 
    SendMessage(FReceiverFromWS, WM_COPYDATA, wParam(FReceiverFromWS), lParam(@lCopyDataStruct)); 
end; 

、パブリックメソッドを

手順WMCopyData(VARメッセージ:TWMCopyData)。メッセージWM_COPYDATA;

は次のとおりです。

procedure TFormWebServices.WMCopyData(var Msg: TWMCopyData); 
var 
    i : integer; 
    s : string; 
begin 
    i := Msg.CopyDataStruct.dwData; 
    case i of 
     0: begin // Message to display 
      s := String(PChar(Msg.CopyDataStruct.lpData)); 
      AddMemoLine(s); 
     end; 
     1: begin // Statistical data 
      s := String(PChar(Msg.CopyDataStruct.lpData)); 
      FrmWebServiceStats.CollectStats(s); 
     end; 
    end; 
end; 

(あなたが見ることができるように、私は実際にメッセージの種類を知らせると違っこれらを処理するためにdwDataを使用)

関連する問題