如何从我的全局热键中粘贴其他应用程序

时间:2013-11-23 23:32:26

标签: objective-c macos macos-carbon

我编写了一个小型生产力工具,可以通过剪贴板进行一些字符串操作。

它当前正在注册一个热键,它会拉入剪贴板文本,处理它,然后将结果转储回剪贴板。

我在CMD + SHIFT + V上安装了这个

目前你需要从另一个apppiclation做的是复制(CMD + C),然后激活我的hothandler(CMD + SHIFT + V),然后你必须用(CMD + V)将它粘贴回原始应用程序

如果可能的话,我想删除第三步,所以我的hothandler会以某种方式告诉要粘贴的活动应用程序。

有任何建议怎么做?

我的代码(减去实际无聊的文本替换内容)是这样的:

请注意,这需要热键处理程序的碳框架

[编辑:]我从this answer on stack overflow借用了代码来获取热键处理程序代码。

AppDelegate.h

#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>
#import <Carbon/Carbon.h>

@interface AppDelegate : NSObject <NSApplicationDelegate>  {

    EventHotKeyRef  hotKeyRef;
}

@property (assign) IBOutlet NSWindow *window;
-(IBAction) checkClipboard:(id) sender ;

@end

AppDelegate.m

#import "AppDelegate.h"
//#import "NSString+cppMacros.h" // not relevant to question




OSStatus _AppDelegateHotKeyHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData) {
    AppDelegate *appDel = [[NSApplication sharedApplication] delegate];
    [appDel checkClipboard:nil];
    return noErr;
}

@implementation AppDelegate



- (void)installHotkey {

    if (!hotKeyRef) {
        EventHotKeyID   hotKeyId;
        EventTypeSpec   eventType;

        eventType.eventClass    = kEventClassKeyboard;
        eventType.eventKind     = kEventHotKeyPressed;

        InstallApplicationEventHandler(&_AppDelegateHotKeyHandler, 1, &eventType, NULL, NULL);

        hotKeyId.signature  = 'hotk';
        hotKeyId.id         = 1337;

        RegisterEventHotKey(kVK_ANSI_V, cmdKey + shiftKey, hotKeyId, GetApplicationEventTarget(), 0, &hotKeyRef);
        NSLog(@"_AppDelegateHotKeyHandler installed");

    }
}

-(void) uninstallHotkey {
    if (hotKeyRef) {
        UnregisterEventHotKey(hotKeyRef);
        hotKeyRef = nil;
        NSLog(@"_AppDelegateHotKeyHandler uninstalled");
    }

}



-(IBAction) checkClipboard:(id) sender {

    NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];


    NSArray *types = [NSArray arrayWithObjects:NSStringPboardType, nil];



    NSString *text = [pasteboard  stringForType:NSPasteboardTypeString];

    NSLog(@"clipboard input:%@",text);

    /* actual code is this: (not relevant to question)
     NSString *newText = [text isMacroEncoded] ? [text macroDecodedString] : [text macroEncodedString];
     */
    // demo code for question

    NSString *newText = [@"Pasted:" stringByAppendingString:text];


    [pasteboard declareTypes:types owner:self];

    [pasteboard setString:newText forType:NSStringPboardType];

    NSLog(@"clipboard output:%@",newText);

}


- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
    hotKeyRef = nil;
    [self installHotkey];
}

-(void) applicationWillTerminate:(NSNotification *)notification {
    [self uninstallHotkey];
}



@end

2 个答案:

答案 0 :(得分:4)

您不希望使用全局热键。您想编写应用程序以便它提供“服务”。请参阅Services Implementation Guide

您的服务可以通过键盘快捷键激活,可以是应用程序Info.plist中的默认配置,也可以是用户在“系统偏好设置”中配置的快捷键。

Cocoa负责从活动应用程序复制并在完成转换后粘贴到它中,因此这将处理第一步和第三步。

服务使用单独的粘贴板来传输数据,因此这也不会干扰一般(复制和粘贴)粘贴板的内容。

这是每个级别的优秀方法。


编辑以增加其他好处:

服务不会从活动应用中窃取键盘快捷键。

通过应用程序菜单和上下文菜单也可以使用服务。这使它可被发现。

答案 1 :(得分:1)

事实证明,有办法做我想做的事。

void pasteCurrent() {

    CGEventRef commandDown = CGEventCreateKeyboardEvent(NULL, kVK_Command, YES);
    CGEventRef VDown = CGEventCreateKeyboardEvent(NULL, kVK_ANSI_V, YES);

    CGEventRef VUp = CGEventCreateKeyboardEvent(NULL, kVK_ANSI_V, NO);
    CGEventRef commandUp = CGEventCreateKeyboardEvent(NULL, kVK_Command, NO);

    CGEventSetFlags(VDown,kCGEventFlagMaskCommand);
    CGEventSetFlags(VUp,kCGEventFlagMaskCommand);

    CGEventPost(kCGHIDEventTap, commandDown);
    CGEventPost(kCGHIDEventTap, VDown);
    CGEventPost(kCGHIDEventTap, VUp);
    CGEventPost(kCGHIDEventTap, commandUp);

    CFRelease(commandDown);
    CFRelease(VDown);
    CFRelease(VUp);
    CFRelease(commandUp);

}