我正在尝试创建一个OS X键盘钩子用于辅助技术目的(即不要担心,而不是键盘记录器).
当用户按下某个键时,我想阻止真正的按键并发送假按键(我选择的字符).
我有以下代码:
- (void) hookTheKeyboard {
CGEventMask keyboardMask = CGEventMaskBit(kCGEventKeyDown);
id eventHandler = [NSEvent addGlobalMonitorForEventsMatchingMask:keyboardMask handler:^(NSEvent *keyboardEvent) {
NSLog(@"keyDown: %c", [[keyboardEvent characters] characterAtIndex:0]);
//Want to: Stop the keyboard input
//Want to: Send another key input instead
}];
}
Run Code Online (Sandbox Code Playgroud)
有任何帮助实现这些目标吗?基本上修改NSEvent"keyboardEvent"以发送不同的字符.谢谢.
我刚刚尝试了addLocalMonitorForEventsMatchingMask:handler:NSEvent中的方法,并遇到了以下问题:如何确定是否只按了某些修饰符?
将此问题设置为上下文的简短示例:我想要听取快捷方式"⌘+ W".因此我写了以下代码:
[NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *theEvent) {
if ([theEvent modifierFlags] & NSCommandKeyMask && [theEvent keyCode] == 13) {
[self.window performClose:self];
}
return theEvent;
}];
Run Code Online (Sandbox Code Playgroud)
这很有效,但即使按下更多修饰键,也会触发快捷键,例如"^ +⌘+ W"或"⇧+ ^ +⌥+⌘+ W".有没有办法规避这个?
一个简单的解决方案是检查所有其他修改键并确保没有按下它们.这似乎很乏味且容易出错 - 除了它的丑陋之外,因为它现在与一元"&".此外,如果(由于某种原因)另一个修改键添加到键盘布局,您可能会遇到麻烦.
一如既往,我很感谢任何建议.
我有一个捕获mouseDown事件的NSView.
我正在使用以下方式协调鼠标点击:
- (void)mouseDown:(NSEvent *)theEvent {
NSPoint touchPoint = [NSEvent mouseLocation];
//Rest of code
}
Run Code Online (Sandbox Code Playgroud)
但是,这会将clickPoint设置为全局屏幕协调中鼠标的位置.
我想在相对视图协调中获得点击的位置 - 如果用户点击窗口的左下角,我想要的是点(0,0),无论屏幕上包含的窗口在哪里.
当用户使用以下代码按任意Shift键时,我可以识别:
-(void)flagsChanged:(NSEvent *)theEvent
{
if ([theEvent modifierFlags] & NSShiftKeyMask)
//. . .
}
Run Code Online (Sandbox Code Playgroud)
但有没有办法区分它是按下的右键还是左键?
在Swift中:我创建了一个简单的NSView,现在想要执行不同的功能,具体取决于按下哪个mouseButton(左或右).我怎么能发现这个?
在我正在开发的应用程序中,数据库用于存储所有用户数据,通常位于库/应用程序支持中的某个位置.为了使用户能够切换数据库,我想实现类似于iTunes或iPhoto的功能,如果在启动应用程序时按下选项键,应用程序会询问库或数据库的位置.
如果没有NSEvent,如何检查当前按下的(修饰符)键?
我已经尝试过:
[NSResponder flagsChanged:(NSEvent *)theEvent] - 可能没有被调用,因为选项键在窗口之前已经关闭,并且任何响应者都被实例化了.
[[NSApplication sharedApplication] currentEvent]- 退货nil.
我在侦听事件时遇到问题,我可以听取完美运行的事件但是我不能让它停止听事件.我研究了一段时间,想出了一个方法,+(void)removeMonitor:(id)eventMonitor,它说当我完成监听器时我应该使用它
但是当我尝试使用这种方法时,就像这样
[NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDownMask|NSKeyDownMask) handler:^(NSEvent *event) {
[NSEvent removeMonitor:event];
}];
Run Code Online (Sandbox Code Playgroud)
我一直收到错误" - [NSEvent invalidate]:无法识别的选择器发送到实例"我也研究过,我相信这意味着我正在覆盖正在使用的内存.但是我不知道如何解决这个问题.任何建议或帮助非常感谢!
更新感谢JWWalker,Samir和Abizern,它现在有效
//I made a global variable called eventHAndler
Run Code Online (Sandbox Code Playgroud)
.h文件
id eventHAndler
Run Code Online (Sandbox Code Playgroud)
.m文件
eventHAndler = [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDownMask|NSKeyDownMask) handler:^(NSEvent *event){
///code
}];
/// created another method called stop. When called it stops the eventHAndler
- (IBAction)Stop:(id)sender
{
stop = 1;
NSLog(@"inside stop method");
[NSEvent removeMonitor:eventHAndler];
}
Run Code Online (Sandbox Code Playgroud) 在我的应用程序中,我希望滚动发生,只有鼠标滚轮动作而不是触控板上的两个手指动作.基本上,我试图确定是否从鼠标或触控板生成scrollWheelEvent,内部 - (void)scrollWheel:(NSEvent*)theEvent方法.据我所知,到目前为止,似乎没有直接的方法来实现这一目标.
我尝试了将boolean变量设置为true和false in - (void)beginGestureWithEvent:(NSEvent*)event; 和 - (void)endGestureWithEvent:(NSEvent*)事件; 但这不是一个解决方案,因为在调用endGestureWithEvent:方法之后,会多次调用scrollWheel:方法.
这是我的代码:
$BOOL fromTrackPad = NO;
-(void)beginGestureWithEvent:(NSEvent *)event;
{
fromTrackPad = YES;
}
-(void) endGestureWithEvent:(NSEvent *)event;
{
fromTrackPad = NO;
}
- (void)scrollWheel:(NSEvent *)theEvent
{
if(!fromTrackPad)
{
//then do scrolling
}
else
{
//then don't scroll
}
}
Run Code Online (Sandbox Code Playgroud)
我知道这是不标准的,但这是我的要求.有谁知道这样做的方法?谢谢!
我是OS X编程的新手,我正在尝试编写一个能够在系统范围内捕获Force Click事件的应用程序.
基于各种来源,我写下了下面列出的代码:
var lastClickStage = -1
func checkAssistanceSettings () -> Bool {
let checkOptPrompt = kAXTrustedCheckOptionPrompt.takeUnretainedValue() as NSString
let options = [checkOptPrompt: true]
let accessEnabled = AXIsProcessTrustedWithOptions(options)
return accessEnabled == 1
}
func processForceClick(incomingEvent: NSEvent!) -> Void {
let clickStage = incomingEvent.stage
if clickStage == lastClickStage {
return
}
if (lastClickStage == 2 && clickStage != 2) {
lastClickStage = clickStage
return
}
if (clickStage == 2 && lastClickStage != 2) {
let applicationClicked = NSWorkspace.sharedWorkspace().frontmostApplication?.bundleIdentifier
if (applicationClicked …Run Code Online (Sandbox Code Playgroud) 在某些应用程序中,应用程序直接处理键盘快捷键是有意义的,否则键盘快捷键将绑定到系统范围的组合.例如,⌘-Space(通常是Spotlight)或⌘-Tab(通常是app切换器).这适用于各种Mac应用程序,例如VMWare Fusion,Apple自己的屏幕共享和远程桌面客户端(分别将事件转发到VM或服务器,而不是在本地处理它们),以及应用程序中的一些类似的第三方应用程序商店.
我们希望在我们正在开发的应用程序中实现这样的模式,但是很难确定如何做到这一点.我应该指出,有问题的应用程序是一个常规的前台应用程序,是沙箱,任何解决方案都必须符合App Store规则.商店中的其他应用程序可以执行此操作的事实意味着这必须是可能的.
要清楚,我们希望:
Apple的Event Architecture文档表明前台应用程序应该已经接收了这些事件.(这大约只有同期水平搬运东西,如电力会谈和弹出按钮,这是很好的.)它继续提出,而关键事件文件还暗示说NSApplication的sendEvent:方法就是检测基于修正标志潜在的快捷方式,调度他们到窗口,如果失败,到菜单栏.它没有明确说明全局绑定快捷方式会发生什么.
我尝试了子类化NSApplication和重写sendEvent:.无论我是否将所有事件都传递给超类实现,或者如果我说,过滤修饰键事件,当我按⌘-Space时,我会收到按下并释放命令(⌘)键的事件,但不会显示空格键.Spotlight UI总是会弹出.
我没有从Apple或其他方面找到有关子类化NSApplication及其早期事件处理的更多信息.我似乎无法找出检测和处理全局快捷方式的级别.
有人可以指点我正确的方向吗?
可行的解决方案不起作用:
建议我在其他Stack Overflow帖子中看到但不适用于我见过的其他应用程序(这会破坏App Store规则):
这两个会矫枉过正,无论如何,因为他们让你拦截所有的活动在所有时候,不只是当你的应用程序是前台应用程序.
NSevent的addGlobalMonitorForEventsMatchingMask:handler:同时并不妨碍全球快捷方式处理从发射这些事件,所以甚至没有尝试它.
nsevent ×10
cocoa ×7
macos ×6
objective-c ×4
swift ×2
modifier-key ×1
mousedown ×1
nsview ×1
trackpad ×1