2009-11-03 158 views
11

我想定製我在OS X上繪製窗口標題欄的方式。具體來說,我想要做一些類似於Twitterrific的應用程序,其中有一個自定義關閉按鈕,沒有最小/最大按鈕,窗口標題文本是正確的。與Twitterrific不同,我不想自定義繪製整個窗口(儘管我並不完全反對)。如何在Objective-C中自定義繪製窗口標題欄?

我已經看到了Cocoa With Love上的RoundWindow示例以及Apple提供的RoundTransparentWindow示例,但都不合適。

回答

6

如果你不想使用無邊框窗口類,那麼你可以做一些事情。

首先,您可以使用-[NSWindow standardWindowButton:]自定義關閉/最小/最大按鈕購買。一旦你得到的按鈕,你可以將其定位/刪除/等...

您可以通過將標題設置爲@""來自定義標題。然後,您可以通過執行以下[[[NSWindow contentView] superview] addSubview:textField]來添加NSTextField以繪製您自己的標題。

這可能是最簡單的方法。

另一種方式做,這是自定義繪製的所有窗口標題欄等視圖...

NSWindow的內容視圖的是一個「主題圖」裏。您可以繼承主題視圖並進行自己的繪製。唯一的問題是主題視圖是私人類,所以你必須小心。

+0

謝謝你,萊博維茨。你能否提供一些關於如何設置NSTextField的更多細節?我如何設置它的框架,使其正確定位在窗口中,以及我的代碼中哪裏是最好的地方? – sam 2009-11-03 18:05:35

+0

FWIW,我是在應用控制器的awakeFromNib方法中完成的。我將文本框的框架相對於窗口的框架進行了定位。這可能不是最好的辦法,但我使用通知來了解窗口何時變爲/退出主窗口並用它來更改文本的顏色。再次感謝這個想法。 – sam 2009-11-04 23:00:02

5

cocoadev提供了一些關於如何最好地實現自己的NSWindow子類的更多細節,並完成了對大多數常見陷阱的描述。

它的要點是建立NSWindow一個子類,並設置其styleMaskNSBorderlessWindowMask在init方法:

- (id) initWithContentRect: (NSRect) contentRect 
       styleMask: (unsigned int) aStyle 
        backing: (NSBackingStoreType) bufferingType 
        defer: (BOOL) flag 
{ 
    if ((self = [super initWithContentRect: contentRect 
           styleMask: NSBorderlessWindowMask 
            backing: bufferingType 
            defer: flag]) == nil) { return nil; } 

    [super setMovableByWindowBackground:YES]; 
    [super setLevel:NSNormalWindowLevel]; 
    [super setHasShadow:YES]; 
    // etc. 

    return self; 
} 

請注意,你應該爲了返回YES爲canbecomeKeyWindow,使你的窗口的行爲像一個正常的窗口。

- (BOOL) canBecomeKeyWindow 
{ 
    return YES; 
} 

然後,您可以創建自定義的NSView子類,與所述類的一個實例填滿整個窗口,然後執行所有相應的窗口從該自定義視圖中繪製的。

整件事情可能會有點痛苦。您將不得不重新實現大部分常規窗口行爲,例如通過拖動右下角來調整大小。

+0

謝謝,eJames。你說得對,這種方法(之前我已經開始)可能會很痛苦。我希望避免它,因爲我不想完全定製,我不想實現所有窗口的標準功能。這個方法基本上是我在問題中引用的示例中使用的。這種方法的一個奇怪的方面是窗口的陰影似乎不能正常工作。它不像標準窗口上的陰影那樣黑暗,並且焦點改變時它不會改變。我認爲這可能是一個無邊界窗口風格的錯誤。 – sam 2009-11-03 17:21:41

+0

陰影問題是奇怪的。聽起來Leibowitzn的答案可能是適合你的方式。祝你好運! – 2009-11-03 18:48:29

+0

陰影問題是一個長期存在的問題。蘋果公司並沒有爲有鍵盤焦點的無邊界窗口繪製較暗的陰影。例如,看一下Stickies。根據Apple的建議,解決這個問題的方法是使用普通窗口類型,然後執行所有自己的繪圖。 – Leibowitzn 2009-11-05 00:14:13

2

CoreData Stickies示例項目中有一個自定義窗口實現示例。