如何区分用户点击的键盘事件和生成的键盘事件?

发布于 2024-11-04 21:35:09 字数 853 浏览 0 评论 0原文

我安装了一个键盘钩子:

CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {

基本上我想获取用户的键盘点击,吃掉输入,然后发布我自己的输入代替。

因此,如果他点击“g”,我可能想将“foo”发布到文本字段。

我正在使用 CGEventPost 和 CGEventSetUnicodeString 写入文本字段,如下所示: http://www.mail-archive.com/ [email protected]/msg23343.html

问题是我以编程方式输入的每个字符都按下了键盘挂钩。所以我不能在键盘钩子中返回NULL来阻止用户输入......这也会阻止所有程序的输入!

我在 C# 中使用“注入”标志在 Windows 端区分它们,请参阅我一年前的问题:如何使用低级 8 位标志作为条件?

在 Objective-C 中寻找类似的东西。

I've installed a keyboard hook:

CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {

Basically I want to take the user's keyboard taps, eat the input, and post my own input instead.

So if he taps "g" I might want to post "foo" to the textfield.

I'm writing to the textfield with CGEventPost and CGEventSetUnicodeString as found here:
http://www.mail-archive.com/[email protected]/msg23343.html

The problem is that each of my programmatically entered characters is hitting the keyboard hook. So I can't return NULL in the keyboard hook to block the user input... that blocks all the program's input as well!

I differentiated them on the Windows side in C# with the 'injected' flag, see my question a year ago here: How do I use low-level 8 bit flags as conditionals?

Looking for something similar in Objective-C.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

记忆之渊 2024-11-11 21:35:16

看一下CGEventSource.h中的注释。将信息放在一起比使用 活动服务参考。长但更正确的方法看起来像 创建事件源(受内存管理规则的约束;如果使用完毕,则需要CFRelease)在程序终止之前):

myEventSource = CGEventSourceCreate(kCGEventSourceStatePrivate);

这将创建您自己的具有唯一 ID 的私有事件源;然后,您表明您创建的事件来自那里:

CGEventRef myKeyboardEvent = CGEventCreateKeyboardEvent(myEventSource, 
                                                        keyCode, true);

当事件进入时,检查它是否来自您自己:

 if( (CGEventGetType(newEvent) == kCGEventKeyDown) &&
     (CGEventGetIntegerValueField(newEvent, kCGEventSourceStateID) == CGEventSourceGetSourceStateID(myEventSource) ) {

还有一个 源的用户数据字段,可让您传递任意 64 位,如果您需要的话。

快速而肮脏的方法是尝试选择一个不太可能对键盘事件有意义的值的事件字段,例如 kCGMouseEventPressure 并将其转换为签名:

CGEventSetIntegerValueField(myKeyboardEvent, 
                            kCGMouseEventPressure, 
                            0xFEEDFACE);
// The field is an int_64 so you could make the sig longer

Take a look at the comments in CGEventSource.h. It's a little bit easier to put the information together than using the Event Services Reference. The long, but more correct, way around looks like creating an event source (which is subject to memory management rules; you need to CFRelease it if you're done using it before program termination):

myEventSource = CGEventSourceCreate(kCGEventSourceStatePrivate);

This will create your own private event source with a unique ID; you then indicate that events you create came from there:

CGEventRef myKeyboardEvent = CGEventCreateKeyboardEvent(myEventSource, 
                                                        keyCode, true);

When an event comes in, check to see if it's from yourself:

 if( (CGEventGetType(newEvent) == kCGEventKeyDown) &&
     (CGEventGetIntegerValueField(newEvent, kCGEventSourceStateID) == CGEventSourceGetSourceStateID(myEventSource) ) {

There's also a user data field for the source that lets you pass around an arbitrary 64 bits, should you need to.

The quick and dirty way would be to try picking an event field that isn't likely to be a meaningful value for a keyboard event, like kCGMouseEventPressure and turn it into a signature:

CGEventSetIntegerValueField(myKeyboardEvent, 
                            kCGMouseEventPressure, 
                            0xFEEDFACE);
// The field is an int_64 so you could make the sig longer
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文