2014-02-08 21 views
4

我已經子類NSWindow和我有一個mywindow的類實現以下方法:更改鼠標光標放在非激活NSWindow

-(void)resetCursorRects { 
    NSImage *image = [NSImage imageNamed:@"cursor.png"]; 
    [image setSize:NSMakeSize(32, 32)]; 
    NSCursor *cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint(1, 1)]; 
    [super resetCursorRects];  
    [self addCursorRect:[self bounds] cursor:cursor]; 
} 

這將改變光標整個窗口,我會看,而不是cursor.png的默認的鼠標指針。問題是,只有當MYWindow被設置爲關鍵窗口,這當然不是微不足道的。

在我的項目開始時,我只有一個主窗口,但現在我需要有兩個不同的MYWindow。兩個窗口的問題無法設置爲關鍵窗口,因此只能在活動窗口上顯示自定義鼠標指針。我需要點擊另一個窗口來顯示光標。

有沒有辦法解決這個問題?所以我在兩個窗口上都有一個自定義光標?

編輯:嘗試NSTrackingArea

我將此添加到我的內容視圖的init方法:

self.trackingArea = [[NSTrackingArea alloc] initWithRect:[self frame] options: (NSTrackingCursorUpdate | NSTrackingActiveAlways | NSTrackingMouseMoved) owner:self userInfo:nil]; 
[self addTrackingArea:self.trackingArea]; 

然後我overrided cursorUpdate:是這樣的:

-(void)cursorUpdate:(NSEvent *)event { 
    NSLog(@"event : %@", event); 
    [[NSCursor crosshairCursor] set]; 
} 

這使得crosshairCursor顯示何時包含NSImageView派生類的NSWindow是關鍵窗口。但是,如果我在應用程序的關鍵窗口內創建另一個NSWindow,則光標會再次返回到標準光標。難道我做錯了什麼?

回答

2

現在我終於找到一個可行的解決方案。我不知道這是否會在未來讓我陷入尾巴,但至少在測試時這似乎有效。

感謝Wil對於這個例子,讓我感受到了一半。但只有當我最終將它與resetCursorRects結合在一起,並且還在每個視圖中使用特定光標定義了遊標矩形時。這花了我很長時間才弄清楚,我不知道解決方案是否是最佳的(歡迎提出改進意見)

下面是完整的例子,它使它在我的工作最終(self.cursor是光標的實例)

- (void)viewWillMoveToWindow:(NSWindow *)newWindow { 
    NSTrackingArea *const trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect options:(NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways | NSTrackingInVisibleRect) owner:self userInfo:nil]; 
    [self addTrackingArea:trackingArea]; 
    [self.window invalidateCursorRectsForView:self]; 
} 

- (void)resetCursorRects { 
    [super resetCursorRects]; 
    [self addCursorRect:self.bounds cursor:self.cursor]; 
} 

- (void)mouseEntered:(NSEvent *)theEvent { 
    [super mouseEntered:theEvent]; 
    [self.cursor push]; 
} 

- (void)mouseExited:(NSEvent *)theEvent { 
    [super mouseExited:theEvent]; 
    [self.cursor pop]; 
} 
+0

我是新來的OS X,但從我讀過的addCursorRect爲整個矩形定義了一個特定的光標 - 如果您想在鼠標移動到不同區域時更改光標,該怎麼辦?讓我們假設我無法預先定義所有rects。我想你可以改變self.cursor並調用resetCursorRects ... 重寫'windowDidBecomeKey'和'windowDidBecomeMain'以調用'[self.cursor push]'似乎是一種替代解決方案,儘管您暫時可以看到光標閃爍當點擊窗口時到正常的箭頭。 (你甚至需要使用光標縮進的'push'?) – sqweek

4

只要不希望它在應用程序處於非活動狀態時(也就是不可能)不需要更改,您應該可以添加更改光標的NSTrackingArea。


編輯:

我能得到這個工作,用下面的代碼:

- (vod)someSetup; 
{ 
    NSTrackingArea *const trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect) owner:self userInfo:nil]; 
    [self.view addTrackingArea:trackingArea]; 
} 

- (void)mouseEntered:(NSEvent *)theEvent; 
{ 
    [[NSCursor IBeamCursor] push]; 
} 

- (void)mouseExited:(NSEvent *)theEvent; 
{ 
    [[NSCursor IBeamCursor] pop]; 
} 
+0

我想你是指NSTrackingArea?我現在已經嘗試過,但是我無法使用它。我只對當我的應用程序處於活動狀態時更改光標感興趣,但我也需要在應用程序內的不活動的NSWindows上發生這種情況。我將用我的發現更新我的問題。 –

+0

Thnaks!現在,編輯之後,這非常接近於工作,只剩下一件事需要解決。 現在它在我的NSWindows中正確顯示了正確的光標,但是一旦我點擊其中一個NSWindows,光標就會恢復爲標準光標。如果我進入和離開窗戶,它會再次正確。但我需要修復這個小毛病。 –

+0

你的窗戶有哪些視圖?你仍然在視圖上有cursorUpdate:方法嗎? –

3

我掙扎着這個問題的很長一段時間,我覺得只有一個改變了活動應用鼠標光標(在非前臺窗口)的方式。這是一種奇特而神奇的方式。

之前調用非常標準:

[[NSCursor pointingHandCursor] push]; 

你要撥打:

void CGSSetConnectionProperty(int, int, int, int); 
int CGSCreateCString(char *); 
int CGSCreateBoolean(BOOL); 
int _CGSDefaultConnection(); 
void CGSReleaseObj(int); 
int propertyString, boolVal; 

propertyString = CGSCreateCString("SetsCursorInBackground"); 
boolVal = CGSCreateBoolean(TRUE); 
CGSSetConnectionProperty(_CGSDefaultConnection(), _CGSDefaultConnection(), propertyString, boolVal); 
CGSReleaseObj(propertyString); 
CGSReleaseObj(boolVal); 

或者,如果您使用的是斯威夫特:

YourApp-Bridging-Header.h將這個:

typedef int CGSConnectionID; 
CGError CGSSetConnectionProperty(CGSConnectionID cid, CGSConnectionID targetCID, CFStringRef key, CFTypeRef value); 
int _CGSDefaultConnection(); 

然後致電:

let propertyString = CFStringCreateWithCString(kCFAllocatorDefault, "SetsCursorInBackground", 0) 
CGSSetConnectionProperty(_CGSDefaultConnection(), _CGSDefaultConnection(), propertyString, kCFBooleanTrue) 
+0

如果你沒有橋接頭,該怎麼辦。你如何在Swift中聲明這些行? – MAH

+0

我相信你只需要'bridging header'(爲什麼不呢?),因爲沒有其他方法(IMO)在Swift代碼中導入這些函數。或者你可以把這個代碼放入一個動態庫(用C或Objective-C編寫)中,然後用Swift代碼導入它。 –

+0

沒有理由沒有我想到的。我的應用程序完全在Swift中,但我無法完成這部分工作。剩下的唯一難題就是讓'CGAssociateMouseAndMouseCursorPosition'在後臺工作。 – MAH