【问题标题】:drawing applications mainmenu using Delphi [duplicate]使用Delphi绘制应用程序主菜单[重复]
【发布时间】:2011-02-26 23:44:13
【问题描述】:

可能重复:
Owner Drawing TMainMenu over Aero Glass Form?

嗨,

我有兴趣在应用程序的标题栏上绘制应用程序的主菜单吗?有点像 iTunes 和 Songbird (Windows 7)。

任何提示都会有所帮助 - 我可以绘制按钮或面板,但不能绘制菜单。

干杯

【问题讨论】:

  • iTunes 不在玻璃中绘制其主菜单,即使它在非客户区顶部绘制其菜单也是如此。如果您只想在非客户区绘制菜单,请从问题标题中删除 glass 一词,这样它就不会因为重复而关闭。据我所知,Songbird 也不支持玻璃。
  • 投票重新打开,因为显然提到 glass 是一个无意的错误,已根据 Warren 的评论进行了纠正,事实上,我不太明白其他问题。

标签: delphi


【解决方案1】:

无法重新定位标准的 Windows 菜单,Windows 总是将它放在标题的正下方。实际上,使用“iTunes”和“WS_CAPTION”进行搜索会显示一些参考资料,指出 iTunes 窗口没有WS_CAPTION 样式。我猜“Songbird”也是如此。因此,这些应用程序所做的就是删除标题以使菜单位于顶部并模拟标题(它们甚至可能没有标准菜单和自己的菜单实现,但我不知道)。

您可以通过删除样式来删除 Delphi 表单的标题:

  SetWindowLong(Handle, GWL_STYLE,
      GetWindowLong(Handle, GWL_STYLE) and not WS_CAPTION);
  SetWindowPos(Handle, 0, 0, 0, 0, 0,
      SWP_NOSIZE or SWP_NOMOVE or SWP_NOZORDER or SWP_FRAMECHANGED);

然后菜单将出现在顶部(没有标题)。然后,您将在窗口顶部伪造鼠标点击,使其位于标题上,以便能够使用鼠标在窗口中移动。您可以通过处理WM_NCHITTEST 消息来实现这一点。但是你必须排除菜单项占据的区域;

type
  TForm1 = class(TForm)
    [...]
  private
    procedure WmNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
  public

[...]

procedure TForm1.WmNCHitTest(var Msg: TWMNCHitTest);
var
  Pt: TPoint;
  MenuBarInfo: TMenuBarInfo;
  i, MenuWidth: Integer;
begin
  inherited;

  // calculate the total width of top menu items
  MenuBarInfo.cbSize := SizeOf(MenuBarInfo);
  MenuWidth := 0;
  for i := 0 to MainMenu1.Items.Count - 1 do begin
    GetMenuBarInfo(Handle, OBJID_MENU, 1, MenuBarInfo);
    MenuWidth := MenuWidth + MenuBarInfo.rcBar.Right - MenuBarInfo.rcBar.Left;
  end;

  Pt := ScreenToClient(SmallPointToPoint(Msg.Pos));
  Pt.Y := Pt.Y + MenuBarInfo.rcBar.Bottom - MenuBarInfo.rcBar.Top;
  if (Pt.Y <= GetSystemMetrics(SM_CYCAPTION)) and (Pt.Y >= 0) and
      (Pt.X > MenuWidth) and (Pt.X < ClientWidth) then
    Msg.Result := HTCAPTION;
end;

根据您使用的 Delphi 版本,您可能无法成功调用 GetMenuBarInfo。菲D2007 错误地声明了TMenuBarInfo 结构打包。所以你可能需要在调用函数之前重新声明它和函数。

type
  TMenuBarInfo = record
    cbSize: DWORD;
    rcBar: TRect;
    hMenu: HMENU;
    hwndMenu: HWND;
    fBarFocused: Byte;
    fFocused: Byte;
  end;

function GetMenuBarInfo(hend: HWND; idObject, idItem: ULONG;
  var pmbi: TMenuBarInfo): BOOL; stdcall; external user32;

最后,您可能会在最右侧放置一些按钮,以便用户能够最小化、恢复等.. 窗口。

【讨论】:

  • 酷。我会进行实验,看看这是否符合我的要求!
  • 它可以工作 - 只要我知道如何更换控制按钮。
  • @Mmarquee - 如果控制按钮是指最小化、关闭等,您可以根据光标的位置再次返回相关的命中测试。至于外观,您可以根据是否按下鼠标按钮绘制适当的图像...提示:您可以随时提出问题。 :)
猜你喜欢
  • 2021-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-20
  • 2011-09-22
相关资源
最近更新 更多