我很快把這段代碼扔到了一起,所以一定要審查它的內存泄漏等。你會看到你需要添加你想處理的其他字符以及案例(我只加k - >к) 。
本示例構建爲「命令行」實用程序,因此它沒有UI,適合通過launchd
在後臺運行。請注意,您需要以root用戶身份運行此操作,或者在系統偏好設置中啓用輔助設備支持,併爲此應用添加權限。
請注意,在開發Xcode時,您可以轉到Product -> Scheme -> Edit
並在「運行」部分將「調試過程as」的收音機更改爲「root」。
編輯:使用autorelease池更新以釋放臨時對象。
// compile and run from the commandline with:
// clang -fobjc-arc -framework Cocoa ./foo.m -o foo
// sudo ./foo
#import <Foundation/Foundation.h>
#import <AppKit/NSEvent.h>
typedef CFMachPortRef EventTap;
@interface KeyChanger : NSObject
{
@private
EventTap _eventTap;
CFRunLoopSourceRef _runLoopSource;
CGEventRef _lastEvent;
}
@end
CGEventRef _tapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, KeyChanger* listener);
@implementation KeyChanger
- (BOOL)tapEvents
{
if (!_eventTap) {
NSLog(@"Initializing an event tap.");
_eventTap = CGEventTapCreate(kCGSessionEventTap,
kCGTailAppendEventTap,
kCGEventTapOptionDefault,
CGEventMaskBit(kCGEventKeyDown),
(CGEventTapCallBack)_tapCallback,
(__bridge void *)(self));
if (!_eventTap) {
NSLog(@"unable to create event tap. must run as root or add privlidges for assistive devices to this app.");
return NO;
}
}
CGEventTapEnable(_eventTap, TRUE);
return [self isTapActive];
}
- (BOOL)isTapActive
{
return CGEventTapIsEnabled(_eventTap);
}
- (void)listen
{
if (!_runLoopSource) {
if (_eventTap) {//dont use [self tapActive]
_runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault,
_eventTap, 0);
// Add to the current run loop.
CFRunLoopAddSource(CFRunLoopGetCurrent(), _runLoopSource,
kCFRunLoopCommonModes);
NSLog(@"Registering event tap as run loop source.");
CFRunLoopRun();
}else{
NSLog(@"No Event tap in place! You will need to call listen after tapEvents to get events.");
}
}
}
- (CGEventRef)processEvent:(CGEventRef)cgEvent
{
NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
// TODO: add other cases and do proper handling of case
if ([event.characters caseInsensitiveCompare:@"k"] == NSOrderedSame) {
event = [NSEvent keyEventWithType:event.type
location:NSZeroPoint
modifierFlags:event.modifierFlags
timestamp:event.timestamp
windowNumber:event.windowNumber
context:event.context
characters:@"к"
charactersIgnoringModifiers:@"к"
isARepeat:event.isARepeat
keyCode:event.keyCode];
}
_lastEvent = [event CGEvent];
CFRetain(_lastEvent); // must retain the event. will be released by the system
return _lastEvent;
}
- (void)dealloc
{
if (_runLoopSource){
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), _runLoopSource, kCFRunLoopCommonModes);
CFRelease(_runLoopSource);
}
if (_eventTap){
//kill the event tap
CGEventTapEnable(_eventTap, FALSE);
CFRelease(_eventTap);
}
}
@end
CGEventRef _tapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, KeyChanger* listener) {
//Do not make the NSEvent here.
//NSEvent will throw an exception if we try to make an event from the tap timout type
@autoreleasepool {
if(type == kCGEventTapDisabledByTimeout) {
NSLog(@"event tap has timed out, re-enabling tap");
[listener tapEvents];
return nil;
}
if (type != kCGEventTapDisabledByUserInput) {
return [listener processEvent:event];
}
}
return event;
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
KeyChanger* keyChanger = [KeyChanger new];
[keyChanger tapEvents];
[keyChanger listen];//blocking call.
}
return 0;
}
我不清楚你在問什麼 - 也許你可以提供一些更多的上下文,或者一個例子顯示你在找什麼?請務必檢查[問題清單](http://meta.stackexchange.com/questions/156810/stack-overflow-question-checklist)。謝謝! –
@ChristianTernus我需要的是一個像這樣的本地應用程序:http://translit.ru/,但在後臺工作。每次我寫和應用程序正在運行,我得到我的所有應用俄語輸出(野生動物園,鉻等) –
看起來這個問題的答案將幫助您: http://stackoverflow.com/questions/6421718/how- to-trap-global-keydown-keyup-events-in-cocoa –