繁体   English   中英

Delphi - 更改菜单栏颜色

[英]Delphi - change the menu bar color

编辑:滚动到问题底部以查看已回答的工作代码。

我正在尝试更改表单上菜单栏的颜色。

我通过一些建议找到了这个网站:

https://www.experts-exchange.com/questions/20150240/Color-on-the-MainMenu.html

我将在下面粘贴代码本身。

不幸的是,它并不像我想要的那样工作。 缺点是:

  • 该颜色仅适用于菜单项,最后一个菜单项右侧的剩余空间为灰色。 我已将 Form 颜色设置为与菜单相同,但它不会改变这一点。

  • 每个菜单下拉菜单中的某些条目应该被禁用,如果我不应用着色代码,它们将被正确显示为禁用。 应用颜色更改会消除这种视觉效果,它们的颜色与菜单下拉菜单中的所有其他条目相同。

我的问题是:

  1. 是否有一个预先滚动的菜单对象可以让我轻松地为菜单栏着色,包括右侧的空白区域,并保留显示禁用等属性?

  2. 如果没有,有人可以指出我需要对可以解决上述问题的代码进行哪些额外更改的正确方向吗?

我是 Delphi 的新手(和编码,真的),但如果我能找到要查找的东西的名称,那么我可以谷歌并从那里获取它。

我正在使用 Delphi 10.3。

从上面的链接复制的代码:

type
  TForm1 = class(TForm)
    .....
    procedure FormCreate(Sender: TObject);
  public
    procedure DrawMenuItem(Sender: TObject; ACanvas: TCanvas;
      ARect: TRect; Selected: Boolean);
  end;

...

procedure TForm1.DrawMenuItem(Sender: TObject; ACanvas: TCanvas;
  ARect: TRect; Selected: Boolean);
var
  S: String;
begin
  with ACanvas do
  begin
    S := TMenuItem(Sender).Caption;
    if Selected then
      Brush.Color := clHighLight
    else
      Brush.Color := clLime;
    FillRect(ARect);
    DrawText(ACanvas.Handle, PChar(S), Length(S), ARect, DT_SINGLELINE or DT_VCENTER);
  end;

end;

procedure AllOnDrawTo(M: TMenuItem; P: TMenuDrawItemEvent);
var
  I: Integer;
begin
  M.OnDrawItem := P;
  for I := 0 to M.Count-1 do
    AllOnDrawTo(M.Items[I], P);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to MM.Items.Count -1 do
    AllOnDrawTo(MM.Items[I], DrawMenuItem);
end;

更新:@tom-brunberg 在评论中给了我所需的补充。 以下是实现我请求的两个项目的更新代码。 我保留了原始代码,因为我认为看到两个选项之间的对比很有趣。

type
  TForm1 = class(TForm)
    .....
    procedure FormCreate(Sender: TObject);
  public
    procedure AdvancedDrawMenuItem(Sender: TObject; ACanvas: TCanvas;
      ARect: TRect; State: TOwnerDrawState);
  end;

...

procedure TForm1.AdvancedDrawMenuItem(Sender: TObject; ACanvas: TCanvas;
  ARect: TRect; State: TOwnerDrawState);
var
  S: String;
begin
  with ACanvas do
  begin
    S := TMenuItem(Sender).Caption;
    // Set the highlight colour when the menu item is selected.  Grey highlight if disabled.
    if odSelected in State then
      if odDisabled in State then
        Brush.Color := clBtnFace
      else
        Brush.Color := clGradientActiveCaption
    else
      Brush.Color := clGradientInactiveCaption;
    // Set the colour of the menu item textm, grey if disabled
    if odDisabled in State then
      Font.Color := clGray
    else
      Font.Color := clBlack;

    // this line fill rest of the top of the form the same colour as the menu.  If its the LAST menu item fill rect all way to the right.  My example has 8 menu items
    if (Parent = nil) and (TMenuItem(Sender).MenuIndex = 8) and not (odSelected in State) then
      ARect.Right := Width;

    FillRect(ARect);
    DrawText(ACanvas.Handle, PChar(S), Length(S), ARect, DT_SINGLELINE or DT_VCENTER);
  end;

end;

procedure AdvancedAllOnDrawTo(M: TMenuItem; P: TAdvancedMenuDrawItemEvent);
var
  I: Integer;
begin
  M.OnAdvancedDrawItem := P;
  for I := 0 to M.Count-1 do
    AdvancedAllOnDrawTo(M.Items[I], P);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to MM.Items.Count -1 do
    AdvancedAllOnDrawTo(MM.Items[I], AdvancedDrawMenuItem);
end;

我没有给你一个完整的答案,但你确实说过你可以“从那里谷歌”。

您的代码仅将自定义绘图例程应用于菜单项。 如果您还想绘制菜单栏本身,则需要为此自定义绘制例程。 标准的 TMenu OwenerDraw 允许您接收菜单项的事件。 菜单确实有一个窗口句柄,这意味着您可以对其进行绘制,理想情况下您希望它阻止自己对您所做的任何更改进行过度绘制。 查看 TMenu 绘画的源代码(我没有时间这样做),看看您是否可以发现需要覆盖的内容来绘画它。

TMenu 将包装菜单的通用 Windows 处理,因此您可以了解 Windows 如何允许您绘制菜单,然后实现它。 (这是相当数量的谷歌搜索!)

至于启用/禁用反馈您可以在 on draw 事件中绘制任何您喜欢的东西。 如果您想在禁用 TMenuItem 时在视觉上显示不同的内容,请检查它是否已禁用,然后绘制您想要的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM