我需要用Cocoa編寫一些東西來表面原始鼠標移動數據。最理想的情況是,應用程序只是一個可以運行的小守護程序,將數據傳遞給另一個應用程序可以使用的套接字服務器來訪問事件。鼠標跟蹤守護進程
任何人都可以在方向和工具方面指出正確的方向嗎?我甚至不知道現在該從哪裏開始。
我需要用Cocoa編寫一些東西來表面原始鼠標移動數據。最理想的情況是,應用程序只是一個可以運行的小守護程序,將數據傳遞給另一個應用程序可以使用的套接字服務器來訪問事件。鼠標跟蹤守護進程
任何人都可以在方向和工具方面指出正確的方向嗎?我甚至不知道現在該從哪裏開始。
其他簡單的方式做,這是add a global event monitor(10.6只,不過):
id eventHandler = [NSEvent addGlobalMonitorForEventsMatchingMask:NSMouseMovedMask handler:^(NSEvent * mouseEvent) {
NSLog(@"Mouse moved: %@", NSStringFromPoint([mouseEvent locationInWindow]));
}];
然後,當你做跟蹤,你這樣做:
[NSEvent removeMonitor:eventHandler];
寫一個EventTap。文檔可以是found here。
在MacOS X的每一個事件(例如每鍵盤按鍵按下,每一個鼠標鍵按下或鼠標移動)創建了移動以下路徑的事件:在這裏我寫了一個箭頭
Driver (Kernel) -> Window Server (privileged) -> User (Login) Session -> Active Application
無處不在(->
)的可以將EventTap放置到只查看事件(僅偵聽EventTap)或修改或刪除事件(事件篩選EventTap)。請注意,要捕獲Driver和WindowServer之間的事件,您的守護程序必須以root權限運行。
下面是一些示例代碼:
// Compile with:
// gcc -framework ApplicationServices -o MouseWatcher MouseWatcher.c
//
// Start with:
// ./MouseWatcher
//
// Terminate by hitting CTRL+C
#include <ApplicationServices/ApplicationServices.h>
static CGEventRef myEventTapCallback (
CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void * refcon
) {
CGPoint mouseLocation;
// If we would get different kind of events, we can distinguish them
// by the variable "type", but we know we only get mouse moved events
mouseLocation = CGEventGetLocation(event);
printf(
"Mouse is at x/y: %ld/%ld\n",
(long)mouseLocation.x,
(long)mouseLocation.y
);
// Pass on the event, we must not modify it anyway, we are a listener
return event;
}
int main (
int argc,
char ** argv
) {
CGEventMask emask;
CFMachPortRef myEventTap;
CFRunLoopSourceRef eventTapRLSrc;
// We only want one kind of event at the moment: The mouse has moved
emask = CGEventMaskBit(kCGEventMouseMoved);
// Create the Tap
myEventTap = CGEventTapCreate (
kCGSessionEventTap, // Catch all events for current user session
kCGTailAppendEventTap, // Append to end of EventTap list
kCGEventTapOptionListenOnly, // We only listen, we don't modify
emask,
&myEventTapCallback,
NULL // We need no extra data in the callback
);
// Create a RunLoop Source for it
eventTapRLSrc = CFMachPortCreateRunLoopSource(
kCFAllocatorDefault,
myEventTap,
0
);
// Add the source to the current RunLoop
CFRunLoopAddSource(
CFRunLoopGetCurrent(),
eventTapRLSrc,
kCFRunLoopDefaultMode
);
// Keep the RunLoop running forever
CFRunLoopRun();
// Not reached (RunLoop above never stops running)
return 0;
}
來自Dave答案是這樣做幾乎同樣的事情的更好的方式可可;基本上Cocoa和我在後面的示例中做的一樣,只是包裝成靜態方法。 Dave的代碼只能在10.6上運行,不過,上面的代碼在10.4,10.5和10.6中運行。
嗨Mecki,感謝這個。我使用的是10.6,因此,Dave描述的單線方法是更理想的解決方案。感謝您的意見! – Raconteur 2010-06-28 22:26:44
將'self'作爲'refcon'參數傳入,以便在觸發時可以調用ObjC類中的方法。請參閱http://stackoverflow.com/a/14985036/130910 – vaughan 2014-03-03 06:17:01
調用'[NSEvent eventWithCGEvent:event]'得到一個更好的API用於處理ObjC代碼的'NSEvent'。在ARC你需要橋接。例如:'[(__bridge MyClass *)refcon myHandlerInstanceMethod:e];' – vaughan 2014-03-03 06:19:32
但只適用於10.6,而我的代碼甚至可以使用10.4以上:-P – Mecki 2010-06-28 19:48:25
@Mecki yep,這是唯一的警告。如果海報可以專門定位10.6,那麼全球顯示器肯定更容易。否則,他需要一個事件點擊。 – 2010-06-28 19:49:17
感謝您的信息。我試着將Dave的代碼添加到我的應用程序中,但是我得到一個編譯錯誤,說NSEvent可能不會響應mouseLocation,並且NSStringFromPoint傳遞了一個無效參數。 (NSEvent * mouseEvent)之前的插入符號是什麼?這是問題嗎?我不熟悉這種語法... 鑑於我不能嘗試這個,讓我問,這會給我的鼠標數據?基本上,即使鼠標固定在左上角,我也需要知道用戶繼續向上移動並離開,就是這樣。這會實現嗎? 再次感謝! – Raconteur 2010-06-28 21:09:44