Delphi 无法在设计时单击自定义控件

Delphi 无法在设计时单击自定义控件,delphi,custom-controls,mouse,delphi-xe2,design-time,Delphi,Custom Controls,Mouse,Delphi Xe2,Design Time,我正在Delphi XE2中构建一个自定义控件(继承自TCustomControl),在设计时,我无法单击它们。我知道这与鼠标捕获有关,在设计时捕获鼠标事件并以与运行时不同的方式处理它们,但我不知道如何适当地适应这种情况。换句话说,在我能想到的许多解决方法中,我无法决定哪一种是正确的(或最有效的)方法 我相信这一定有一些非常简单的标准,很可能是使用ControlStyle或CreateParams但不知道是什么 在这个特定的控件中(我在本期中没有看到模式),我捕获的消息包括WM\u NCHITT

我正在Delphi XE2中构建一个自定义控件(继承自
TCustomControl
),在设计时,我无法单击它们。我知道这与鼠标捕获有关,在设计时捕获鼠标事件并以与运行时不同的方式处理它们,但我不知道如何适当地适应这种情况。换句话说,在我能想到的许多解决方法中,我无法决定哪一种是正确的(或最有效的)方法

我相信这一定有一些非常简单的标准,很可能是使用
ControlStyle
CreateParams
但不知道是什么

在这个特定的控件中(我在本期中没有看到模式),我捕获的消息包括
WM\u NCHITTEST
WM\u LBUTTONDOWN
。在设计时,控件100%处于活动状态,就像它是运行时一样,单击时,它将执行运行时代码

我感觉它就在我的命中测试消息处理程序中,下面是代码(有些东西被重命名):

以及我的控件的构造函数(已剥离):


但你当然是对的。您没有在
WM\u nchitest
处理程序中返回任何内容。当调用处理程序时,您的
Mmessage.Result
为“0”(HTNOWHERE),并且您没有为其分配任何其他内容

或者在某个时候调用<代码>继承< /代码>,或者实现您的逻辑并返回(设置消息。结果)<代码> HTCuths<代码>为您认为是控件内部的点。

如果这已经是运行时所需的行为,您可以包括设计时检查(但我想您应该出于某种原因进行所有计算):


在设计时支持鼠标交互的官方方式是对
CM_designhitest
消息响应非零结果。组件随后将接收正常的鼠标消息。

+1
csDesigning
完成了这个技巧-我知道这是类似的,但我是在
ControlState
而不是
ComponentState
中查找,这就是为什么我无法找到答案的原因。谢谢AFAICS CM_DESIGNHITTEST仅在控件返回HTCLIENT for WM_NCHITTEST时发送。顺便说一句,通过查看VCL源代码,我不太理解这是如何工作的,它也没有文档记录。我为测试控件返回了0,无法观察到任何不同的行为。您不需要处理
WM\u nchitest
,让默认处理程序为您管理。大多数控件不需要支持设计时交互,因此它们不响应
CM_designhitest
,但也有一些本机控件响应,例如那些允许可视化调整列大小而不使用对象检查器的控件。更具体地说,此控件实际上是一个水平(或垂直)项目列表或箭头。每个项目都被一个接一个地绘制为多边形,每个项目周围的空间被视为空白(背景)。当鼠标悬停在某个项目上时,我会突出显示该项目(并对该项目执行其他内部引用)。我还计划对单个列表项实施关注。
procedure TMyCustomControl.WMNCHitTest(var Message: TWMNCHitTest);
var
  P: TPoint;
  Poly: TPoints;
  X: Integer;
  I: TMyCollectionItem;
  Ch: Bool; //Need to improve invalidation
begin
  Ch:= False;
  P:= ScreenToClient(Point(Message.Pos.X, Message.Pos.Y));
  for X := 0 to Items.Count - 1 do begin
    I:= Items[X];
    Poly:= I.Points;
    FMouseIndex:= -1;
    FMouseState:= bmNone;
    if PointInPolygon(P, Poly) then begin //checks if point is within polygon
      FMouseIndex:= X;
      FMouseState:= bmHover;
      Ch:= True;
      Break;
    end;
  end;
  if Ch then Invalidate;
end;
constructor TMyCustomControl.Create(AOwner: TComponent);
begin
  inherited;
  ControlStyle:= ControlStyle - [csDesignInteractive];
end;
if csDesigning in ComponentState then
  Msg.Result := HTCLIENT;