2012-06-15 121 views
2

我想在沒有實際點擊鼠標的情況下模擬Cocoa應用程序上的鼠標點擊,並且*不必知道在當前鼠標位置的情況下哪個視圖應該響應點擊。在NSWindow中模擬鼠標點擊

我想Cocoa框架來處理搞清楚哪些觀點應該作出迴應,所以我不認爲一個的NSView對象上的方法調用就是我要找的。也就是說,我想我需要一個方法調用,最終調用這個方法。

我現在有通過點擊鼠標在特定的全局位置,使用CGEventCreateMouseEvent和CGEventPost這個工作。但是,這種技術實際上點擊了鼠標。所以這是有效的,但我並不完全滿意這種行爲。例如,如果我在調用CGEventPost時按住鍵盤上的某個鍵,則該鍵將被包裝到事件中。另外,如果我將另一個進程的窗口移動到我想要模擬點擊的窗口上,那麼CGEventPost方法將在該窗口中單擊鼠標。也就是說,它在全球範圍內行動,跨越流程。我想要一種可以在單個窗口上工作的技術。 NSWindow對象上可能有?

我在Cocoa文檔中讀到「鼠標事件由NSWindow對象分派給發生事件的NSView對象」。

好的。所以我想知道調用的方法。在窗口中調用這個方法,然後讓框架指定哪個NSView調用給定當前鼠標位置。

任何幫助將不勝感激。我剛剛開始學習Cocoa框架,所以我很抱歉如果有任何術語/動詞不完全正確。

+2

[' - [NSApplication sendEvent:]'](http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html)實質上是輸入事件的入口點;從那裏(通常)傳遞到窗口。也就是說,你試圖在「模擬」和「實際」點擊鼠標之間的區別並不清楚。您試圖避免的「CGEvent」過程有哪些功能? (例如,物理鼠標設備中沒有移動按鈕的伺服器,這就是我所稱的「實際」點擊。) –

+0

已編輯。 Thx爲您的評論。 –

+0

@JoshCaswell這看起來很不錯,但我無法實現。我會發布代碼,但是它使用Objective C橋編寫在Clozure中,因此解析可能會有點麻煩。我找不到任何使用sendEvent模擬鼠標點擊的例子。你有機會嗎? –

回答

4

很難確切知道您要尋找多少保真度,以及實際點擊會發生什麼。例如,你想要點擊來激活應用程序嗎?你想點擊一下窗口到頂部?爲了讓它成爲關鍵還是主要?如果位置在標題欄中,您是否希望它可能關閉,最小化,縮放或移動窗口?

正如John Caswell指出的那樣,如果您傳遞一個適當構造的NSEvent-[NSApplication sendEvent:],它將精確地模擬真實事件的處理過程。在大多數情況下,NSApplication將把事件轉發到事件窗口及其-[NSWindow sendEvent:]方法。如果您想避免NSApplication做其他事情,則可以直接發送到窗口的-sendEvent:方法。但是這可能會打敗一些理想的行爲,具體取決於你的願望。

如果點擊的窗口或視圖的響應是運行內部事件跟蹤循環,會發生什麼?這將是同步的;也就是說,調用-sendEvent:的代碼在該循環完成之後纔會得到控制權,並且如果您無法傳遞後續事件,該代碼可能無法完成。事實上,這樣的循環將通過-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]尋找隨後的事件,所以如果你的綜合事件不在隊列中,它們將不會被看到。因此,對真實事件處理的更好模擬可能需要您使用-[NSApplication postEvent:atStart:]將事件(鼠標向下,鼠標拖動,鼠標移動)發佈到隊列中。

我認爲你的首要任務是深入思考你要完成的任務,所有潛在的陷阱和案例,並決定如何處理這些問題。

關於CGEvent...的東西,您可以使用CGEventPostToPSN()將事件發佈到特定進程,即使它們位於目標窗口的前方,它也不會點擊其他應用程序的窗口。但是,它仍然可以點擊目標應用程序中的其他窗口。

1

您可以通過調用mouseDown:這樣模擬鼠標點擊:

[self mouseDown: nil]; 

而且在屏幕上獲得鼠標位置:

-(void)mouseDown:(NSEvent *)theEvent { 

    NSPoint mouseLocation = [NSEvent mouseLocation]; 

    NSLog(@"x: %f", mouseLocation.x); 
    NSLog(@"y: %f", mouseLocation.y); 
} 
+0

這需要已經知道鼠標事件的正確目標。 –

+0

@JoshCaswell你是指知道鼠標事件的正確目標是什麼? –

+0

這看起來像是正確的方向,但我認爲我需要爲鼠標單擊構建適當的NSEvent對象。該代碼應該有鼠標位置,是的? –

2

確定。所以我想知道調用的方法。在窗口中調用這個方法,然後讓框架指定哪個NSView調用給定當前鼠標位置。

NSView *target = [[theWindow contentView] hitTest:thePoint]; 

我不是你的問題完全清楚,所以我不知道,如果你想要做的是再調用鼠標按下:目標。但是,如果你這樣做了,那幾乎和真正的鼠標點擊一樣。

這是用於提供實時點擊的消息。它遍歷視圖層次結構,自動處理重疊,隱藏的消息等,並讓視圖鏈中的每一步都可以干預。如果一個視圖想要阻止子視圖獲得點擊,那麼通過使用hitTest:來做到這一點,這意味着它會以與實際點擊相同的方式影響您的代碼。 如果點擊將被髮送,該方法總是告訴你其中它將被髮送。

然而,這並不一定處理的點擊可能無法傳遞(acceptsFirstMouse,模態對話框等)的所有原因。此外,你必須知道窗口和點(在適當的座標系中),但聽起來你就是這樣開始的。

+0

謝謝你。這看起來像一個簡單的方法。將盡快測試,併發布結果。 –