C#实现操作Windows窗口句柄:常用窗口句柄相关API、Winform中句柄属性和Process的MainWindowHandle问题【窗口句柄总结之三】

简介: 本篇主要介绍一些与窗口句柄相关的一些API,比如设置窗口状态、当前激活的窗口、窗口客户区的大小、鼠标位置、禁用控件等,以及介绍Winform中的句柄属性,便于直接获取控件或窗体句柄,以及不推荐...

本篇主要介绍一些与窗口句柄相关的一些API,比如设置窗口状态、当前激活的窗口、窗口客户区的大小、鼠标位置、禁用控件等,以及介绍Winform中的句柄属性,便于直接获取控件或窗体句柄,以及不推荐使用C#自带的ProcessMainWindowHandle获取句柄的原因...

HWND窗口句柄其他的一些API

ShowWindow操作窗口状态(最大化、最小化、正常大小、关闭窗口)

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);

nCmdShow参数表示窗体状态,其常见的取值含义为:

  • 0 —— SW_HIDE 隐藏窗口,并激活其他窗口
  • 1 —— SW_SHOWNORMAL/SW_NORMAL 激活并正常大小显示窗口
  • 2 —— SW_SHOWMINIMIZED 最小化窗口
  • 3 —— SW_SHOWMAXIMIZED/SW_MAXIMIZE 最大化窗口
  • 4 —— SW_SHOWNOACTIVATE 显示但不激活

更多的其它取值请查看官方文档中的介绍。

获取当前激活的正在工作的窗口句柄(获取当前活动窗口句柄)

返回值有可能为null

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetForegroundWindow();

判断窗口状态

/// <summary>
/// 当前窗口是否最小化
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsIconic(IntPtr hWnd);
/// <summary>
/// 当前窗口是否最大化
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
[DllImport("user32.dll")]
public static extern bool IsZoomed(IntPtr hWnd);
/// <summary>
/// 判断窗口是否可见
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
[DllImport("user32")]
public static extern bool IsWindowVisible(IntPtr hWnd);

设置窗口标题Title

[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int SetWindowText(IntPtr hWnd, string title);

获取窗口客户区大小

[DllImport("user32.dll")]
private static extern bool GetClientRect(IntPtr hwnd, out LPRECT lpRect);
/// <summary>
/// 获取窗口客户区大小
/// </summary>
/// <param name="hwnd"></param>
/// <returns></returns>
public static Rectangle GetClientRect(IntPtr hwnd)
{
    LPRECT rect = default;
    GetClientRect(hwnd, out rect);
    return new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
}

获取鼠标坐标

/// <summary>
/// 获取鼠标坐标
/// </summary>
/// <param name="pt"></param>
/// <returns></returns>
[DllImport("user32.dll", EntryPoint = "GetCursorPos")]
public static extern bool GetCursorPos(out Point pt);

获取指定坐标位置的窗体

/// <summary>
/// 获取指定位置所在的窗口句柄
/// </summary>
/// <param name="pt"></param>
/// <returns></returns>
[DllImport("user32.dll", EntryPoint = "WindowFromPoint")]
public static extern IntPtr WindowFromPoint(Point pt);

获取鼠标指向的窗体

/// <summary>
/// 获取鼠标位置的窗体
/// </summary>
/// <returns></returns>
public static IntPtr WindowFromCursor()
{
    if (GetCursorPos(out Point pt))
    {
        return WindowFromPoint(pt);
    }
    return IntPtr.Zero;
}

移动或调整窗体大小

/// <summary>
/// 移动窗体、调整窗体大小
/// </summary>
/// <param name="hWnd"></param>
/// <param name="X">新位置</param>
/// <param name="Y">新位置</param>
/// <param name="nWidth">新大小</param>
/// <param name="nHeight">新大小</param>
/// <param name="bRepaint">是否重新渲染客户区,推荐始终为true</param>
/// <returns></returns>
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint=true);

使变灰的禁用控件可用

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnableWindow(IntPtr hWnd, bool bEnable);

Winform中使用窗口句柄

Handle属性

窗体或控件的Handle属性,可以直接获取对应的窗口句柄。

var frmHwnd = this.Handle;

var btnHwnd = button1.Handle;

获取某控件在Windows中的类名

Win 32 API 中窗口句柄的操作,很多有窗口或控件句柄的类名 ClassName这一项,比如 GetClassName API用于获取句柄的类名。

窗口(控件)句柄的类名是Windows系统中的类名,并不是winform/WPF内部C#的控件或元素类名,这一点要注意。

下面以一个Button按钮为例,通过属性button1.Handle句柄,获取其对应的类名GetClassName

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hwnd, StringBuilder lpClassName, int nMaxCount);

private void button1_Click(object sender, EventArgs e)
{
    int nret;
    var className = new StringBuilder(255);
    nret = GetClassName(button1.Handle, className, className.Capacity);
    if (nret != 0)
        MessageBox.Show("ClassName is " + className.ToString());
    else
        MessageBox.Show("Error getting window class name");
}

获取Winform中Button控件的C#类名对应的window class name(GetClassName):WindowsForms10.BUTTON.app.0.xxx

通过Process进程类获取窗口句柄及相关信息【不推荐】

进程的MainWindowHandleMainWindowTitle

进程的MainWindowHandle属性可以直接获取主窗口句柄;MainWindowTitle属性为窗口的标题。

如下,根据窗口标题模糊查找窗口句柄。

/// <summary>
/// 根据窗口标题查找窗口句柄【不推荐】
/// </summary>
/// <param name="puzze_title">窗口标题,支持模糊查询可指定标题的一部分;为null则返回所有句柄</param>
/// <returns></returns>
public List<IntPtr> FindHwndsByTitle(string puzze_title=null)
{
    //按照窗口标题来寻找窗口句柄
    Process[] ps = Process.GetProcesses();
    var intptrs = new List<IntPtr>();
    foreach (Process p in ps)
    {
        if (puzze_title != null && !p.MainWindowTitle.Contains(puzze_title))
        {
            continue;
        }
        intptrs.Add(p.MainWindowHandle);
    }
    return intptrs;
}

MainWindow的问题

Process.MainWindowHandle属性是合成的(synthetic),Windows中并没有main window相关的正式概念;

一个程序可以创建多个可见的顶层窗口,对于Windows而言,它们都是相同的。

因此,推荐使用EnumWindows获取(顶层)窗口,即之前介绍到的FindAllWindows方法。

参考

相关文章
|
25天前
|
设计模式 开发框架 安全
C# 一分钟浅谈:GraphQL API 与 C#
本文介绍了 GraphQL API 的基本概念及其优势,并通过 C# 实现了一个简单的 GraphQL 服务。GraphQL 是一种高效的 API 查询语言,允许客户端精确请求所需数据,减少不必要的数据传输。文章详细讲解了如何使用 `GraphQL.NET` 库在 C# 中创建和配置 GraphQL 服务,并提供了常见问题的解决方案和代码示例。
42 4
|
2月前
|
开发框架 .NET API
RESTful API 设计与实现:C# 开发者的一分钟入门
【10月更文挑战第5天】本文从零开始,介绍了如何使用 C# 和 ASP.NET Core 设计并实现一个简单的 RESTful API。首先解释了 RESTful API 的概念及其核心原则,然后详细说明了设计 RESTful API 的关键步骤,包括资源识别、URI 设计、HTTP 方法选择、状态码使用和错误处理。最后,通过一个用户管理 API 的示例,演示了如何创建项目、定义模型、实现控制器及运行测试,帮助读者掌握 RESTful API 的开发技巧。
77 7
|
3月前
|
SQL API 定位技术
基于C#使用winform技术的游戏平台的实现【C#课程设计】
本文介绍了基于C#使用WinForms技术开发的游戏平台项目,包括项目结构、运行截图、实现功能、部分代码说明、数据库设计和完整代码资源。项目涵盖了登录注册、个人信息修改、游戏商城列表查看、游戏管理、用户信息管理、数据分析等功能。代码示例包括ListView和ImageList的使用、图片上传、图表插件使用和SQL工具类封装,以及高德地图天气API的调用。
基于C#使用winform技术的游戏平台的实现【C#课程设计】
|
2月前
|
设计模式 程序员 C#
C# 使用 WinForm MDI 模式管理多个子窗体程序的详细步骤
WinForm MDI 模式就像是有超能力一般,让多个子窗体井然有序地排列在一个主窗体之下,既美观又实用。不过,也要小心管理好子窗体们的生命周期哦,否则一不小心就会出现一些意想不到的小bug
196 0
|
2月前
|
API C# Windows
【C#】在winform中如何实现嵌入第三方软件窗体
【C#】在winform中如何实现嵌入第三方软件窗体
132 0
|
2月前
|
C# 开发工具 Windows
C# 获取Windows系统信息以及CPU、内存和磁盘使用情况
C# 获取Windows系统信息以及CPU、内存和磁盘使用情况
57 0
|
2月前
|
数据可视化 程序员 C#
C#中windows应用窗体程序的输入输出方法实例
C#中windows应用窗体程序的输入输出方法实例
54 0
|
2月前
|
安全 API C#
C# 如何让程序后台进程不被Windows任务管理器强制结束
C# 如何让程序后台进程不被Windows任务管理器强制结束
71 0
|
2月前
|
API C#
C#实现Winform程序右下角弹窗消息提示
C#实现Winform程序右下角弹窗消息提示
117 0
|
2月前
|
API C#
异步轮询 Web API 的实现与 C# 示例
异步轮询 Web API 的实现与 C# 示例
87 0