2009-04-30 92 views
6

我需要模擬第三方應用程序中的按鍵。假設我有一個C#應用程序需要向計算器應用程序發送一個「8」。我無法使用.Net的SendKeys或win32 API的keybd_event,因爲它們都需要窗口成爲最活躍的窗口,這在我的情況中不是這樣。我不明白如何使用SendMessage或PostMessage調用

因此,讓我與調用sendMessage和postMessage。我一直試圖在最近三個小時試圖獲得一些結果,但現在我完全沒有希望了。

我有以下幾點:

 [DllImport("user32.dll")] 
    public static extern int FindWindow(string lpClassName,string lpWindowName); 
    [DllImport("user32.dll")] 
    public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam); 

    [return: MarshalAs(UnmanagedType.Bool)] 
    [DllImport("user32.dll", SetLastError = true)] 
    public static extern bool PostMessage(int hWnd, uint Msg, int wParam, int lParam); 

    private void button1_Click(object sender, EventArgs e) 
    { 
     const int WM_KEYDOWN = 0x100; 
     const int WM_SYSCOMMAND = 0x018; 
     const int SC_CLOSE = 0x053; 

     int WindowToFind = FindWindow(null,"Calculator"); 

     int result = SendMessage(WindowToFind, WM_SYSCOMMAND, SC_CLOSE, 0); 
     Boolean result2 = PostMessage(WindowToFind, WM_SYSCOMMAND, SC_CLOSE, 0); 

     int result3 = SendMessage(WindowToFind, WM_KEYDOWN,((int)Keys.NumPad7), 0); 
     Boolean result4 = PostMessage(WindowToFind, WM_KEYDOWN, ((int)Keys.NumPad7), 0); 
    } 

正如你所看到的,我試圖四次與計算機進行通信。使用sendMessage和PostMessage關閉窗口併發送密鑰7.沒有任何工作。 FindWindow方法的工作原因是我得到了應用程序的處理程序(我甚至嘗試自己啓動該進程並使用process.MainWindowHandler訪問它,但沒有運氣)。沒有錯誤或例外,但它只是在計算器中無所作爲。

我也嘗試了與記事本完全相同的東西,沒有任何改變。

回答

11

你有機會在64位機器上運行它?如果是這樣,我相信所有那些實際上是hWnds(發送/發送的第一個參數,來自FindWindow的返回值)的'int'值都必須是IntPtr。


更多的檢查後,它看起來像兩個SendMessage函數和PostMessage的,第一,第三和第四個參數應IntPtr的,而不是INT(以及所有這些返回值)

所以,正確的簽名是:

[DllImport("user32.dll")] 
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName); 
[DllImport("user32.dll")] 
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 
[DllImport("user32.dll")] 
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 
+0

哇。那有效?談論一個幸運的猜測。我從來沒有使用過這兩種特殊的win32方法。 – 2009-04-30 19:11:57

3

有關於這一個很好的文章在CodeProject: http://www.codeproject.com/KB/cs/SendKeys.aspx

SendKeys實際上是正確的想法,但您需要獲取目標窗口的HWND(窗口句柄)。 This MSDN sample顯示如何有效地使用SendKeys,但不知道如何發現最頂層窗口以外的其他任何HWND。

結合這兩種技術,使用CodeProject示例找到要定位的應用程序的HWND,然後使用MSDN文章使用SendKeys將擊鍵(或鼠標事件)發送到目標應用程序。

2

不能直接你的問題,但SendMessagePostMessage之間的不同之處在於Send是一個阻塞調用,Post立即返回(前接收應用程序已經處理它)。

MSDN解釋的區別:http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx

另外,如果你是在Vista上,但不是在.NET 3.0中也可能是一個問題:

SendKeys類已更新爲.NET Framework 3.0以使其可用於在Windows Vista上運行的應用程序。 Windows Vista增強的安全性(稱爲用戶帳戶控制或UAC)可防止以前的實施按預期工作。

1

因爲它是記事本窗口內的編輯子窗口。您應該將消息發送到正確的子窗口。它是C中的一個工作示例:

#include <windows.h> 
#include <stdio.h> 

void main(void) { 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 
    HWND mainwnd,editwnd; 
    char c; 
    si.cb=sizeof(si); 
    si.lpReserved=NULL; 
    si.lpDesktop=NULL; 
    si.lpTitle=NULL; 
    si.dwFlags=0; 
    si.cbReserved2=0; 
    si.lpReserved2=NULL; 
    if(!CreateProcess("c:\\windows\\notepad.exe",NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) { 
     printf("Failed to run app"); 
     return; 
    } 
    WaitForInputIdle(pi.hProcess,INFINITE); 
    mainwnd=FindWindow(NULL,"Untitled - Notepad"); 
    if(!mainwnd) { 
     printf("Main window not found"); 
     return; 
    } 
    editwnd=FindWindowEx(mainwnd,NULL,"Edit",""); 
    if(!editwnd) { 
     printf("Edit window not found"); 
     return; 
    } 
    for(c='1';c<='9';c++) { 
     PostMessage(editwnd,WM_CHAR,c,1); 
     Sleep(100); 
    } 
} 
相關問題