2011-02-26 30 views
1

可能重複:
Owner Drawing TMainMenu over Aero Glass Form?繪圖應用程序MAINMENU採用Delphi

嗨,

我很感興趣,有一個應用程序的主菜單中的應用程序的標題欄上繪製的?有點像iTunes和Songbird(Windows 7)。

任何提示都會有所幫助 - 我可以繪製按鈕或面板,但不能顯示菜單。

歡呼

+2

這是一個重複http://stackoverflow.com/questions/4732039/owner-drawing-tmainmenu-over-aero-glass-form? –

+0

即使在非客戶區域頂部繪製菜單,iTunes也不會在玻璃上繪製其主菜單。如果您只想在非客戶區域繪製菜單,請從問題標題中刪除單詞玻璃,並且它不會作爲副本關閉。 Songbird不支持從我所能看到的玻璃。 –

+0

投票重新開放,因爲明顯提到*玻璃*是一個無意的錯誤,已經根據沃倫的評論予以更正,事實上,我不太明白其他問題提出的問題。 –

回答

2

這是不可能搬遷一個標準的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調用獲得成功。 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; 

最後,您可能會在最右邊放一些按鈕,以便用戶能夠最小化,恢復等。窗口。

+0

很酷。我會試驗一下,看看這是否做到了我想要的! – Mmarquee

+0

它的工作原理 - 只要我知道如何更換控制按鈕。 – Mmarquee

+0

@Marquee - 如果通過控制按鈕表示最小化,關閉等等,則可以根據光標的位置再次返回相關的命中測試。至於外觀,你可以根據鼠標按鍵來選擇合適的圖像。提示:你總是可以提出一個問題。 :) –