Windows 在运行时确定弹出提示消息(THintInfo::HintStr)的大小

Windows 在运行时确定弹出提示消息(THintInfo::HintStr)的大小,windows,delphi,delphi-7,Windows,Delphi,Delphi 7,我们有一个启用了ShowHint的TListView。在OnInfo提示处理程序中,将构造一条特定于鼠标悬停的项目的提示消息。消息可以包括换行1310个字符 已创建覆盖以处理CM_HINTSHOW消息,将要显示的提示消息可在msg.HintInfo.HintStr中看到。可以在运行时计算大小,但这似乎有风险,因为实现细节可能很复杂或依赖于平台 是否可以查询THintInfo的“边框”,或者是否有其他方法来确定显示时弹出提示消息的大小 这是必需的,因此可以设置提示msg.HintInfo.Hint

我们有一个启用了ShowHint的TListView。在OnInfo提示处理程序中,将构造一条特定于鼠标悬停的项目的提示消息。消息可以包括换行1310个字符

已创建覆盖以处理CM_HINTSHOW消息,将要显示的提示消息可在msg.HintInfo.HintStr中看到。可以在运行时计算大小,但这似乎有风险,因为实现细节可能很复杂或依赖于平台

是否可以查询THintInfo的“边框”,或者是否有其他方法来确定显示时弹出提示消息的大小

这是必需的,因此可以设置提示msg.HintInfo.HintPos的准确位置。

THintWindow具有可用于此情况的功能CalcHintRect。VCL在显示HintWindow时将使用此功能:

  with HintInfo do
    HintWinRect := FHintWindow.CalcHintRect(HintMaxWidth, HintStr, HintData);
由于FHintWindow在TApplication之外不可访问,因此需要创建一个临时实例

procedure TMyListView.CMHintShow(var Message: TCMHintShow);
var
  AHintWindow: THintWindow;
  AHintWinRect: TRect;
  ...
begin
  AHintWindow := Message.HintInfo.HintWindowClass.Create(nil);
  try
    AHintWinRect := AHintWindow.CalcHintRect(...);
    ...
  finally
    AHintWindow.Free;
  end;
end;
这是否正确取决于THintWindowClass的实现。但是,如果人们不能依赖它,辛特温道将显示错误

一个潜在的陷阱可能是在中东地区,当比迪莫德是从右到左。然后,还将执行以下操作:

  if FHintWindow.UseRightToLeftAlignment then
    with HintWinRect do
    begin
      Delta := MultiLineWidth(HintInfo.HintStr) + 5;
      Dec(Left, Delta);
      Dec(Right, Delta);
    end;
THintWindow具有可用于此情况的CalcHintRect功能。VCL在显示HintWindow时将使用此功能:

  with HintInfo do
    HintWinRect := FHintWindow.CalcHintRect(HintMaxWidth, HintStr, HintData);
由于FHintWindow在TApplication之外不可访问,因此需要创建一个临时实例

procedure TMyListView.CMHintShow(var Message: TCMHintShow);
var
  AHintWindow: THintWindow;
  AHintWinRect: TRect;
  ...
begin
  AHintWindow := Message.HintInfo.HintWindowClass.Create(nil);
  try
    AHintWinRect := AHintWindow.CalcHintRect(...);
    ...
  finally
    AHintWindow.Free;
  end;
end;
这是否正确取决于THintWindowClass的实现。但是,如果人们不能依赖它,辛特温道将显示错误

一个潜在的陷阱可能是在中东地区,当比迪莫德是从右到左。然后,还将执行以下操作:

  if FHintWindow.UseRightToLeftAlignment then
    with HintWinRect do
    begin
      Delta := MultiLineWidth(HintInfo.HintStr) + 5;
      Dec(Left, Delta);
      Dec(Right, Delta);
    end;

可能重复是的,问题是相关的,好点!虽然我不反对这个问题被关闭,但他们从稍微不同的角度来看待这个问题。我更喜欢这里给出的答案,它与这个具体问题更密切相关。但框架应该为您考虑这一点。您需要在CM_HINTSHOW消息处理程序中设置HintPos。或者我错过了什么…@kobik:我确实按照你的建议设置了HintPos,但是由于消息文本是动态的,我无法知道要使用的确切位置。如果位于TListView客户端区域的左上角,则HintPos:=Self.ClientToScreenPoint1,1;就足够了…但是如果你想要右下角,比如说,那么你需要知道弹出框的尺寸,以计算从父TListView控件边缘的正确偏移量。可能重复的是,问题是相关的,很好!虽然我不反对这个问题被关闭,但他们从稍微不同的角度来看待这个问题。我更喜欢这里给出的答案,它与这个具体问题更密切相关。但框架应该为您考虑这一点。您需要在CM_HINTSHOW消息处理程序中设置HintPos。或者我错过了什么…@kobik:我确实按照你的建议设置了HintPos,但是由于消息文本是动态的,我无法知道要使用的确切位置。如果位于TListView客户端区域的左上角,则HintPos:=Self.ClientToScreenPoint1,1;就足够了…但是如果您想要右下角,比如说,那么您需要知道弹出框的尺寸,以计算与父TListView控件边缘的正确偏移量。我动态创建了一个THintWindow,名为myHintWnd.CalcHintRect。。。。很好用。哦,说得好。我没有意识到没有属性可以访问FHintWindow,所以肯定需要创建临时窗口。@AlainD,我不知道你想解决什么问题,但我认为你做得不对。你创建THintWindow只是为了获得提示窗口的尺寸?如果必须从THintWindow.CalcHintRect获取实现,则它只使用带有DT_CALCRECT的DrawText。不过,我还是觉得你走错了路。@kobik:我有一个触摸屏应用程序,鼠标光标被隐藏,弹出提示框有时会妨碍列表中选定的项目。我试图将弹出消息塞进父TListView的一个角落,以便显示数据,但不会模糊所选项目或上面和下面的项目。nil的回答很有技巧,尽管你可能是对的,它不是最优雅的。我在飞行中创建了一个THintWindow,名为myHintWnd.CalcHintRect。。。。很好用。哦,说得好。我没有意识到没有属性可以访问FHintWindow,所以肯定需要创建临时窗口。@AlainD,我不知道你想解决什么问题,但我认为你做得不对。你创建THintWindow只是为了获得提示窗口的尺寸?如果必须从THintWindow.CalcHintRect wher获取实现
它只是使用带有DT_CALCRECT的DrawText。不过,我还是觉得你走错了路。@kobik:我有一个触摸屏应用程序,鼠标光标被隐藏,弹出提示框有时会妨碍列表中选定的项目。我试图将弹出消息塞进父TListView的一个角落,以便显示数据,但不会模糊所选项目或上面和下面的项目。尼尔的回答很有技巧,尽管你可能是对的,它不是最优雅的。