1

我在 OSX 上的 C++ 中使用 ApplicationServices 和 CGEventPost,我正在尝试查看是否可以按住一个键,但它不起作用。

这是我正在使用的方法:

void postKeyboardEvent( int keyCode, bool keyUp = false )
{

    CGEventSourceRef source = CGEventSourceCreate( kCGEventSourceStateHIDSystemState );

    CGEventRef keyEvent = CGEventCreateKeyboardEvent( source, (CGKeyCode) keyCode, !keyUp );
    CGEventPost( kCGAnnotatedSessionEventTap, keyEvent );
    CFRelease( keyEvent );

    CFRelease( source );

}

这就是我测试它的方式:

postKeyboardEvent( kVK_Command );
postKeyboardEvent( kVK_Tab );
postKeyboardEvent( kVK_Tab, true );
postKeyboardEvent( kVK_Command, true );

据我了解,这应该将我切换到另一个窗口,但它只是“放开”命令键并键入一个制表符。

重要提示:我不想使用以下内容:

CGEventSetFlags( keyEvent, kCGEventFlagMaskCommand );

我需要发送按键和按键命令的“串行链”,不必知道哪些键码是修饰键或用多少个来标记事件。

有没有办法做到这一点?

4

1 回答 1

1

这就是答案!https://stackoverflow.com/a/8202467/877860https://stackoverflow.com/users/314546/valexa发布

最简单的方法就是将当前修饰符标志与所需修饰符的标志进行按位或运算,例如:

CGEventFlags flags = kCGEventFlagMaskShift;
CGEventRef ev;
CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateCombinedSessionState);

//press down            
ev = CGEventCreateKeyboardEvent (source, keyCode, true);    
CGEventSetFlags(ev,flags | CGEventGetFlags(ev)); //combine flags                        
CGEventPost(kCGHIDEventTap,ev);
CFRelease(ev);              

//press up                                  
ev = CGEventCreateKeyboardEvent (source, keyCode, false);                       
CGEventSetFlags(ev,flags | CGEventGetFlags(ev)); //combine flags                        
CGEventPost(kCGHIDEventTap,ev); 
CFRelease(ev);              

CFRelease(source);

更新: 这是我采用的方法,它可以进行一些清理,但对于我将一系列键码发送到系统并让它们可预测地发生的目的来说,它工作得很好。

这里一个非常重要的元素是按位操作,如果 shift 不向下,则使用(& ~)含义 AND NOT 删除 shift 键掩码。

int shiftKeyCode = 56;
bool shiftIsDown = false;

void postKeyboardEvent( int keyCode, bool keyUp = false )
{

    // Don't send keys while blocked.
    if( blockState == 1 ){

        return;

    }

    if( keyCode == shiftKeyCode ){

        if( keyUp ){

            shiftIsDown = false;

        }else{

            shiftIsDown = true;

        }

    }

    CGEventSourceRef source = CGEventSourceCreate( kCGEventSourceStateHIDSystemState );
    CGEventRef keyEvent = CGEventCreateKeyboardEvent( source, (CGKeyCode) keyCode, !keyUp );

    if( shiftIsDown ){

        // Use Shift flag
        CGEventSetFlags( keyEvent, CGEventGetFlags( keyEvent ) | kCGEventFlagMaskShift );

    }else{

        // Use all existing flag except Shift
        CGEventSetFlags( keyEvent, CGEventGetFlags( keyEvent ) & ~kCGEventFlagMaskShift );

    }

    CGEventPost( kCGHIDEventTap, keyEvent );

    CFRelease( keyEvent );
    CFRelease( source );

}
于 2012-05-23T01:45:11.260 回答