在重新创建关联时保持UpDown-Associate连接

时间:2009-09-01 11:30:31

标签: delphi controls updown recreate

我有一个TUpDown控件,其Associate设置为TEdit子类的实例。 edit类在其重写的DoEnter方法中调用RecreateWnd。不幸的是,这会破坏API级别的伙伴连接,从而导致奇怪的行为,例如点击向上箭头时。

我的问题是编辑实例不知道它应该重新连接到某个更新的伙伴,并且没有通知其伙伴丢失的更新。我有什么想法可以重新连接这两个?

3 个答案:

答案 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属性的值存储在局部变量中,然后再将其设置回来。