C#基础(⑦user32.dll)

我们来详细学习如何使用 user32.dll,它是 Windows 系统中负责用户界面交互的核心 DLL,包含窗口管理、消息处理、键盘鼠标输入等功能。下面从基础到进阶,一步一步教你调用其中的常用函数。

在 C# 中调用 user32.dll 需要使用 DllImport 特性,这需要引入 System.Runtime.InteropServices 命名空间。所有示例都基于这个前提,先创建一个控制台应用程序(或 Windows 应用程序),并在代码开头添加:

using System;
using System.Runtime.InteropServices; // 必须引入,用于DllImport

第一步:调用最基础的函数 —— 显示消息框(MessageBox)

MessageBox 是 user32.dll 中最常用的函数之一,用于显示系统风格的弹窗。

步骤 1:声明函数

首先需要在 C# 中声明 user32.dll 中的 MessageBox 函数,函数定义要和 DLL 中的原生接口一致:

// 声明 user32.dll 中的 MessageBox 函数
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int MessageBox(IntPtr hWnd,       // 父窗口句柄(null表示无父窗口)string lpText,     // 弹窗内容string lpCaption,  // 弹窗标题uint uType         // 弹窗样式(按钮、图标组合)
);

CharSet = CharSet.Unicode:确保中文等字符正常显示。
返回值 int:表示用户点击的按钮(如 1 = 确定,2 = 取消)。

步骤 2:调用函数

在 Main 方法中调用声明好的函数,测试不同样式的弹窗:

static void Main(string[] args)
{// 示例1:基础弹窗(只有"确定"按钮)int result1 = MessageBox(IntPtr.Zero,       // 无父窗口"这是一个简单的消息框", // 内容"基础示例",         // 标题0x00000000         // 样式:只有"确定"按钮(0));Console.WriteLine($"用户点击了按钮:{result1}"); // 点击"确定"会输出 1// 示例2:带"确定"和"取消"按钮 + 警告图标int result2 = MessageBox(IntPtr.Zero,"是否继续操作?","确认提示",0x00000003 | 0x00000030  // 0x3=确定+取消;0x30=警告图标(组合用 |));Console.WriteLine($"用户点击了按钮:{result2}"); // 确定=1,取消=2
}

运行效果
第一个弹窗只有 “确定” 按钮,点击后控制台输出 1。
第二个弹窗有 “确定”“取消” 按钮和警告图标,点击对应按钮会输出 1 或 2。

第二步:获取屏幕分辨率(GetSystemMetrics)

GetSystemMetrics 函数可以获取系统相关的尺寸信息,比如屏幕宽度、高度。

步骤 1:声明函数

// 声明获取系统尺寸的函数
[DllImport("user32.dll")]
public static extern int GetSystemMetrics(int nIndex);

参数 nIndex:指定要获取的信息(比如 0 = 屏幕宽度,1 = 屏幕高度)。

步骤 2:调用函数

static void Main(string[] args)
{// 获取屏幕宽度(参数 0 表示 SM_CXSCREEN)int screenWidth = GetSystemMetrics(0);// 获取屏幕高度(参数 1 表示 SM_CYSCREEN)int screenHeight = GetSystemMetrics(1);Console.WriteLine($"屏幕分辨率:{screenWidth} × {screenHeight}");// 额外示例:获取任务栏高度(参数 29 表示 SM_CYCAPTION)int taskbarHeight = GetSystemMetrics(29);Console.WriteLine($"任务栏高度:{taskbarHeight} 像素");
}

运行效果

控制台会输出你的屏幕分辨率(如 1920 × 1080)和任务栏高度。

第三步:查找窗口并操作(FindWindow + SetWindowText)

    FindWindow:根据窗口标题或类名查找窗口句柄(类似窗口的 “身份证”)。
    SetWindowText:修改窗口的标题。

    // 查找窗口(根据类名和窗口名)
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);// 修改窗口标题
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern bool SetWindowText(IntPtr hWnd, string lpString);

    步骤 2:调用函数(实战:修改记事本窗口标题)
    先手动打开一个记事本(Notepad),标题默认为 “无标题 - 记事本”。
    运行以下代码:

    static void Main(string[] args)
    {// 查找记事本窗口(类名"Notepad",标题"无标题 - 记事本")IntPtr notepadWnd = FindWindow("Notepad", "无标题 - 记事本");if (notepadWnd != IntPtr.Zero){// 找到窗口后,修改标题bool success = SetWindowText(notepadWnd, "被C#修改过的标题 - 记事本");if (success){Console.WriteLine("记事本标题修改成功!");}else{Console.WriteLine("标题修改失败");}}else{Console.WriteLine("未找到记事本窗口,请先打开记事本");}
    }

    运行效果

    如果记事本已打开且标题正确,它的标题会被改为 “被 C# 修改过的标题 - 记事本”。

    四、移动鼠标:SetCursorPos 函数

    SetCursorPos 可以直接设置鼠标指针在屏幕上的位置,非常直观。

    步骤 1:声明函数

    using System;
    using System.Runtime.InteropServices;class User32Demo
    {// 声明 SetCursorPos 函数:设置鼠标位置[DllImport("user32.dll")]public static extern extern bool SetCursorPos(int X, int Y);// 参数:X(水平坐标)、Y(垂直坐标),返回值:是否成功
    }

    步骤 2:使用函数移动鼠标

    static void Main(string[] args)
    {// 1. 移动鼠标到屏幕左上角(0, 0)bool success1 = SetCursorPos(0, 0);Console.WriteLine($"移动到左上角:{ (success1 ? "成功" : "失败") }");// 等待1秒,让你看清效果System.Threading.Thread.Sleep(1000);// 2. 移动鼠标到屏幕中心(假设屏幕分辨率是1920×1080)int screenWidth = 1920;  // 可通过前面学的 GetSystemMetrics(0) 获取实际宽度int screenHeight = 1080; // 可通过 GetSystemMetrics(1) 获取实际高度bool success2 = SetCursorPos(screenWidth / 2, screenHeight / 2);Console.WriteLine($"移动到中心:{ (success2 ? "成功" : "失败") }");// 等待1秒System.Threading.Thread.Sleep(1000);// 3. 移动鼠标到右下角bool success3 = SetCursorPos(screenWidth - 10, screenHeight - 10);Console.WriteLine($"移动到右下角:{ (success3 ? "成功" : "失败") }");
    }

    运行效果

    鼠标会依次移动到屏幕左上角 → 中心 → 右下角,每次移动后会在控制台显示结果。

    五、发送窗口消息:SendMessage 函数

    SendMessage 是 user32.dll 中非常强大的函数,它可以向指定窗口发送各种消息(如点击按钮、输入文本、关闭窗口等),实现对窗口的精细控制。

    先理解:什么是 “窗口消息”?
    Windows 系统中,所有窗口交互都是通过 “消息” 机制实现的。例如:

    点击按钮 → 窗口收到 WM_LBUTTONDOWN(左键按下)消息
    键盘输入 → 窗口收到 WM_CHAR(字符输入)消息
    窗口关闭 → 窗口收到 WM_CLOSE 消息

    SendMessage 就是手动给窗口发送这些消息,模拟用户操作。

    步骤 1:声明函数和常用消息常量

    class User32Demo
    {// 声明 SendMessage 函数:发送消息到窗口[DllImport("user32.dll", CharSet = CharSet.Unicode)]public static extern IntPtr SendMessage(IntPtr hWnd,    // 目标窗口句柄(通过 FindWindow 获取)uint Msg,       // 消息类型(如 WM_CLOSE 表示关闭窗口)IntPtr wParam,  // 消息参数1(根据消息类型变化)string lParam   // 消息参数2(字符串类型,如输入的文本));// 常用消息常量(可在微软文档中查询更多)public const uint WM_CLOSE = 0x0002;         // 关闭窗口消息public const uint WM_SETTEXT = 0x000C;       // 设置窗口文本(如输入框内容)public const uint WM_LBUTTONDOWN = 0x0201;   // 鼠标左键按下public const uint WM_LBUTTONUP = 0x0202;     // 鼠标左键释放(模拟点击)
    }

    步骤 2:实战 1:关闭指定窗口(发送 WM_CLOSE 消息)

    以关闭记事本为例:

    static void Main(string[] args)
    {// 1. 先找到记事本窗口(确保已打开,标题为"无标题 - 记事本")IntPtr notepadWnd = FindWindow("Notepad", "无标题 - 记事本");if (notepadWnd == IntPtr.Zero){Console.WriteLine("未找到记事本窗口");return;}// 2. 发送关闭窗口消息(WM_CLOSE)SendMessage(notepadWnd, User32Demo.WM_CLOSE, IntPtr.Zero, null);Console.WriteLine("已发送关闭消息,记事本应该会关闭");
    }// 注意:需要先声明前面学过的 FindWindow 函数
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    运行效果

    如果记事本已打开,会收到关闭消息并弹出保存提示(和手动点击关闭按钮效果一致)。

    步骤 3:实战 2:向记事本输入文本(发送 WM_SETTEXT 消息)

    记事本的编辑区域是一个子窗口(类名 "Edit"),需要先找到它的句柄,再发送输入消息:

    static void Main(string[] args)
    {// 1. 找到记事本主窗口IntPtr notepadWnd = FindWindow("Notepad", null); // 忽略标题,找所有记事本if (notepadWnd == IntPtr.Zero){Console.WriteLine("请先打开一个记事本");return;}// 2. 找到记事本的编辑区域子窗口(类名"Edit",无标题)IntPtr editWnd = FindWindowEx(notepadWnd, IntPtr.Zero, "Edit", null);if (editWnd == IntPtr.Zero){Console.WriteLine("未找到编辑区域");return;}// 3. 发送输入文本消息(WM_SETTEXT)SendMessage(editWnd, User32Demo.WM_SETTEXT, IntPtr.Zero, "这是通过 SendMessage 输入的文本!");Console.WriteLine("已向记事本输入文本");
    }// 额外声明 FindWindowEx 函数(用于查找子窗口)
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindWindowEx(IntPtr hWndParent,  // 父窗口句柄IntPtr hWndChildAfter, // 起始子窗口(null表示从第一个开始)string lpClassName, // 子窗口类名string lpWindowName // 子窗口标题
    );

    运行效果

    记事本的编辑区域会自动填入文本 “这是通过 SendMessage 输入的文本!”。

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
    如若转载,请注明出处:http://www.pswp.cn/web/95354.shtml
    繁体地址,请注明出处:http://hk.pswp.cn/web/95354.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    Markdown格式.md文件的编辑预览使用

    推荐工具Visual Studio Code (VS Code) - 强烈推荐特点:微软出品,免费、开源、跨平台(Windows, macOS, Linux)。拥有海量插件市场。编辑体验:安装 Markdown All in One 等插件后,可以获得语法高亮、实时预览…

    TypeScript:unknown 类型

    作为前端开发工程师,在 TypeScript 中使用 unknown 类型是提升类型安全的关键实践。下面我会结合实际开发场景详细讲解其特性和价值。unknown 核心特性1.类型安全的顶级类型与 any 类似,可接受任何类型的赋值:let userInput: unknown; userIn…

    2025 批量下载hasmart所有知乎回答,文章和想法,导出txt,html和pdf

    之前分享过文章2025 一键批量下载备份知乎回答/文章/想法/专栏/视频/收藏夹,导出txt,html和 pdf ,今天继续下载hasmart这个号的所有知乎回答 下载的知乎回答目录,包含发布时间和标题,点击可跳转对应回答。 2019年发布…

    mapbox高阶,结合threejs(threebox)添加管道,实现管道流动效果

    👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言 1.1 ☘️mapboxgl.Map 地图对象 1.2 ☘️mapboxgl.Map style属性 1.3 ☘️threebox add加载网格对象 二、🍀…

    语音识别后处理——如何语音断句加上标点、顺滑、ITN等

    基本流程 基于cpu的计算: 前往intel官网下载libmkl相关的库:libmkl_core.a、libmkl_gf_lp64.a、libmkl_sequential.a # 静默安装 ./intel-onemkl-2025.2.0.629_offline.sh -a -s --eula accept默认安装目录:/opt/intel/oneapi libmkl相关的…

    [吾爱出品] 图片转换王 v1.01 - 多格式支持 / 支持pds、Ai格式

    [吾爱出品] 图片转换王 多格式支持 链接:https://pan.xunlei.com/s/VOZ81aeES9JDqlcvXPKYlxwqA1?pwdni9b# 图片转换王」是一款专为设计师、自媒体从业者及普通用户打造的专业图片格式转换工具,秉持绿色便携理念,无需繁琐安装步骤&#xf…

    GitLab 18.3 正式发布,更新多项 DevOps、CI/CD 功能【一】

    沿袭我们的月度发布传统,极狐GitLab 发布了 18.3 版本,该版本带来了通过直接转移进行迁移、CI/CD 作业令牌的细粒度权限控制、自定义管理员角色、Kubernetes 1.33 支持、通过 API 让流水线执行策略访问 CI/CD 配置等几十个重点功能的改进。下面是对部分重…

    【macOS】垃圾箱中文件无法清理的--特殊方法

    【macOS】垃圾箱中文件无法清理的特殊方法直接拖拽到 Beyond Compare App中,删除时,选择以下选项即可彻底删除。1.在macOS桌面,将垃圾箱打开2.将垃圾文件和文件夹,拖拽到Beyond Compare界面3.选中待删除的文件和文件夹如上图。4.鼠…

    Python UV 管理如何使用镜像源安装 Python

    uv python install [版本号] --mirrorhttps://github.com/astral-sh/python-build-standalone/releases/download/这是默认情况下 uv python 安装命令,命令会找到 astral 公司在 Github 上的存储库,然后进行下载。我们只需要为 mirror 增加任意 Github 镜…

    SPI片选踩坑实录(硬件片选和软件片选)

    SPI(Serial Peripheral Interface,串行外设接口)的片选信号(Chip Select,简称 CS 或 SS,即 Slave Select)是 SPI 通信中用于选择从设备的关键控制信号,其作用是在多从设备的 SPI 总线…

    从理论到RTL,实战实现高可靠ECC校验(附完整开源代码/脚本)(3) RTL实现实战

    第二部分:ECC (30, 24)RTL实现实战 - 精雕细琢的硬件卫士 理论是基石,实现是关键。本部分将 手把手构建参数化、可综合、高可靠的ECC编解码器 。本部分将以MIPI 协议中Packet Header 用到的ECC(30,24) 为例…

    揭密设计模式:像搭乐高一样构建功能的装饰器模式

    揭密设计模式:像搭乐高一样构建功能的装饰器模式 在软件开发中,我们常常会遇到一个问题:如何给一个对象动态地添加新功能,同时又不想修改它的代码?如果直接在原有类上修修补补,代码会变得臃肿复杂&#xff…

    【Vue】前端 vue2项目搭建入门级(二)

    本文不同于【Vue】前端 vue2项目搭建入门级(一),本文创建vue2项目方式是一键创建vue2 项目,不需要自己配置。1.cmd进入根目录,输入vue create project(vue create 项目名)创建一个project的项目…

    基于SQLite索引的智能图片压缩存储系统设计与实现

    摘要 本文介绍一种基于SQLite索引的智能图片压缩存储系统,通过融合图像质量压缩与数据压缩技术,实现60-80%的压缩率,较传统方法压缩效率提升4-5倍。系统采用“大文件存储索引数据库”架构,针对性解决海量图片数据迁移与存储中的核…

    【一张图看懂Kafka消息队列架构】

    一张图看懂Kafka消息队列架构Kafka架构全景图ApacheKafka作为当今最流行的分布式消息队列系统,其架构设计精巧而高效。通过一张典型的Kafka架构图,我们可以清晰地看到几个核心组件:生产者(Producer)、消费者(Consumer)、主题(Topic)、分区(Pa…

    计算机三级嵌入式填空题——真题库(24)原题附答案速记

    1.表征数字音频每秒钟数据量的参数称为波形声音的__码率__。CD音乐的声音信号的采样率约为44kHz,量化位数为16位,采用双声道,则该参数的值为__1408__kb/s。(码率取样频率*量化位数*声道数44kHz*16*21408kb/s)2.利用载波…

    Gradle vs. Maven,Java 构建工具该用哪个?

    Java构建工具的甜咸粽子之争,就是 Gradle 和 Maven 该用哪个? 随心所欲的手动挡 vs. 稳如老狗的自动挡 Maven用的是pom.xml。很多人一听XML就头大,觉得又臭又长。但换个角度想,XML的缺点正是它最大的优点:死板、规范、…

    将Markdown文档输出成Word格式

    大家好!今天想和大家分享一个技术文档格式转换的小故事。有个朋友在软件行业从事文档工作,她们的手册是用Markdown编写的,使用Facebook的Docsaurus框架,在线浏览很方便,但输出Word格式却很不方便,问我是否有…

    COMSOL基于Voronoi毛细管及多边形骨料ITZ的微介观混凝土水分扩散模型

    本案例是通过COMSOL对论文An innovative method for mesoscale modelling of moisture diffusion in concrete(https://doi.org/10.1016/j.cemconcomp.2024.105836)中Voronoi毛细管、多边形骨料、ITZ、水泥浆体多相材料的几何模型复现。 其中论文中的混…

    机器学习和高性能计算中常用的几种浮点数精度

    浮点数 (Floating-Point Number) 是一种在计算机中表示带有小数部分的数字的方式。它通过科学记数法类似的方式(尾数 基数 ^ 指数)来近似表示实数。浮点数的精度决定了它可以表示的数值范围以及数值之间的精细程度。 常见的浮点数精度包括:F…