无法重新定位标准的 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;
最后,您可能会在最右侧放置一些按钮,以便用户能够最小化、恢复等.. 窗口。