这一段时间以来一直令我困惑,也许答案很简单,或者它可能涉及更多的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;
可以简单地称之为:
procedure TForm1.chkActiveClick(Sender: TObject);
begin
SetControlState(Button1, chkActive.Checked);
SetControlState(Button2, chkActive.Checked);
SetControlState(Edit1, chkActive.Checked);
end;
或者例如,表单上的所有控件:
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;
我注意到的两个问题是,虽然控件确实看起来像设计状态,但某些控件(如TButton)仍然会在其上绘制动画效果。另一个问题是当控件处于设计状态时按下左Alt键会导致它们消失。
所以我的问题是,我如何在运行时将控件置于设计状态模式,就像Delphi表单设计器那样,那些控件没有动画(基于Windows主题)并且无法获得焦点或输入?
为了使这一点更清晰,请根据以上代码示例查看此示例图像,其中控件不再处于活动状态,但TButton的动画颜色仍处于活动状态:
但实际应该是:
从上面的两张图片中,只能与TCheckBox控件进行交互。
是否有某个程序隐藏在可以改变控件状态的地方?或者也许更合适的方法来实现这一目标?到目前为止我设法得到的代码只会带来更多问题。
将控件设置为Enabled := False
也不是我要找的答案,是的,行为有点相同但当然控件的颜色不同以显示它们已被禁用,这不是我要找的
答案 0 :(得分:5)
您正在寻找的不是控件本身的功能,而是表单设计器本身的实现。在设计时,用户输入在被任何给定控件处理之前被截获。 VCL定义了一条CM_DESIGNHITTEST
消息,允许每个控件指定是否要在设计时接收用户输入(例如,允许视图调整列表/网格列标题的大小)。这是一个选择加入功能。
但是,您可以执行的操作是将所需的控件放在无边框TPanel
上,然后根据需要启用/禁用TPanel
。这将有效地启用/禁用其子控件的所有用户输入和动画。此外,当TPanel
被禁用时,子控件不会将自身呈现为禁用。
答案 1 :(得分:1)
Remy Lebeau关于将控件放入容器(如TPanel),然后将面板设置为Enabled := False
的答案确实将控件置于我正在寻找的状态。我还发现,覆盖控件WM_HITTEST
会将控件置于同一状态,例如,它们不会获得焦点而无法与之交互。这两个问题是控件仍然需要能够响应MouseDown
,MouseMove
和MouseUp
事件等,但它们不再能够响应。
Remy还建议编写一个类并实现Vcl.Forms.IDesignerHook
,这是我尚未尝试过的东西,因为它可能需要太多的工作来满足我的需求。
无论如何,经过大量的游戏后我发现了另一种替代方式,它涉及使用PaintTo
将控件绘制到画布上。我做的步骤如下:
TPanel
Canvas
FormCreate
创建自定义面板并将其与客户端对齐PaintTo
方法调用到自定义面板Canvas
这实际上是在创建组件并使用Form作为父级,我们的自定义面板位于顶部。然后将控件绘制到面板画布上,使其看起来好像控件位于面板上,实际上它位于未受干扰的表单下方。
由于控件位于面板下方,为了让他们响应MouseDown
,MouseMove
和MouseUp
等事件,我覆盖了面板中的WM_NCHitTest
并将结果设置为HTTRANSPARENT
。
在代码中它看起来像这样:
自定义面板:
type
TMyPanel = class(TPanel)
protected
procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHitTest;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Canvas;
end;
{ TMyPanel }
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Align := alClient;
BorderStyle := bsNone;
Caption := '';
end;
destructor TMyPanel.Destroy;
begin
inherited Destroy;
end;
procedure TMyPanel.WMNCHitTest(var Message: TWMNCHitTest);
begin
Message.Result := HTTRANSPARENT;
end;
<强> 形式: 强>
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FMyPanel: TMyPanel;
procedure ControlMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
public
{ Public declarations }
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
FMyPanel := TMyPanel.Create(nil);
FMyPanel.Parent := Form1;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FMyPanel.Free;
end;
procedure TForm1.ControlMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Sender is TWinControl then
begin
ShowMessage('You clicked: ' + TWinControl(Sender).Name);
end;
end;
将TButton添加到表单的示例:
procedure TForm1.Button1Click(Sender: TObject);
var
Button: TButton;
begin
Button := TButton.Create(Form1);
Button.Parent := Form1;
FMyPanel.BringToFront;
with Button do
begin
Caption := 'Button';
Left := 25;
Name := 'Button';
Top := 15;
OnMouseDown := ControlMouseDown;
PaintTo(FMyPanel.Canvas, Left, Top);
Invalidate;
end;
end;
如果您尝试运行上述内容,您会看到我们创建的TButton没有动画或获得焦点,但它可以响应我们在上面的代码中附加的MouseDown
个事件,因为我们实际上并不是这样看着控件,我们正在查看控件的图形副本。
答案 2 :(得分:0)
我不确定这是不是你想要的,但是Greatis有一个Form Designer组件。请参阅:http://www.greatis.com/delphicb/formdes/