drawing applications mainmenu using Delphi [duplicate]
Possible Duplicate:
Owner Drawing TMainMenu over Aero Glass Form?
Hi,
I am interested in having an application's main menu drawn on the application's caption bar ? A bit like iTunes and Songbird (Windows 7).
Any hints would be helpful - I can draw a button or panel, but no开发者_StackOverflow社区 a menu.
CHeers
It is not possible to relocate a standard Windows menu, Windows places it always right under the caption. Indeed a search with "iTunes" and "WS_CAPTION" shows up some references that say the iTunes window does not have the WS_CAPTION
style. I would guess the same to be true with 'Songbird' also. So what these applications doing is to remove the caption to have the menu at the top and simulate having a caption (they might even not have a standard menu and their own menu implementation, but I don't know about that).
You can remove the caption of a Delphi form by removing the style:
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);
Then the menu will appear at the top (with no caption). You would then fake mouse clicks at the top of the window to be on the caption for being able to move around the window with the mouse. You can achieve this by handling WM_NCHITTEST
message. But you have to exclude the area that the menu items occupy;
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;
Depending on the Delphi version you use, you might not succeed with the GetMenuBarInfo
call. F.i. D2007 incorrectly declares the TMenuBarInfo
structure packed. So you might have to redeclare it and the function before you call the function.
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;
Finally you would probably put some buttons to the far right side for users to be able to minimize, restore etc.. the window.
精彩评论