delphi - 如何防止设计时与注册为组件的 TFrame 交互

标签 delphi

我创建了一个新框架,我想将其注册为组件。我已经从 this question 了解了 RegisterSprigType ,所以它省去了我一些麻烦。

RegisterSprigType 可以正确防止设计者选择、意外移动或删除框架内的控件,但仅限直接选择。里面的控件仍然接受要删除的控件。

就我而言,我的框架内有面板。我可以在所述面板上放置一个按钮。如果我删除该按钮,则会选择父级(恰好是面板),然后我可以删除该面板。

我尝试从框架的 ControlStyle 中删除 csAcceptsControls。它确实阻止了控件直接落在框架上,但内部面板仍然接受控件。

因此,我最终在“加载”过程中从框架中包含的所有控件中删除了 csAcceptsControls。

如果我的框架动态创建控件以响应属性更改,我想我还需要重写通知过程以从任何添加的控件中剥离 csAcceptsControls。

所以,我的问题是,是否有更好的方法来实现相同的结果(防止设计者在注册为组件的框架内添加控件)。一个“寄存器”告诉设计者忽略框架类及其子类作为容器?

如果这个方法已经是最优的,我是否错过了什么?

这种方法有什么我应该注意的“陷阱”吗? (有副作用吗?设计和运行时都有。)

最佳答案

我深入研究了,但没有很好的解决你的问题 因为所有方法都在框架上下文中工作,而不是在其子组件中工作 像 DesignWndProc、WM_NCHITTEST ...

但我有解决方案(不太好),请看下面,但我不知道它是否比您删除 csAcceptsControls 的解决方案更好。

您可以在设计时仅创建Panel(透明)并仅从中删除csAcceptsControls。在调整框架大小时,您可以设置此面板的宽度和高度以吃掉整个框架。 但是您必须将所有控件放在某个顶级面板(父级是 Frame)中并对齐 alClient,并且每个控件都将位于其上。 然后,您创 build 计时间面板(父级是框架),它将成为框架上的第二个顶级面板。 创建后您只能将其置于前面一次。 此删除需要更改创建新控件的每个属性。

类似这样的结构 Frame{PanelTopLevel{任何其他控件}}{DesignPanel}:

object FrameTestDisableFrame: TFrameTestDisableFrame
  object PanelTopLevel: TPanel
    object Panel1: TPanel
      Left = 96
      Top = 56
      Width = 201
      Height = 105
      Caption = 'Panel1'
      TabOrder = 0
      object Button1: TButton
        Left = 48
        Top = 24
        Width = 75
        Height = 25
        Caption = 'Button1'
        TabOrder = 0
      end
    end
end

设计面板代码

TDesignPanel = class(TWinControl)
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
  public
    constructor Create(AOwner: TComponent); override;
  end;

实现

{ TDesignPanel }

constructor TDesignPanel.Create(AOwner: TComponent);
begin
  inherited;
  ControlStyle:= ControlStyle - [csAcceptsControls];
  Color:= clBackground;
end;

procedure TDesignPanel.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle:= Params.ExStyle or WS_EX_TRANSPARENT;
end;

procedure TDesignPanel.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
  Message.Result:= 1;
end;

在你的框架中

private
    DesignPanel: TDesignPanel;

...

constructor TFrameTestDisableFrame.Create(AOwner: TComponent);
begin
  inherited;
  ControlStyle:= ControlStyle - [csAcceptsControls];
  if csDesigning in ComponentState then
    begin
      DesignPanel:= TDesignPanel.Create(Self);
      DesignPanel.Parent:= Self;
      DesignPanel.BringToFront;
    end;
end;



procedure TFrameTestDisableFrame.Resize;
begin
  inherited;
  DesignPanel.BringToFront;
  DesignPanel.SetBounds(0, 0, Width, Height);
end;

我测试了这个并且工作正常

提示

In my situation, I have panels inside my frame. I can drop a button on said panel. If I delete the button, then the parent get selected (which happen to be the panel) and then I can delete the panel.

在delphi西雅图,当我删除此类按钮时,整个框架被选择而不是父面板。

关于delphi - 如何防止设计时与注册为组件的 TFrame 交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30601073/

相关文章:

delphi - 如何从枚举填充内存表?

delphi - 使用 Generics.Collections.TObjectDictionary 的示例

Delphi - 显示所有图像格式

delphi dbgrid 绘制单元格图像黑色背景

delphi - 在 DataModule 上使用函数

delphi - VirtualStringTree 过滤正确完成

delphi - 如何在Delphi中发出HTTPS POST请求?

使用 Indy HTTP 的 Delphi Google oauth2 token 请求得到 400 错误请求

delphi - 在哪里可以获得 Excel 式多项式回归曲线拟合的 Delphi/Pascal 实现?

Delphi:将 TByte 转换为 AnsiString 中相应的十六进制值