模拟按键操作 C#

58

我想在我的C#程序中模拟按下 F5 键。当IE浏览器打开时,我希望能够自动刷新我的网站。

我该如何实现?


这是一个Web应用还是桌面应用? - ckramer
在这种情况下,我认为邦迪先生说得很对。 - ckramer
8个回答

83

这里有一个例子...

static class Program
{
    [DllImport("user32.dll")]
    public static extern int SetForegroundWindow(IntPtr hWnd);

    [STAThread]
    static void Main()
    {
        while(true)
        {
            Process [] processes = Process.GetProcessesByName("iexplore");

            foreach(Process proc in processes)
            {
                SetForegroundWindow(proc.MainWindowHandle);
                SendKeys.SendWait("{F5}");
            }

            Thread.Sleep(5000);
        }
    }
}

一个更好的,不那么烦人的...

static class Program
{
    const UInt32 WM_KEYDOWN = 0x0100;
    const int VK_F5 = 0x74;

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

    [STAThread]
    static void Main()
    {
        while(true)
        {
            Process [] processes = Process.GetProcessesByName("iexplore");

            foreach(Process proc in processes)
                PostMessage(proc.MainWindowHandle, WM_KEYDOWN, VK_F5, 0);

            Thread.Sleep(5000);
        }
    }
}

6
这个(特别是“更好”的那个)对我很有帮助,点赞。请看我的回答这里,以查看一个更复杂的例子,它还涉及修改键。 - Mike Fuchs

13
你可以使用Win32 API的FindWindowFindWindowEx来查找打开的浏览器窗口句柄,然后只需使用SendMessageWM_KEYDOWN发送按键消息。通常最简单的方法是将窗口标题传递给FindWindowEx,让它为您查找关联的窗口句柄。
如果您自己通过Process process对象启动浏览器进程,则可以使用process.MainWindowHandle代替调用FindWindowEx
当您要开始使用其他窗口时,Spy++是一个非常有用的工具。它基本上允许您了解另一个程序的UI元素层次结构。您还可以监视进入您正在监视的窗口的所有消息。我在这个帖子中有更多信息。
F5键的虚拟键码是:
const int VK_F5 = 0x74;

FindWindowEx 在 C# 中的 p/invoke 签名为:

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

您可以通过p/invoke(导入)Win32 API SendMessage 来实现:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

简单总结一下,你需要在你的C#代码中调用FindWindowEx函数,在类中的某个位置。 FindWindowEx将会返回一个窗口句柄。一旦你有了窗口句柄,你可以向窗口发送任何按键或者调用许多其他Win32 API来处理窗口句柄。甚至可以使用另一个调用FindWindowEx来查找子窗口。例如,你可以选择浏览器的编辑控件,然后更改它的文本。

如果一切都出了问题,你认为自己已经向窗口发送了正确的按键,那么可以使用spy++工具查看当你手动设置焦点到浏览器并手动按下时,发送到窗口的消息。


1
请您能否详细一些,因为我真的不知道如何使用Win32 API。 - Dani
1
SO线程的链接非常完美。但也许这个代码片段可以帮助 - http://snippets.dzone.com/posts/show/4070 - Reddog
1
@Dani:我添加了更多信息,但你可以使用lang:c#在Google代码搜索中查找更详细的示例。http://www.google.com/codesearch?q=lang:c%23+FindWindowEx&hl=en&btnG=Search+Code - Brian R. Bondy
这个回答非常需要一个有用的示例。你会怎样使用这个函数,它在哪里定义? SendMessage中的属性应该是什么? - emilaz

11

3
SendKeys未定义。 - Bengi Besçeli
添加对 System.Windows.Forms 的引用。 - Shiroy

7

可以使用mouse_event或keybd_event。虽然有人说不再建议使用它们,但是你根本不需要找到窗口。

using System;
using System.Runtime.InteropServices;

public class SimulatePCControl
{

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void keybd_event(uint bVk, uint bScan, uint dwFlags, uint dwExtraInfo);

private const int VK_LEFT = 0x25;

public static void LeftArrow()
{
    keybd_event(VK_LEFT, 0, 0, 0);
}

}

这里提供一些虚拟按键码的列表:http://www.kbdedit.com/manual/low_level_vk_list.html

另外,还有一些关于鼠标的:

using System.Runtime.InteropServices;
using UnityEngine;

public class SimulateMouseClick
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
//Mouse actions
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;

public static void Click()
{
    //Call the imported function with the cursor's current position
    uint X = (uint)0;
    uint Y = (uint)0;
    mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
    Debug.LogError("SIMULATED A MOUSE CLICK JUST NOW...");
}

//...other code needed for the application
}

5
简单的方法,将其添加到Main之前。
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

主函数/方法内的代码:

string className = "IEFrame";
string windowName = "New Tab - Windows Internet Explorer";
IntPtr IE = FindWindow(className, windowName);
if (IE == IntPtr.Zero)
{
   return;
}
SetForegroundWindow(IE);
InputSimulator.SimulateKeyPress(VirtualKeyCode.F5);

注意:

  1. 添加InputSimulator作为参考。下载请点击此处

  2. 使用WinSpy++查找类名和窗口名。下载请点击此处


5
另一种模拟按下F5键的替代方法是在Windows窗体应用程序中托管WebBrowser控件。您可以使用WebBrowser.Navigate方法加载您的网页,然后使用标准的Timer,在定时器的每个滴答声中重新导航到将重新加载页面的URL。

4

简单、短小,无需窗口焦点:

此外这里有一个有用的虚拟键代码列表

        [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;
            const int VK_F5 = 0x74;

            IntPtr WindowToFind = FindWindow(null, "Google - Mozilla Firefox");

            PostMessage(WindowToFind, WM_SYSKEYDOWN, VK_F5, 0);
        }

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接