zoukankan      html  css  js  c++  java
  • [C#] 使用Win32 API嵌入窗口,键盘、鼠标光标不响应问题解决

    
    
    /// <summary>
    /// 根据类名和窗口名称查找窗口
    /// </summary>
    /// <param name="lpClassName"></param>
    /// <param name="lpWindowName"></param>
    /// <returns></returns>
    [DllImport("user32.dll", EntryPoint = "FindWindow")]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
    /// <summary>
    /// 更改指定子窗口的父窗口
    /// </summary>
    /// <param name="hWndChild">子窗口句柄</param>
    /// <param name="hWndNewParent">父窗口句柄</param>
    /// <returns></returns>
    [DllImport("user32.dll", EntryPoint = "SetParent")]
    public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    
    /// <summary>
            /// 更改子,弹出窗口或顶级窗口的大小,位置和z顺序。
            /// </summary>
            /// <param name="hWnd">窗口句柄</param>
            /// <param name="hWndInsertAfter"></param>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="cx"></param>
            /// <param name="cy"></param>
            /// <param name="uFlags"></param>
            /// <returns></returns>
    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    public static extern Boolean SetWindowPos(IntPtr hWnd, Int32 hWndInsertAfter, Int32 x, Int32 y, Int32 cx, Int32 cy, UInt32 uFlags);
    
    /// <summary>
            /// 检索有关指定窗口的信息
            /// </summary>
            /// <param name="hWndChild"></param>
            /// <param name="nIndex"></param>
            /// <returns></returns>
    [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
    public static extern IntPtr GetWindowLong(IntPtr hWndChild, Int32 nIndex);
    
    /// <summary>
    /// 更改指定窗口的属性
    /// </summary>
    /// <param name="hWndChild"></param>
    /// <param name="nIndex"></param>
    /// <returns></returns>
    [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
    public static extern IntPtr SetWindowLong(IntPtr hWndChild, Int32 nIndex, IntPtr dwNewLong);
    
    /// <summary>
    /// 从窗口句柄中检索进程句柄
    /// </summary>
    /// <param name="hWnd">窗口句柄</param>
    /// <returns></returns>
    [DllImport("User32.dll", EntryPoint = "GetWindowThreadProcessId")]
    public static extern UInt32 GetWindowThreadProcessId(IntPtr hWnd, out UInt32 processId);/// <summary>
    /// 确定指定窗口的可见性状态
    /// </summary>
    /// <param name="hWnd"></param>
    /// <returns></returns>
    [DllImport("User32.dll", EntryPoint = "IsWindowVisible")]
    public static extern Boolean IsWindowVisible(IntPtr hWnd);
    
    
    SetParent函数不能更改窗口样式,而嵌入窗口需要给窗口添加WS_CHILD样式,并移除WS_POPUP样式,同时要去除边框、窗口标题,不能改变大小,使用SetWindowLong函数可修改窗口样式,使用SetWindowPos函数调整窗口大小,
    有个注意事项,刚拿到窗口句柄,就修改窗口样式会不起作用,需要等窗口显示了再调用,使用IsWindowVisible函数判断窗口是否显示,这比Thread.Sleep()更稳更快,使用FindWindow函数查找窗口句柄。

    /// <summary>
    /// 嵌入窗口
    /// </summary>
    /// <param name="process"></param>
    /// <param name="hWndNewParent"></param>
    /// <param name="size"></param>
    /// <param name="lpClassName"></param>
    /// <param name="lpWindowName"></param>
    /// <returns></returns>
    public static bool SetParentWindow(IntPtr hWndNewParent, System.Drawing.Size size, string lpClassName, string lpWindowName, out Process childProcess, Process process = null)
    {
        var ret = FindWindow(lpClassName, lpWindowName, out IntPtr hWndChild, out childProcess, process);
    
        if (ret)
        {
            SpinWait.SpinUntil(() =>
            {
                if (NativeMethods.IsWindowVisible(hWndChild))
                    return true;
                else
                {
                    Thread.Sleep(100);
                    return false;
                }
            });
    
            // 设为无边框窗口 + 嵌入窗口前,设为子窗口
            var style = NativeMethods.GetWindowLong(hWndChild, -16);
            style = (IntPtr)((style.ToInt32() | 0x40000000L) ^ (0x00C00000 | 0x00080000 | 0x00040000));
            NativeMethods.SetWindowLong(hWndChild, -16, style);
    
            // 改变窗口大小 
            NativeMethods.SetWindowPos(hWndChild, 0, 0, 0, size.Width, size.Height, 0);
    
            // 嵌入窗口
            return NativeMethods.SetParent(hWndChild, hWndNewParent) != IntPtr.Zero;
        }
    
        return false;
    }
    
    /// <summary>
    /// 查找指定窗口
    /// </summary>
    /// <param name="lpClassName"></param>
    /// <param name="lpWindowName"></param>
    /// <param name="process"></param>
    /// <returns></returns>
    public static bool FindWindow(string lpClassName, string lpWindowName, out IntPtr hWnd, out Process childProcess, Process process = null)
    {
        childProcess = null;
        var hWndChild = hWnd = IntPtr.Zero;
    
        // 查找指定窗口
        var ret = SpinWait.SpinUntil(() =>
        {
            if (process == null || process.MainWindowHandle != IntPtr.Zero)
                return (hWndChild = NativeMethods.FindWindow(lpClassName, lpWindowName)) != IntPtr.Zero;
    
            Thread.Sleep(100);
            return false;
        }, 5000);
    
        if (ret)
        {
            hWnd = hWndChild;
    
            // 查找窗口所在进程
            if (NativeMethods.GetWindowThreadProcessId(hWndChild, out UInt32 processId) != 0)
                childProcess = Process.GetProcessById((Int32)processId);
        }
    
        return ret;
    }
  • 相关阅读:
    看起来像一个输入框的input,实际上是有两个input
    Actions类的一些主要方法
    selenium通过WebDriverWait实现ajax测试,实现等页面元素加载完成
    如何判断新打开窗口是否需要切换
    鼠标悬停
    Selenium WebDriver使用IE浏览器
    Element should have been select but was input
    58同城Java面试
    2个线程ABAB或者BABA循环输出
    使多个线程循环输出099099
  • 原文地址:https://www.cnblogs.com/pumbaa/p/15133115.html
Copyright © 2011-2022 走看看