TWinControl 控件之间关联的问题,如何感知对方的 handle 变化?(100分)

  • 主题发起人 主题发起人 940801
  • 开始时间 开始时间
9

940801

Unregistered / Unconfirmed
GUEST, unregistred user!
我有一个 MyComponent 组件,它有一个 OtherControl: TWinControl 属性,
这个 othercontrol 是独立于 MyComponent 的,不是由 mycomponent 创建的
程序运行过程中 OtherControl 的 handle 改变了,MyComponent 怎样才能知道这个变化呢?
请指点。万分感谢。
 
什么意思?handle是只读的呀。
 
wheel 兄可以简单的测试一下,Form.BorderStyle 变化前后的 handle 值是否一样
 
940801 兄:
我在 Borland Newsgroup 中看到你的提问了. :) 。记得以前看到过类似的问答。
一种方法大概可以 Hook 住 OtherControl 的 WindowProc ,截获 CM_RECREATEWND 消息。
但 Anders Melander (就是 Drap&Drip 的作者啦) 说上面的方法不太安全,他用一个比较
巧的办法是 MyComponent 创建一个内部的 TWinControl,另该 WinControl 的 Parent 为
OtherControl,则 OtherControl Handle 被 Destroy 或 Create 时该内部 WinControl
都会得到通知,MyControl 也就知道 OtherControl 的 Handle 变化了。转贴如下:
type
TWinControlProxy = class(TWinControl)
protected
procedure DestroyWnd; override;
procedure CreateWnd; override;
procedure CreateParams(var Params: TCreateParams); override;
end;

procedure TWinControlProxy.CreateParams(var Params: TCreateParams);
begin
inherited;
// Avoid that control draws itself in case it becomes visible (e.g. if a
// TToolBar is specified as target.
Params.ExStyle := Params.ExStyle or WS_EX_TRANSPARENT;
end;

procedure TWinControlProxy.CreateWnd;
begin
inherited CreateWnd;
OleCheck(RegisterDragDrop(Parent.Handle, TCustomDropTarget(Owner)));
Visible := False;
Width := 0;
end;

procedure TWinControlProxy.DestroyWnd;
begin
if (Parent.HandleAllocated) then
RevokeDragDrop(Parent.Handle);
// Control must be visible in order to guarantee that CreateWnd is called when
// parent control recreates window handle.
Visible := True;
inherited DestroyWnd;
end;


procedure TCustomDropTarget.DoRegister(ATarget: TWinControl);
begin
if (AutoRegister) then
begin
// Create a child control to monitor the target window handle.
// The child control will perform the drop target registration for us.
with TWinControlProxy.Create(Self) do
Parent := ATarget;
end else
OleCheck(RegisterDragDrop(ATarget.Handle, Self));
end;

procedure TCustomDropTarget.DoUnregister(ATarget: TWinControl);
var
i: integer;
begin
if (AutoRegister) then
begin
// Delete target proxy.
// The target proxy willl unregister the drop target for us when it is
// destroyed.
for i := ATarget.ControlCount-1 downto 0 do
if (ATarget.Controls is TWinControlProxy) and
(TWinControlProxy(ATarget.Controls).Owner = Self) then
with TWinControlProxy(ATarget.Controls) do
begin
Parent := nil;
Free;
break;
end;
end else
if (ATarget.HandleAllocated) then
// Ignore failed unregistrations - nothing to do about it anyway
RevokeDragDrop(ATarget.Handle);
end;


DIXI
+--------------------from usenet----------------------+
| Anders Bo Melander | mailto:anders@melander.dk |
| Denmark | http://www.melander.dk |
+------------------------+----------------------------+
其实都是看了你关于 IDataObject 的问题在 www.Tamarack.com 搜索到的,这些针对 Borland
News 的搜索引擎十分有用的。
 
妙,确实妙,

昨天我在 ATarget 的 CreateWnd, DestoryWnd 实现了 Register 和 Unregister,
但这样就没法自由的为 DropTarget 指定别的 WinControl 为 Target 了。

这个方法太巧妙了,太感谢了,多谢 bbkxjy 兄费心了
 
后退
顶部