Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我能';我不知道如何使用SendMessage或PostMessage调用_C#_Keypress_Handler_Sendmessage_Postmessage - Fatal编程技术网

C# 我能';我不知道如何使用SendMessage或PostMessage调用

C# 我能';我不知道如何使用SendMessage或PostMessage调用,c#,keypress,handler,sendmessage,postmessage,C#,Keypress,Handler,Sendmessage,Postmessage,我需要在第三方应用程序中模拟按键。假设我有一个C#应用程序,需要向计算器应用程序发送一个“8”。我不能使用.Net的SendKeys或win32 api的keybd_事件,因为它们都要求窗口是最活跃的窗口,而我的情况并非如此 所以我只剩下sendMessage和postMessage两个电话了。在过去的三个小时里,我一直在努力取得一些成果,但现在我完全没有希望了 我有以下资料: [DllImport("user32.dll")] public static extern

我需要在第三方应用程序中模拟按键。假设我有一个C#应用程序,需要向计算器应用程序发送一个“8”。我不能使用.Net的SendKeys或win32 api的keybd_事件,因为它们都要求窗口是最活跃的窗口,而我的情况并非如此

所以我只剩下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访问它,但运气不好)。并没有错误或异常,但它在计算器中并没有任何作用


我也用记事本做了同样的尝试,但没有任何改变。

你有可能在64位机器上运行这个吗?如果是这样的话,我相信所有那些实际上是hWnds的“int”值(发送/发布的第一个参数,FindWindow返回的值)都需要是IntPtr


经过进一步检查,SendMessage和PostMessage的第1、第3和第4个参数都应该是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);

关于CodeProject,有一篇很好的文章:

SendKeys实际上是正确的想法,但是您需要获得目标窗口的HWND(窗口句柄)。演示如何有效地使用SendKeys,但不演示如何发现除最顶部窗口之外的任何其他窗口的HWND


将这两种技术结合起来,使用CodeProject示例定位您要定位的应用程序的HWND,然后使用MSDN文章使用SendKeys将按键(或鼠标事件)发送到目标应用程序。

不直接回答您的问题,但是
SendMessage
PostMessage
之间的区别在于
Send
是一个阻塞调用,
Post
立即返回(在接收应用程序处理它之前)

MSDN解释了区别:

另外,如果您在vista上,但不在.NET 3.0上,这也可能是一个问题:

已为.NET Framework 3.0更新SendKeys类,以便在运行于Windows Vista的应用程序中使用它。Windows Vista增强的安全性(称为用户帐户控制或UAC)阻止以前的实现按预期工作


因为它是记事本窗口中的编辑子窗口。您应该将消息发送到正确的子窗口。这是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);
    }
}
#包括
#包括
真空总管(真空){
STARTUPINFO si;
处理信息;
HWND mainwnd,editwnd;
字符c;
si.cb=sizeof(si);
si.lpReserved=NULL;
si.lpDesktop=NULL;
si.lpTitle=NULL;
si.dwFlags=0;
si.cbReserved2=0;
si.lpReserved2=NULL;
如果(!CreateProcess(“c:\\windows\\notepad.exe”,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)){
printf(“无法运行应用程序”);
返回;
}
WaitForInputIdle(pi.hProcess,无限);
mainwnd=FindWindow(NULL,“无标题的记事本”);
如果(!mainwnd){
printf(“未找到主窗口”);
返回;
}
editwnd=FindWindowEx(mainwnd,NULL,“编辑”,“编辑”);
如果(!editwnd){
printf(“未找到编辑窗口”);
返回;
}

对于(c='1';c这里的解决方案帮助了我,但我不得不编辑它,而且它现在更短了:

还有一个有用的虚拟密钥代码列表


哇。真管用?说一个幸运的猜测吧。我甚至从未使用过这两种特定的win32方法。你能检查一下我最后的答案吗?:)windows中所有内容的可能重复都会显示消息-因此,当你移动鼠标时,你的应用程序可能会收到鼠标移动消息、按下按钮、鼠标按下消息。现在,看看上面,最明显的部分是,你确定它找到了你的计算器吗??
        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);

        private void button1_Click(object sender, EventArgs e)
        {
            const int WM_SYSKEYDOWN = 0x0104;

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

            PostMessage(WindowToFind, WM_SYSKEYDOWN, ((int)Keys.NumPad7), 0);
        }