Simulate/Toggle 以编程方式在 OS X 中使用 CAPS LOCK

Simulate/Toggle CAPS LOCK programatically in OS X

我看过很多关于这个话题的post。但是还没有在任何地方找到明确的答案。

有没有办法在 Objective-C 或 C 代码中切换 CAPS LOCK?我不是在寻找使用 X11 库的解决方案。我不关心 LED on/off 状态。但只是 CAPS LOCK 的功能(改变字母的大小写和在数字键上打印特殊字符)。

为什么 CGEvent 不像其他密钥那样支持此功能?

经过长时间的努力,我终于成功了。

调用下面给出的方法两次。一次用于向上事件,另一个用于向下事件。例如模拟CAPS A,我们需要做如下操作。

[self handleKeyEventWithCapsOn:0 andKeyDown:NO];
[self handleKeyEventWithCapsOn:0 andKeyDown:YES];

0 是 'a' 的键码。

- (void) handleKeyEventWithCapsOn:(int) keyCode andKeyDown:(BOOL)keyDown
{
    if(keyDown)
    {
        CGEventRef eventDown;
        eventDown = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)keyCode, true);
        CGEventSetFlags(eventDown, kCGEventFlagMaskShift);
        CGEventPost(kCGSessionEventTap, eventDown);
        CFRelease(eventDown);
    }
    else
    {
        CGEventRef eventUp;
        eventUp = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)keyCode, false);
        CGEventSetFlags(eventUp, kCGEventFlagMaskShift);
        CGEventPost(kCGSessionEventTap, eventUp);

        // SHIFT Up Event
        CGEventRef eShiftUp = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)56, false);
        CGEventPost(kCGSessionEventTap, eShiftUp);
        CFRelease(eventUp);
        CFRelease(eShiftUp);
    }
}
var ioConnect: io_connect_t = .init(0)
let ioService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass))
IOServiceOpen(ioService, mach_task_self_, UInt32(kIOHIDParamConnectType), &ioConnect)

var modifierLockState = false
IOHIDGetModifierLockState(ioConnect, Int32(kIOHIDCapsLockState), &modifierLockState) 

modifierLockState.toggle()
IOHIDSetModifierLockState(ioConnect, Int32(kIOHIDCapsLockState), modifierLockState)

IOServiceClose(ioConnect)

当您希望 CapsLock 切换当前键盘语言时,以下方法也适用(如果您已将 CapsLock 键配置为执行此操作)。

CFMutableDictionaryRef mdict = IOServiceMatching(kIOHIDSystemClass);
io_service_t ios = IOServiceGetMatchingService(kIOMasterPortDefault, (CFDictionaryRef)mdict);
if (ios) {
    io_connect_t ioc = 0;
    IOServiceOpen(ios, mach_task_self(), kIOHIDParamConnectType, &ioc);
    if (ioc) {
        NXEventData event{};
        IOGPoint loc{};

        // press CapsLock key
        UInt32 evtInfo = NX_KEYTYPE_CAPS_LOCK << 16 | NX_KEYDOWN << 8;
        event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS;
        event.compound.misc.L[0] = evtInfo;
        IOHIDPostEvent(ioc, NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE);

        // release CapsLock key
        evtInfo = NX_KEYTYPE_CAPS_LOCK << 16 | NX_KEYUP << 8;
        event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS;
        event.compound.misc.L[0] = evtInfo;
        IOHIDPostEvent(ioc, NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE);

        IOServiceClose(ioc);
    }
}