我正在尝试编写一个组件,以便通过WM_COPYDATA在应用程序之间发送字符串消息。 我想陷阱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 :(得分: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;
答案 1 :(得分:1)
您的问题是TComponent
不是窗口组件。 WM_COPYDATA
是一条Windows消息,通过窗口过程传递。因此你需要一个窗口把手。使用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;
无论发送消息是什么,都需要找到一种方法来掌握窗口句柄。
答案 2 :(得分:1)
我是这样做的:
我在线程中运行的Web模块需要将字符串发送到主窗体上的备忘录。 FReceiverFromWS是一个THandle
在创建时:
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;
发送讯息:
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 Msg: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来表示消息的类型并以不同的方式处理它们)