我正在发送键盘按键和按键释放事件,适用于所有键盘按键。
但修饰键只有在与应用程序关联的键与应用程序发送时才有效,而不是从真实硬件发送。那就是我送的 从应用程序转移和'a',它打印'A'(资本A,这是预期的)。
但是如果我从应用程序发送'shift'键向下事件,并从物理键盘输入'a',它会打印'a'(换档键似乎不能在不同的设备上工作)。这同样适用于其他修饰键,例如cmd,alt和fn键!。
有没有办法将修改键发送到系统,以便我可以从我的应用程序模拟修改键? 具体来说,我想从应用程序激活修改键,然后从物理键盘输入组合键。
以下是我用来发送按键和发布事件的代码。
- (void)setADBKey:(uint32)key value:(int)value
{
if (!eventSource)
{
eventSource = CGEventSourceCreate(kCGEventSourceStatePrivate);
}
CGEventRef event = CGEventCreateKeyboardEvent(eventSource, key, value!=0);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}
我还尝试通过以下代码创建和发送系统事件
struct
{
CGKeyCode keyCode;
int flag;
int cgEventFlag;
} modifiers[] = {
{ 56, NX_DEVICELSHIFTKEYMASK, kCGEventFlagMaskShift },
{ 60, NX_DEVICERSHIFTKEYMASK, kCGEventFlagMaskShift },
{ 59, NX_DEVICELCTLKEYMASK, kCGEventFlagMaskControl },
{ 58, NX_DEVICELALTKEYMASK, kCGEventFlagMaskAlternate },
{ 61, NX_DEVICERALTKEYMASK, kCGEventFlagMaskAlternate },
{ 55, NX_DEVICELCMDKEYMASK, kCGEventFlagMaskCommand },
{ 54, NX_DEVICERCMDKEYMASK, kCGEventFlagMaskCommand }
};
- (void)setAdbKey:(uint32)adbkey value:(int)value repeat:(BOOL)repeat
{
//int adbkey = def_usb_2_adb_keymap[hidkey];
int modifier = 0;
for(int i=0; i< ARR_SIZE(modifiers); i++)
{
if (adbkey == modifiers[i].keyCode)
{
modifier = modifiers[i].cgEventFlag;
break;
}
}
if (value)
{
flags |= modifier;
}
else
{
flags &= ~modifier;
}
CGEventRef event = CGEventCreateKeyboardEvent(eventSource, adbkey, value!=0);
if (repeat)
{
CGEventSetIntegerValueField(event, kCGKeyboardEventAutorepeat, (int64_t)1);
}
// don't apply modifier flags to a modifier
if (!modifier)
{
CGEventSetFlags(event, flags);
}
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}
当从应用程序发送修饰键和组合键时,这两种方法都有效,但是当仅从应用程序设置修饰键时,这两种方法都不起作用。
答案 0 :(得分:1)
您所要做的就是创建一个事件点按并设置面具。
样品:
@interface AppDelegate ()
@property (assign) CFMachPortRef myEventTap;
@property (assign) CFRunLoopSourceRef myRunLoopSource;
@end
@implementation AppDelegate
CGEventRef MyEventTapCallBack(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
CGEventSetFlags(event, kCGEventFlagMaskShift);
return event;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.myEventTap = CGEventTapCreate(kCGHIDEventTap,
kCGHeadInsertEventTap,
kCGEventTapOptionDefault,
CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged),
MyEventTapCallBack,
(__bridge void *)self);
if (self.myEventTap) {
self.myRunLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, self.myEventTap, 0);
if (self.myRunLoopSource)
CFRunLoopAddSource(CFRunLoopGetMain(), self.myRunLoopSource, kCFRunLoopCommonModes);
}
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
if (self.myRunLoopSource) {
CFRunLoopSourceInvalidate(self.myRunLoopSource);
CFRelease(self.myRunLoopSource);
}
if (self.myEventTap)
CFRelease(self.myEventTap);
}
@end
答案 1 :(得分:0)
这是我的appDelegate及其运行方式。
import Cocoa
import CoreGraphics
import Foundation
var shift = false;
var cntrl = false;
var option = false;
var command = false;
func myCGEventCallback(proxy: CGEventTapProxy, type: CGEventType, event: CGEvent, refcon: UnsafeMutableRawPointer?) -> Unmanaged<CGEvent>? {
var mask: CGEventFlags = []
if(shift) {
mask.insert(CGEventFlags.maskShift)
}
if(cntrl) {
mask.insert(CGEventFlags.maskControl)
}
if(option) {
mask.insert(CGEventFlags.maskAlternate)
}
if(command) {
mask.insert(CGEventFlags.maskCommand)
}
if(mask.rawValue != 0) {
event.flags = mask;
}
return Unmanaged.passRetained(event)
}
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
let mask: CGEventMask = 1 << CGEventType.keyDown.rawValue
let eventTap:CFMachPort = CGEvent.tapCreate(tap: .cghidEventTap, place: .headInsertEventTap, options: .defaultTap, eventsOfInterest: mask, callback: myCGEventCallback, userInfo: nil)!
let runLoopSource:CFRunLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, CFRunLoopMode.commonModes);
CGEvent.tapEnable(tap: eventTap, enable: true);
CFRunLoopRun();
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
public func SetShift() {
shift = !shift;
}
public func SetCtrl() {
cntrl = !cntrl;
}
public func SetCommand() {
command = !command;
}
public func SetOption() {
option = !option;
}
}