【问题标题】:I can't understand how to use SendMessage or PostMessage calls我不明白如何使用 SendMessage 或 PostMessage 调用
【发布时间】:2026-01-23 21:35:01
【问题描述】:

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

所以剩下的就是调用 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 访问它,但没有运气)。没有错误或异常,但它在计算器中什么也不做。

我也用记事本尝试了完全相同的东西,也没有任何改变。

【问题讨论】:

  • Simulating Key Press c#的可能重复
  • windows 中的所有内容都运行消息 - 因此,当您移动鼠标时,您的应用程序可能会收到鼠标移动消息、按下按钮、鼠标按下消息。现在,看上面,明显的部分是你确定它找到了你的计算器??

标签: c# keypress handler sendmessage postmessage


【解决方案1】:

这里的解决方案帮助了我但是我不得不编辑它,而且它现在更短了:

还有here 一个有用的虚拟键代码列表

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

【讨论】:

    【解决方案2】:

    你有没有机会在 64 位机器上运行它?如果是这样,我相信所有那些实际上是 hWnds 的“int”值(Send/Post 的第一个参数,FindWindow 的返回值)都需要是 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);
    

    【讨论】:

    • 哇。那行得通吗?谈论一个幸运的猜测。我什至从未使用过这两种特殊的 win32 方法。
    • 你能检查我的最后一个答案吗? :)
    【解决方案3】:

    CodeProject 上有一篇很好的文章: http://www.codeproject.com/KB/cs/SendKeys.aspx

    SendKeys其实是正确的思路,但是需要获取目标窗口的HWND(窗口句柄)。 This MSDN sample 展示了如何有效地使用 SendKeys,但没有展示如何发现除最顶层窗口之外的任何内容的 HWND。

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

    【讨论】:

      【解决方案4】:

      不是直接你的问题,而是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)会阻止以前的实现按预期工作。

      【讨论】:

        【解决方案5】:

        因为它是记事本窗口内的一个编辑子窗口。您应该将消息发送到右侧子窗口。这是 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);
            }
        }
        

        【讨论】: