我有一个TUpDown控件,其Associate设置为TEdit子类的实例。 edit类在其重写的DoEnter方法中调用RecreateWnd。不幸的是,这会破坏API级别的伙伴连接,从而导致奇怪的行为,例如点击向上箭头时。
我的问题是编辑实例不知道它应该重新连接到某个更新的伙伴,并且没有通知其伙伴丢失的更新。我有什么想法可以重新连接这两个?
答案 0 :(得分:2)
我注意到TCustomUpDown.SetAssociate如何检查updown和buddy是否具有相同的父级,并使用它来避免重复关联。所以我尝试调用自己的RecreateWnd方法:
procedure TAlignedEdit.RecreateWnd;
var
i: Integer;
c: TControl;
ud: TCustomUpDown;
begin
ud := nil;
for i := 0 to Pred(Parent.ControlCount) do
begin
c := Parent.Controls[i];
if c is TCustomUpDown then
if THACK_CustomUpDown(c).Associate = Self then
begin
ud := TCustomUpDown(c);
Break;
end;
end;
inherited RecreateWnd;
if Assigned(ud) then
begin
THACK_CustomUpDown(ud).Associate := nil;
THACK_CustomUpDown(ud).Associate := Self;
end;
end;
et voila - 它有效!
答案 1 :(得分:1)
你发现了一些相当不幸的事情。您在应用程序级别设置了两个控件之间的关联,因此应该能够继续在应用程序级代码中管理该关联,但VCL不提供维护该关联所需的框架。理想情况下,会有一个通用的关联框架,因此关联的控件可以相互通知他们应该自行更新。
VCL的开头是Notification
方法,但只通知被销毁的组件。
我认为您提出的解决方案对于该任务来说有点过于具体。编辑控件不一定知道它附加到一个上下控件,即使它是,它们也不应该被要求共享一个父控件。另一方面,为这个问题编写一个完整的通用观察框架将是过度的。我建议妥协。
从编辑控件上的新事件属性开始:
property OnRecreateWnd: TNotifyEvent read FOnRecreateWnd write FOnRecreateWnd;
然后如上所述覆盖RecreateWnd
,但不是所有特定于上下控制的代码,只需触发事件:
procedure TAlignedEdit.RecreateWnd;
begin
inherited;
if Assigned(OnRecreateWnd) then
OnRecreateWnd(Self);
end;
现在,在您的应用程序代码中处理该事件,您可以确切地知道哪些控件彼此关联,因此您不必搜索任何内容,也不需要任何父子关系:
procedure TUlrichForm.AlignedEdit1RecreateWnd(Sender: TObject);
begin
Assert(Sender = AlignedEdit1);
UpDown1.Associate := nil;
UpDown1.Associate := AlignedEdit1;
end;
答案 2 :(得分:0)
尝试在调用RecreateWnd之前将Associate属性的值存储在局部变量中,然后再将其设置回来。