这是一个有效的问题,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 状态,尽管我不确定我是否在这里缺少设置,或者它是否符合错误的条件.