7

サードパーティのアプリケーションでキープレスをシミュレートする必要があります。電卓アプリケーションに "8" を送信する必要がある C# アプリケーションがあるとします。.Net の SendKeys または win32 api の keybd_event を使用することはできません。どちらもウィンドウを一番上にアクティブにする必要があるためです。これは私の状況では当てはまりません。

そのため、sendMessage と postMessage の呼び出しが残ります。過去 3 時間、何らかの結果を得ようと努力してきましたが、今は完全に絶望的です。

私は次のものを持っています:

        [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);
    }

ご覧のとおり、電卓との通信を 4 回試行します。sendMessage と PostMessage の両方を使用してウィンドウを閉じ、キーを送信する 7. 何も機能しません。FindWindow メソッドが機能するため、アプリのハンドラーを取得できます (プロセスを自分で起動して、process.MainWindowHandler でアクセスしようとしましたが、うまくいきませんでした)。エラーや例外はありませんが、電卓では何もしません。

メモ帳でもまったく同じことを試しましたが、何も変わりませんでした。

4

5 に答える 5

12

これを64ビットマシンで実行している可能性はありますか? もしそうなら、実際には hWnds (Send/Post への最初の引数、FindWindow からの戻り値) であるすべての「int」値は IntPtr である必要があると思います。


もう少し確認すると、SendMessage と PostMessage の両方で、1 番目、3 番目、4 番目のパラメーターは int ではなく IntPtr である必要があるようです (これらすべての戻り値も同様です)。

したがって、正しい署名は次のようになります。

[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);
于 2009-04-30T19:07:42.577 に答える
3

CodeProject にこれに関する良い記事があります: http://www.codeproject.com/KB/cs/SendKeys.aspx

SendKeys は実際には正しい考えですが、ターゲット ウィンドウの HWND (ウィンドウ ハンドル) を取得する必要があります。この MSDN サンプルは、SendKeys を効果的に使用する方法を示していますが、最上位ウィンドウ以外の HWND を検出する方法は示していません。

CodeProject の例を使用してターゲットにするアプリケーションの HWND を特定し、MSDN の記事を使用して SendKeys を使用してキー ストローク (またはマウス イベント) をターゲット アプリケーションに送信します。

于 2009-04-30T19:19:09.633 に答える
2

SendMessage直接の質問ではありませんが、との違いPostMessageSendブロッキング呼び出しであり、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 と呼ばれます) により、以前の実装が期待どおりに機能しなくなります。

于 2009-04-30T19:23:11.323 に答える
1

メモ帳ウィンドウ内の Edit Child ウィンドウだからです。右側の子ウィンドウにメッセージを送信する必要があります。これは 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);
    }
}
于 2010-10-04T13:30:22.923 に答える