寻找Delphi高手(300分)

  • 主题发起人 主题发起人 坏蟑螂
  • 开始时间 开始时间

坏蟑螂

Unregistered / Unconfirmed
GUEST, unregistred user!
如何在线程中向一个继承自TComponet的类的对象发送消息?
我自己做了一个组件,继承自TTable,
如果在主线程中向它发消息倒好办,直接调用TMyTable.Dispach就行了。
而我希望在一个线程中向它发送消息,大家知道,Dispach会直接调用该对象的相应消息处理方法,
也就是说,实际上我在线程中直接地执行了该对象的消息处理方法,而这本该是主线程的事。
这就失去了我用消息传送代替方法调用的本意——隔离。
由于TTable是源于TComponet,而非TWinControl,所以是没有窗口的,
因此也不能用 SendMessage 和 PostMessage。
我应该使用什么方法呢?
 
还可以提高此问题的分数吗?
 
我也想知道
 
能不能这样:
首先想办法给TTable弄一个确定身份的标志(类似于Handle)
然后在线程中向窗体本身发特定的msg,在msg包含要操作的TTable的handle
然后在窗体的消息处理过程中操作该TTable
 
我也想知道
 
能不能这样:
线程向主窗体发消息(Handle, msg, Integer(Param), Integer(Obj))
然后主窗体根据WParam, LParam来确定Obj.Dispach(msg)
如:
PostMessage(Form1.Handle, WM_Msg, 1, Integer(Pointer(Table))
mainForm
if Msg.Msg = WM_Msg then
begin
Msg.Message := Some_Msg;
TComponent(Pointer(Msg.LParam)).Dispach(Msg);
end;

嘻。
end;
 
左轻侯,saoren 的做法应该都可行,也可以参考 TTimer 的代码,利用 AllocateHWnd 为你的
控件分配一个隐藏的窗口,然后就可以直接接收消息了。
 
将Mytable实例传入线程,在线程中调用MyTable.Dispach
 
你可以自己做一个Message 的Wrapper,该 Wrapper 可以接收消息,并处理此消息。
代码可以如下组织:
TMyMsgWRapper = class(TWinControl)
private
procedure MYWrapperMsg(var Messgae : TMessage);
message MYWrapperMsg;
..
end;

TMyThread = class(...)
private
procedure SendWMsg(msg,..);
protected
procedure Execute;
override;
...
end;

procedure TMyThread.Execute;
begin
...
SendWMsg(...);
...
end;

var
MyMsgWRapper : TMyMsgWRapper;
implementation
MyMsgWRapper := TMyMsgWRapper.Create(nil);
finalization
MyMsgWRapper.Free;
end;
 
How is the pointer!
 
Synchronize(...)
 
我是高手















才怪呢!
 
另:Msg: TMessage;为要发送的消息,为防止线程释放,最好在主窗口中定义。
否则线程释放后主线程才处理这消息会出错。
 
saoren的方法好,分给他吧,有多就给我一点。
我的方法思想跟他差不多,实现起来可能更好一点:
自定义消息:
WMU_TABLEDISP = WM_USER + 1;
PMessage = ^TMessage;

在主窗口中截获消息:
TFrMain = class(TForm)
private
...
procedure WmuTableDisp(var Msg: TMessage);
message WMU_TABLEDISP;
...
end;

...
procedure TFrMain.WmuTableDisp(var Message: TMessage);
var
VMsg: PMessage;
VTbl: TComponent;
begin
VTbl := TComponent(Pointer(Message.LParam));
VMsg := PMessage(Pointer(Message.WParam));
VTbl.Dispach(VMsg^);
end;

好处是不用判断每一条消息,DELPHI会帮我们勾上。
线程中使用:
procedure TMyThread.Execute;
var
Msg: TMessage;
begin
...
PostMessage(FrMain.Handle, WMU_TABLEDISP, Integer(Pointer(@Msg)), Integer(Pointer(Table))
...
end;

没有测试过,可能有错请包涵。
 
From delphi help:
*******************
When you use objects from the VCL object hierarchy, their properties and
methods are not guaranteed to be thread-safe. That is, accessing properties
or executing methods may perform some actions that use memory which is not
protected from the actions of other threads. Because of this, a main VCL
thread is set aside for access of VCL objects. This is the thread that
handles all Windows messages received by components in your application.
If all objects access their properties and execute their methods within
this single thread, you need not worry about your objects interfering with
each other. To use the main VCL thread, create a separate routine that
performs the required actions. Call this separate routine from within your
thread’s Synchronize method. For example:
procedureTMyThread.PushTheButton;
begin
Button1.Click;
end;
procedure TMyThread.Execute;
begin
...
Synchronize(PushTheButton);
...
end;

Synchronize waits for the main VCL thread to enter the message loop and
then
executes the passed method.
 
bbkxjy的说法正确,应该在继承于TTABLE的类里生成一个窗口,
SAOREN的方法可以,不过这样做封装性就很差劲了
最好不要让里面和外面在代码上产生关联
 
以下肯定行!!!
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TMyControl = class(TControl)
private
{ Private declarations }
FHandle:THandle;
protected
{ Protected declarations }
procedure WndProc(var Msg:TMessage);
public
{ Public declarations }
Constructor Create(Aowner:TComponent);override;
Destructor Destroy;override;
property Handle:THandle read FHandle;
published
{ Published declarations }
end;

procedure Register;

implementation
procedure Register;
begin

RegisterComponents('Samples', [TMyControl]);
end;

{ TMyControl }
constructor TMyControl.Create(Aowner: TComponent);
begin

inherited;
FHandle:=AllocateHwnd(WndProc);
end;

destructor TMyControl.Destroy;
begin

DeallocateHWnd(FHandle);
inherited;
end;

procedure TMyControl.WndProc(var Msg: TMessage);
begin

try
if Msg.Msg=wm_user+1 then

showmessage('ok')
else
msg.Result:= DefWindowProc(FHandle, Msg.msg, msg.wParam, msg.lParam);
except
Application.HandleException(Self);
end;

end;

end.

可以用postmessage(hwnd_broadcast,wm_user+1,0,0)发
 
翻翻旧帖子,为大富翁提速做点贡献!(政府都提速了,大富翁能不提速吗?)
 
不是高手,听听课总是行的吧!
踢~
 
楼上的介绍的很全面了,
拿去试一试
 
后退
顶部