C#遍历进程获取主窗口句柄

当我们启动一个程序,用 Process process = Process.Start(path);//path是程序的绝对路径

启动时,获取的process.Handle其实是进程的句柄,并不是窗口的句柄,而有时process.MainWindowHandle却等于0

此时就需要用枚举来获取启动进程的主窗口句柄了,代码如下

?
/// <summary>
    /// 用于枚举子窗体是的委托
    /// </summary>
    /// <param name="WindowHandle">窗体句柄</param>
    /// <param name="num">自定义</param>
    /// <returns></returns>
    public delegate bool EnumChildWindow(IntPtr WindowHandle, string num);
    /// <summary>
    /// 获取指定窗体的所有子窗体
    /// </summary>
    /// <param name="WinHandle">窗体句柄</param>
    /// <param name="ec">回调委托</param>
    /// <param name="name">自定义</param>
    /// <returns></returns>
    [DllImport( "User32.dll" )]
    public static extern int EnumChildWindows(IntPtr WinHandle, EnumChildWindow ecw, string name);
    /// <summary>
    /// 获取指定窗体的标题
    /// </summary>
    /// <param name="WinHandle">窗体句柄</param>
    /// <param name="Title">缓冲区取用于存储标题</param>
    /// <param name="size">缓冲区大小</param>
    /// <returns></returns>
    [DllImport( "User32.dll" )]
    public static extern int GetWindowText(IntPtr WinHandle, StringBuilder Title, int size);
    /// <summary>
    /// 获取窗体类型
    /// </summary>
    /// <param name="WinHandle">窗体句柄</param>
    /// <param name="Type">类型</param>
    /// <param name="size">缓冲区大小</param>
    /// <returns></returns>
    [DllImport( "user32.dll" )]
    public static extern int GetClassName(IntPtr WinHandle, StringBuilder Type, int size);
    /// <summary>
    /// 根据句柄获得进程id值
    /// </summary>
    /// <param name="handle">句柄</param>
    /// <param name="pid"></param>
    /// <returns></returns>
    [DllImport( "user32" )]
    private static extern int GetWindowThreadProcessId(IntPtr handle, out int pid);
IntPtr mainHwnd = IntPtr.Zero; //登录窗口句柄
string typeName = string .Empty; //启动程序的窗口标题
   /// <summary>
    /// 枚举窗体
    /// </summary>
    /// <param name="handle"></param>
    /// <param name="num"></param>
    /// <returns></returns>
    private bool EnumChild(IntPtr handle, string num)
    {
        StringBuilder title = new StringBuilder();
        //StringBuilder type = new StringBuilder();
        title.Length = 100;
        //type.Length = 100;
        GetWindowText(handle, title, 100); //取标题
        //GetClassName(handle, type, 100);//取类型
        if (title.ToString() == typeName)
        {
            mainHwnd = handle;
            return false ;
        }
        return true ;
    }
//代码调用
pubilc boolTest()
{
       FileVersionInfo myFileVersion = FileVersionInfo.GetVersionInfo(path);
        typeName = myFileVersion.ProductName; //获取程序产品名称
int waitTime = 0;
     while ( true )
            {
              
                EnumChildWindow ecw = new EnumChildWindow(EnumChild);
                EnumChildWindows(mainWindowHandle, ecw, "" );
                GetWindowRect(mainHwnd.ToInt32(), ref rectMain);
                int pid = 0;
                GetWindowThreadProcessId(mainHwnd, out pid);
                //rectMain.Height - rectMain.Y < 300说明是登录窗口
                if (mainHwnd != IntPtr.Zero && process.Id == pid && rectMain.Height - rectMain.Y < 300) //276               
                    break ;
                waitTime++;
                //30秒没打开程序,登录失败
                if (waitTime >= 30)
                    return false ;
                Thread.Sleep(1000);
            }
return true ;
}
 
**********************************************************
在C#中使用API回调函数的方法

就以EnumChildWindowsEnumChildProc为例子:

首先要声明EnumChildProc 为一个回调函数

public delegate bool EnumChildProc(int hwnd, IntPtr lParam);

delegateC#中的回调类型,相当于C++里面的CALLBACK,这样就可以在下面声明EnumChildWindows的时候在参数中使用EnumChildProc来作为一个类型。

声明调用user32.dll中的EnumChildWindows,如下:

[DllImport("user32.dll", EntryPoint = "EnumChildWindows")]

public static extern bool EnumChildWindows(int hwndParent, EnumChildProc EnumFunc, IntPtr lParam);

定义一个和EnumChildProc返回值和参数一样的函数:

bool EnumCP(int hwnd,IntPtr lParam)

        {

            System.Text.StringBuilder sbClassName = new StringBuilder(255);

            GetClassName(hwnd, sbClassName, 255);

            if ("Static" == sbClassName.ToString())

            {                  

                return false;

            }

            return true;

        }

这时就可以使用EnumChildWindows(hwnd, EnumCP, IntPtr.Zero); EnumCP返回true的时候,EnumChildWindow继续进行枚举窗口。当EnumCP返回false的时候,EnumChildWindow停止进行枚举窗口。

 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值