2010-04-19 49 views
1

我正在編寫一個應用程序,通過將突出顯示的文本複製到NSPasteboard的generalPasteboard中來對熱鍵作出響應。這裏環顧發送虛擬按鍵的解決方案之後,我發現這一點:How to send a "Cmd-C" keystroke to the active application in objective-c, or tell the application to do a copy operation?可可虛擬擊鍵疼痛

我試過的AppleScript建議用NSAppleScript:

NSLog(@"Hotkey Pressed"); 
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; 

NSAppleScript *playScript; 
playScript = [[NSAppleScript alloc] initWithSource:@"tell application \"System Events\" to keystroke \"c\" using command down"]; 

if([playScript isCompiled] == NO){ 
[playScript compileAndReturnError:nil]; 
} 

id exerror = [playScript executeAndReturnError:nil]; 

if(exerror == nil){ 
NSLog(@"Script Failed"); 
} 

它的工作原理,但只在第一次我打的熱鍵。隨後的每次擊中都不會抓住突出顯示的文字。 generalPasteboard仍包含與腳本再次運行之前相同的內容。在運行代碼之前清除generalPasteboard是沒有用的,因爲在嘗試讀取粘貼板內容時代碼失敗。這裏的日誌:

Pastify[16929:a0b] woooooooo! I'm being CALLED 
Pastify[16929:a0b] Hotkey Pressed 
Pastify[16929:a0b] Error loading /Library/ScriptingAdditions/Adobe Unit Types.osax/Contents/MacOS/Adobe Unit Types: dlopen(/Library/ScriptingAdditions/Adobe Unit Types.osax/Contents/MacOS/Adobe Unit Types, 262): no suitable image found. Did find: 
    /Library/ScriptingAdditions/Adobe Unit Types.osax/Contents/MacOS/Adobe Unit Types: no matching architecture in universal wrapper 
Pastify: OpenScripting.framework - scripting addition "/Library/ScriptingAdditions/Adobe Unit Types.osax" declares no loadable handlers. 
Pastify[16929:a0b] Size of copiedItems: 1 
Pastify[16929:a0b] Content of paste: 2010-04-19 03:41:04.355 Pastify[16929:a0b] woooooooo! I'm being CALLED 
Pastify[16929:a0b] Hotkey Pressed 
Pastify[16929:a0b] Size of copiedItems: 1 
Pastify[16929:a0b] Content of paste: 2010-04-19 03:41:04.355 Pastify[16929:a0b] woooooooo! I'm being CALLED 
Pastify[16929:a0b] Hotkey Pressed 
Pastify[16929:a0b] Size of copiedItems: 1 
Pastify[16929:a0b] Content of paste: 2010-04-19 03:41:04.355 Pastify[16929:a0b] woooooooo! I'm being CALLED 

所以我試了下建議的解決方案:

CFRelease(CGEventCreate(NULL)); 

CGEventRef event1, event2, event3, event4; 
event1 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)50, true); 
event2 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)8, true); 
event3 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)8, false); 
event4 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)50, false); 

CGEventPost(kCGHIDEventTap, event1); 
CGEventPost(kCGHIDEventTap, event2); 
CGEventPost(kCGHIDEventTap, event3); 
CGEventPost(kCGHIDEventTap, event4); 

上述應發送鍵擊命令+ C,但我得到的是嘟嘟聲,和剪貼板內容不變。

我很有智慧 - 任何人都可以啓發我對我失去的東西或指出我對我忽視的東西如此簡單嗎?

+3

不要傳遞'error:nil'。首先,它需要一個指向變量的指針,而不是一個指向對象的指針,所以正確的常量將是'NULL',而不是'nil'。更重要的是,不要阻止框架告訴你出了什麼問題。傳遞一個指向NSError *變量的指針,如果您嘗試執行的操作失敗,則至少記錄錯誤對象。 – 2010-04-19 17:51:25

回答

1

有沒有什麼不能爲此使用的服務的原因是什麼?

如果你真的想通過綜合事件來做到這一點,最好的辦法是發佈一個修改過的鍵盤事件而不是down/up - 查看這個問題了解更多細節。

Simulating key press events in Mac OS X

如果不工作,那麼,你知道在哪裏可以找到我:-)

+0

事實上,這確實有效:] 感謝您的幫助,暱稱! – bhargav 2010-05-14 10:46:04

1

只是一個想法... cmd-c技巧適用於最前面的應用程序。我懷疑當你第一次運行熱鍵來觸發正確的應用程序是最前面的時候,cmd-c可以工作,那麼你的應用程序就可以用紙板做一些事情。第二次運行時,熱鍵被激活,但以前的應用程序不再是最前面的,所以cmd-c不起作用。實質上,您正在將cmd-c發送給其他應用程序。也許你的應用程序已經到了前臺或其他。

要避免此問題,您需要確保您所定位的應用程序位於最前面。因此,首先您需要一些方法來找出最前面的應用程序,然後在執行cmd-c之前激活該應用程序。例如,在AppleScript的,如果我想運行在Safari CMD-C,我會用:

tell application "Safari" to activate 
tell application "System Events" to keystroke "c" using command down 
+0

此外,我注意到你「分配」了腳本,所以在代碼底部,如果你不使用垃圾收集,你需要釋放playScript:[playScript release]; – regulus6633 2010-04-19 10:16:49

0

我真的不明白,爲什麼你這樣做根本,但如果你想以確保您的事件進入特定過程,然後使用CGEventPost的「ToPSN」變體。