【问题标题】:ActionMainMenuBar with 32x32 icon带有 32x32 图标的 ActionMainMenuBar
【发布时间】:2013-07-04 13:59:10
【问题描述】:

德尔福 Xe4。表单、ActionManager、ImageList(带有 32x32 图标)、ActionMainMenuBar。

我无法确保图标显示正确。你该怎么办?

同时,如果我应用任何 vcl 风格的装饰,它显示得很好。但如果默认为“Windows”样式,则文字会移出图标。帮助。

抱歉英语不好。

【问题讨论】:

  • 你的图标太大了。您需要使用大小等于GetSystemMetrics(SM_CXSMICON) 的方形图标
  • 在 TMainMenu 中可以使用 32x32 的图标。然后你不能?
  • 我无法理解。
  • 表格。主菜单。图像列表(32x32)。工作正常。 s1.ipicture.ru/uploads/20130705/zbxq3aHT.jpg 和“如果我应用任何 vcl 风格的装饰,它显示得很好”
  • 标准我不需要。然后 32x32 也适用于该标准。再次。在 TMainMenu 中,它们看起来很正常。正常显示和应用样式。并且通常不需要绘制。

标签: delphi action-menu


【解决方案1】:

这是一个有效的问题,TActionMainMenuBar 旨在能够将自定义图标大小作为菜单图像处理,就像本机菜单可以很好地处理它们一样。可以在代码中的 cmets 中找到一个迹象,f.i.在下面的 VCL 代码中,您可以找到注释 16 is standard image size so adjust for larger images

我相信错误代码在“ActnMenus.pas”中的TCustomMenuItem.CalcBounds 中。以下摘录来自 D2007。请注意下面我用一些感叹号评论的行。上层类TCustomActionControl在其CalcLayout方法中计算出文本和图像的位置后,TCustomMenuItem用上述语句中的硬编码24破坏了它。

procedure TCustomMenuItem.CalcBounds;
var
  AWidth, AHeight: Integer;
  NewTextBounds: TRect;
  ImageSize: TPoint;
  ImageOffset: Integer;
begin
  inherited CalcBounds;
  ImageSize := GetImageSize;
  AHeight := FCYMenu;
  if Separator then
    AHeight := FCYMenu div 3 * 2
  else
    // 16 is standard image size so adjust for larger images
    if ImageSize.Y > 16 then
      AHeight := ImageSize.Y + 4;
  if ActionClient = nil then exit;
  if ImageSize.X <= 16 then
    ImageOffset := 24
  else
    ImageOffset := ImageSize.X + 6;  // Leave room for an image frame
  NewTextBounds := TextBounds;
  OffsetRect(NewTextBounds, 24 - TextBounds.Left,          // <- !!!!!
    AHeight div 2 - TextBounds.Bottom div 2 - 1);
  TextBounds := NewTextBounds;
  ShortCutBounds := Rect(0,0,0,0);
  if ActionClient.ShortCut <> 0 then
  begin
    Windows.DrawText(Canvas.Handle, PChar(ActionClient.ShortCutText), -1,
      FShortCutBounds, DT_CALCRECT);
    // Left offset is determined when the item is painted to make it right justified
    FShortCutBounds.Top := TextBounds.Top;
    FShortCutBounds.Bottom := TextBounds.Bottom;
    AWidth := TextBounds.Right + FShortCutBounds.Right + ImageOffset + Spacing;
  end
  else
    AWidth := TextBounds.Right + TextBounds.Left;
  SetBounds(Left, Top, AWidth, AHeight);
end;


24 是基于具有 16 或更少像素宽度的图像的假设。应该改用上面几行计算的ImageOffset 值。替换

  OffsetRect(NewTextBounds, 24 - TextBounds.Left,
    AHeight div 2 - TextBounds.Bottom div 2 - 1);

  OffsetRect(NewTextBounds, ImageOffset - TextBounds.Left,
    AHeight div 2 - TextBounds.Bottom div 2 - 1);

你会得到这样的东西:

不过,您会注意到其他一些奇怪的地方,没有图像的项目仍会采用小图像布局。 IMO 所有菜单项应具有相同的基本布局,但操作菜单的设计允许各个项目的不同布局。另一件奇怪的事情是带有图像('Action6')的项目的 checked 状态,尽管我不确定我是否在这里缺少设置,或者它是否符合错误的条件.

【讨论】:

  • +1。不错的收获。 :-) XE2 和 XE4 中存在相同的硬编码值。
  • 嗯——还在西雅图的 Delphi 10 中。呜呜呜?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
  • 1970-01-01
  • 1970-01-01
  • 2014-04-09
  • 1970-01-01
  • 2012-08-25
相关资源
最近更新 更多