使用Delphi绘制应用程序mainmenu

时间:2011-02-26 23:44:14

标签: delphi

  

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

您好,

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

任何提示都会有所帮助 - 我可以画一个按钮或面板,但没有菜单。

干杯

1 个答案:

答案 0 :(得分:2)

无法重新定位标准Windows菜单,Windows将其始终放在标题下。实际上,使用“iTunes”和“WS_CAPTION”的搜索会显示一些引用,表示iTunes窗口没有WS_CAPTION样式。对于'鸣鸟'我也会猜测同样如此。所以这些应用程序正在做的是删除标题以使菜单位于顶部并模拟具有标题(他们甚至可能没有标准菜单和他们自己的菜单实现,但我不知道这一点)。

您可以通过删除样式删除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调用可能无法成功。 F.i. 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;

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