• C#根据句柄改变窗体控件值


    需求是这样,有个程序界面我们需要通过自己的程序持续输入数据,界面如图。

    可以获得控件的句柄而用钩子写入值。这里需要用到spy++工具。在VS的工具下有个spy++工具,打开如下图

    通过这个工具可以获得窗体的句柄,当然这里获得的句柄只能用于测试,因为.net开发的程序窗体每次打开句柄都会变,都需要重新获得。这个工具的用处在于找一个控件的前一句柄控件和后一句柄控件。

    一、引用

    //寻找目标进程窗口       
    [DllImport("USER32.DLL")]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("USER32.DLL", EntryPoint = "FindWindowEx", SetLastError = true)]
    public static extern IntPtr FindWindowEx(IntPtr hwndParent, uint hwndChildAfter,string lpszClass, string lpszWindow);
    //设置进程窗口到最前       
    [DllImport("USER32.DLL")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);
    //模拟键盘事件         
    [DllImport("USER32.DLL")]
    public static extern void keybd_event(Byte bVk, Byte bScan, Int32 dwFlags, Int32 dwExtraInfo);
    public delegate bool CallBack(IntPtr hwnd, int lParam);
    [DllImport("USER32.DLL")]
    public static extern int EnumChildWindows(IntPtr hWndParent, CallBack lpfn, int lParam);
    //给CheckBox发送信息
    [DllImport("USER32.DLL", EntryPoint = "SendMessage", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern int SendMessage(IntPtr hwnd, UInt32 wMsg, int wParam, int lParam);
    //给Text发送信息
    [DllImport("USER32.DLL", EntryPoint = "SendMessage")]
    private static extern int SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, string lParam);
    [DllImport("USER32.DLL")]
    public static extern IntPtr GetWindow(IntPtr hWnd, int wCmd);
    
    

    二、方法

    公共方法

    /// <summary>
    /// 查找窗体上控件句柄
    /// </summary>
    /// <param name="hwnd">父窗体句柄</param>
    /// <param name="lpszWindow">控件标题(Text)</param>
    /// <param name="bChild">设定是否在子窗体中查找</param>
    /// <returns>控件句柄,没找到返回IntPtr.Zero</returns>
    private static IntPtr FindWindowEx(IntPtr hwnd, string lpszWindow, bool bChild)
    {
        IntPtr iResult = IntPtr.Zero;
        // 首先在父窗体上查找控件
        iResult = FindWindowEx(hwnd, 0, null, lpszWindow);
        // 如果找到直接返回控件句柄
        if (iResult != IntPtr.Zero) return iResult;
        // 如果设定了不在子窗体中查找
        if (!bChild) return iResult;
        // 枚举子窗体,查找控件句柄
        int i = EnumChildWindows(
        hwnd,
        (h, l) =>
        {
            IntPtr f1 = FindWindowEx(h, 0, null, lpszWindow);
            if (f1 == IntPtr.Zero)
                return true;
            else
            {
                iResult = f1;
                return false;
            }
        },
        0);
        // 返回查找结果
        return iResult;
    }
    
    /// <summary>
    /// 输入回车
    /// </summary>
    private static void PrintEnter()
    {
        keybd_event(Convert.ToByte(13), 0, 0, 0);
        keybd_event(Convert.ToByte(13), 0, 2, 0);
    }
    

    获得窗体句柄

    IntPtr wcHandle = FindWindow(null, "窗体名称");
    if (wcHandle != IntPtr.Zero)
    {
        //设置游戏窗口到最前
        SetForegroundWindow(wcHandle);
    }
    

    获得有Title的控件句柄

    uint BM_GETCHECK = 0xF0;
    uint BST_CHECKED = 0xF1;
    
    IntPtr weightIntPtr = FindWindowEx(wcHandle, "输入重量[&H]", true);
    if (weightIntPtr != IntPtr.Zero)
    {
        //获得Checkbox值
        int i = SendMessage(weightIntPtr, BM_GETCHECK, 0, 0);
        //更改CheckBox值
        SendMessage(weightIntPtr, BST_CHECKED, 1, 0);
    }
    

    获得没Title的控件句柄

    public enum WindowSearch
    {
        GW_HWNDFIRST = 0, //同级别第一个
        GW_HWNDLAST = 1, //同级别最后一个
        GW_HWNDNEXT = 2, //同级别下一个
        GW_HWNDPREV = 3, //同级别上一个
        GW_OWNER = 4, //属主窗口
        GW_CHILD = 5 //子窗口}获取与指定窗口具有指定关系的窗口的句柄 
    }
    IntPtr waybill = GetWindow(waybillIntPtr, (int)WindowSearch.GW_HWNDNEXT);
    SendMessage(waybill, WM_SETTEXT, IntPtr.Zero, waybillValue);
    

    这里完成了我们的需求,改变了窗体中选择框和Text文本框的值。

  • 相关阅读:
    Apache Flink 1.12.1发布
    flink 修改web页面刷新时间
    flink 支持的sql 方言
    flink sql 读取hive 表报错
    Typora配置正文、目录、侧边大纲中的标题自动编号
    滴滴开源Logi-KafkaManager 一站式Kafka监控与管控平台
    建立 nfs 服务器
    Linux 设备驱动的第一个例子 。
    备份.vimrc
    shell编程实例
  • 原文地址:https://www.cnblogs.com/kaoleba/p/6183151.html
Copyright © 2020-2023  润新知