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方法。

参考

相关文章
|
22天前
|
人工智能 测试技术 API
Windows用户必备:Postman v11详细安装指南与API测试入门教程(附官网下载
Postman是全球领先的API开发与测试工具,支持REST、SOAP、GraphQL等协议调试。2025年最新版v11新增AI智能生成测试用例、多环境变量同步等功能,适用于前后端分离开发、自动化测试、接口文档自动生成及团队协作共享API资源。本文详细介绍Postman的软件定位、核心功能、安装步骤、首次配置、基础使用及常见问题解答,帮助用户快速上手并高效利用该工具进行API开发与测试。
|
3月前
|
Linux C# iOS开发
开源GTKSystem.Windows.Forms框架让C# Winform支持跨平台运行
开源GTKSystem.Windows.Forms框架让C# Winform支持跨平台运行
82 12
|
7月前
|
JSON API 数据处理
Winform管理系统新飞跃:无缝集成SqlSugar与Web API,实现数据云端同步的革新之路!
【8月更文挑战第3天】在企业应用开发中,常需将Winform桌面应用扩展至支持Web API调用,实现数据云端同步。本文通过实例展示如何在已有SqlSugar为基础的Winform系统中集成HTTP客户端调用Web API。采用.NET的`HttpClient`处理请求,支持异步操作。示例包括创建HTTP辅助类封装请求逻辑及在Winform界面调用API更新UI。此外,还讨论了跨域与安全性的处理策略。这种方法提高了系统的灵活性与扩展性,便于未来的技术演进。
350 2
|
7月前
|
开发框架 缓存 前端开发
基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求
基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求
|
3月前
|
存储 安全 编译器
学懂C#编程:属性(Property)的概念定义及使用详解
通过深入理解和使用C#的属性,可以编写更清晰、简洁和高效的代码,为开发高质量的应用程序奠定基础。
142 12
|
9月前
|
弹性计算 算法 安全
视觉智能开放平台产品使用合集之在Web应用和WinForm应用程序中调用API时,出现Web端能够成功调用而WinForm端调用失败,是什么原因
视觉智能开放平台是指提供一系列基于视觉识别技术的API和服务的平台,这些服务通常包括图像识别、人脸识别、物体检测、文字识别、场景理解等。企业或开发者可以通过调用这些API,快速将视觉智能功能集成到自己的应用或服务中,而无需从零开始研发相关算法和技术。以下是一些常见的视觉智能开放平台产品及其应用场景的概览。
|
6月前
|
SQL API 定位技术
基于C#使用winform技术的游戏平台的实现【C#课程设计】
本文介绍了基于C#使用WinForms技术开发的游戏平台项目,包括项目结构、运行截图、实现功能、部分代码说明、数据库设计和完整代码资源。项目涵盖了登录注册、个人信息修改、游戏商城列表查看、游戏管理、用户信息管理、数据分析等功能。代码示例包括ListView和ImageList的使用、图片上传、图表插件使用和SQL工具类封装,以及高德地图天气API的调用。
基于C#使用winform技术的游戏平台的实现【C#课程设计】
|
6月前
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
6月前
|
安全 C# 索引
C#一分钟浅谈:属性与索引器的定义
本文深入浅出地介绍了C#编程中的属性和索引器。属性让字段更安全,通过访问器方法在读写时执行额外操作,如验证数据有效性;索引器则赋予类数组般的访问方式,支持基于索引的数据访问模式。文章通过示例代码展示了如何定义及使用这两种特性,并提供了常见问题及其解决方案,帮助读者写出更健壮、易维护的代码。希望读者能从中学习到如何有效利用属性和索引器增强C#类的功能性。
147 12
|
5月前
|
设计模式 程序员 C#
C# 使用 WinForm MDI 模式管理多个子窗体程序的详细步骤
WinForm MDI 模式就像是有超能力一般,让多个子窗体井然有序地排列在一个主窗体之下,既美观又实用。不过,也要小心管理好子窗体们的生命周期哦,否则一不小心就会出现一些意想不到的小bug
466 0