2010-05-13 40 views
4

編輯 - 沒有得到太多的輸入,所以這裏是瘦。我將鍵盤事件發佈到PSN。然後我切換到另一個窗口,發佈更多事件(這次是會話級別)並切換回第一個窗口。當我再次開始發佈到PSN時,沒有任何反應。直到我移動鼠標或滾輪。爲什麼會出現這種情況,我該如何解決它(如果不解決的話)?發佈CGEvent到PSN時發生奇怪的行爲

ORIGINAL - 如果我建立了一個將某些鍵盤事件發佈到PSN的循環,我發現除了首次啓動時它工作正常。只有當我用鼠標手動進行操作時纔會發佈事件 - 即使只是稍微移動一下。如果有幫助,以下是詳情。

外部應用程序有一個文本行列表框,我通過發佈複製命令(並檢查粘貼板)來閱讀。不幸的是,這是我獲得此文本的唯一方法。

有時候,應用程序會將焦點從我可以檢測到的列表中拉出來。發生這種情況時,返回焦點的最可靠方法是發送鼠標事件以單擊列表正上方的文本字段,然後發送「標籤」鍵盤事件以將焦點移到列表中。

所以在啓動時,循環運行良好,滾動列表並複製文本。當焦點移開時,它的檢測效果良好,並且發送事件以將焦點移回列表。但似乎沒有發生。循環繼續檢測焦點已經改變,但事件只有在我移動鼠標時才起作用。甚至只是使用滾輪。奇怪。

第一次發生這種情況時,它可以正常工作 - 每次焦點移動時,PSN事件都會切換回來,而無需執行任何操作。

下面是在循環運行的代碼 - 驗證爲工作:

//copy to pasteboard - CMD-V 
e3 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)8, true); 
CGEventSetFlags(e3, kCGEventFlagMaskCommand); 
CGEventPostToPSN(&psn, e3); 
CFRelease(e3); 
e4 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)8, false); 
CGEventPostToPSN(&psn, e4); 
CFRelease(e4); 

//move cursor down 
e1 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)125, true); 
CGEventPostToPSN(&psn, e1); 
CFRelease(e1); 
e2 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)125, false); 
CGEventPostToPSN(&psn, e2); 
CFRelease(e2); 

這裏的地方我切換焦點,也工作(當第一次需要時除外):

//click in text input box - point is derived earlier 
e6 = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, point, 0); 
CGEventPostToPSN(&psn, e6); 
CFRelease(e6); 
e7 = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp, point, 0); 
CGEventPostToPSN(&psn, e7); 
CFRelease(e7); 

//press tab key to move to chat log table 
CGEventRef e = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)48, true); 
//CGEventPost(kCGSessionEventTap, e); 
CGEventPostToPSN(&psn, e); 
CFRelease(e); 
CGEventRef e11 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)48, false); 
CGEventPostToPSN(&psn, e11); 
CFRelease(e11); 
+0

你如何在窗口之間切換,並且都在同一個應用程序中的窗口? – drawnonward 2010-05-28 03:15:37

+0

這兩個窗口都在同一個應用程序中。我正在使用 AXUIElementSetAttributeValue(myWindow,kAXMainAttribute,kCFBooleanTrue); – 2010-06-01 05:08:14

回答

2

嘿,我知道這不是你想要聽到的,但是applescript對於這種事情更有效 - 通過發佈複製命令來讀取文本字段,通過將點擊事件發送到附近的項目然後發送標籤事件來進行設置 - 這實際上不是最好的方式它。

模擬事件的問題在於生成它們不是整個故事。如果目標應用正確解釋它們,它們只會成爲「事件」。你知道目標應用程序是否是可可應用程序嗎?

例如,在您的第二位代碼中,您創建了4個事件。目標應用程序需要運行它的事件處理循環,您無法控制這些循環,並檢查排隊的事件。如果它這樣做,它會找到一個同時鼠標,鼠標,鍵,關鍵。你希望它把這些簡單事件解釋爲鼠標點擊,然後按鍵......但是誰會說呢?

您可能能夠得到這個加入到混合的潮紅事件隊列組合,讓目標應用來看,這是runloop工作,在一些暫停扔模擬事件之間,和擺弄事件時間戳 - 但它可能不會那麼可靠。

在AppleScript的,你可以通過

tell application "System Events" 
    tell process targetAppName 
    set frontmost to true 
    tell window named windowTitle 
     tell table 1 
     set value of attribute "AXFocused" to true 
     set txtField to first text field of row 3 
     return value of txtField 
     end tell 
    end tell 
    end tell 
end tell 

得到了其他應用表第3行的文字從一個可可應用程序,你可以執行字符串作爲一個AppleScript,你可以調用函數在不同的腳本,通變量,返回值等

+0

我無法在此上使用applescript。正如我所提到的,沒有其他辦法 - 我可以詳細說明爲什麼如果你困擾。謝謝你的信息。 – 2010-06-01 05:05:37

+1

是的,我很感興趣,我正在做類似的東西。只是爲了澄清..當我說使用Applescript - 我的意思是(或可能只是有容易的意思)從一個可可應用程序內。 – hooleyhoop 2010-06-01 09:51:44

+0

AppleScript在此沒有特權,System Events.app使用CGPostKeyboardEvent。 – 2012-02-23 13:31:15

1

不再創建一個空CGEventSourceRef事件的嘗試創建輸入源是這樣的:

CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); 

在此基礎上mailing list message,這似乎是成功使用CGEventCreateXXXEvent發佈事件的祕訣。谷歌搜索顯示,很多開發者都遇到了這個問題,但這是我找到的一個成功後,一個適當的CGEventSourceRef(而不是NULL)似乎是這個例子中的一個差異,而其他所有其他找到了。它解決了我發佈鍵盤事件的問題。