如何将控件置于设计状态模式中,就像表单设计器一样?

Cra*_*aig 3 delphi delphi-xe7

这个问题已经困扰了我一段时间了,也许答案很简单,或者它可能涉及更多的VCL黑客或魔法来完成我正在寻找的东西,但无论哪种方式我都不知道如何解决我的问题问题.

如果您查看Delphi表单设计器,您将看到当鼠标移过它们时没有任何控件生成动画,它们也无法接收焦点或输入(例如,您无法键入TEdit,单击TCheckBox或移动TScrollBar等),仅在运行时,控件才能正常运行并响应用户交互.

我想知道如何在运行时对任何控件实现这种类型的行为,例如将控件设置为Designer State Mode?然而,控制也还是应该响应鼠标事件,如OnMouseDown,OnMouseMove,OnMouseUp等,使他们可以移动,如果需要,例如大小.

这是我管理的最接近的:

procedure SetControlState(Control: TWinControl; Active: Boolean);
begin
  SendMessage(Control.Handle, WM_SETREDRAW, Ord(Active), 0);
  InvalidateRect(Control.Handle, nil, True);
end;
Run Code Online (Sandbox Code Playgroud)

这可以简单地称为:

procedure TForm1.chkActiveClick(Sender: TObject);
begin
  SetControlState(Button1, chkActive.Checked);
  SetControlState(Button2, chkActive.Checked);
  SetControlState(Edit1, chkActive.Checked);
end;
Run Code Online (Sandbox Code Playgroud)

或者,例如,表单上的所有控件:

procedure TForm1.chkActiveClick(Sender: TObject);
var
  I: Integer;
  Ctrl: TWinControl;
begin
  for I := 0 to Form1.ControlCount -1 do
  begin
    if Form1.Controls[I] is TWinControl then
    begin
      Ctrl := TWinControl(Form1.Controls[I]);
      if (Ctrl <> nil) and not (Ctrl = chkActive) then
      begin
        SetControlState(Ctrl, chkActive.Checked);
      end;
    end;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

我在上面注意到的两个问题是,虽然控件确实看起来像设计状态,但某些控件(如TButton)仍然会在其上绘制动画效果.另一个问题是当控件设计状态时按下左Alt键会导致它们消失.

所以我的问题是,如何在运行时将控件置于设计状态模式,就像Delphi表单设计器那样,那些控件没有动画(基于Windows主题)并且无法获得焦点或输入?

为了使这一点更清晰,请根据以上代码示例查看此示例图像,其中控件不再处于活动状态,但TButton的动画绘制仍处于活动状态:

控件处于设计状态模式

但实际应该是:

控件处于设计状态模式

从上面的两个图像中,只能与TCheckBox控件进行交互.

是否存在可以改变控件状态的某个程序?或者也许更合适的方法来实现这一目标?到目前为止我设法获得的代码只会带来更多问题.

设置控件Enabled := False不是我正在寻找的答案,是的行为是一样的,但当然控件绘制不同,以显示它们被禁用,这不是我要找的.

Rem*_*eau 5

您正在寻找的不是控件本身的功能,而是表单设计器本身的实现.在设计时,用户输入在被任何给定控件处理之前被截获.VCL定义了一条CM_DESIGNHITTEST消息,允许每个控件指定是否要在设计时接收用户输入(例如,允许可视化调整列表/网格列标题的大小).这是一个选择加入功能.

但是,你可以做的是将所需的控件放到无边框上TPanel,然后TPanel根据需要简单地启用/禁用它自己.这将有效地启用/禁用其子控件的所有用户输入和动画.此外,TPanel禁用时,子控件不会将自身呈现为禁用.

  • 设计师不会"包装"每个控件.设计者将IDesignerHook接口的实现"附加"到设计的TCustomForm.在VCL内部,每个控件将通过拥有TCustomForm的IDesignerHook.IsDesignMsg()来传递每个Windows消息.如果该函数返回True,则消息已被设计者"处理".这包括鼠标和键盘消息. (4认同)