C#基础(⑦user32.dll)

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

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

cs 复制代码
using System;
using System.Runtime.InteropServices; // 必须引入,用于DllImport

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

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

步骤 1:声明函数

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

cs 复制代码
// 声明 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 方法中调用声明好的函数,测试不同样式的弹窗:

cs 复制代码
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:声明函数

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

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

步骤 2:调用函数

cs 复制代码
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:修改窗口的标题。

cs 复制代码
// 查找窗口(根据类名和窗口名)
[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),标题默认为 "无标题 - 记事本"。

运行以下代码:

cs 复制代码
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:声明函数

cs 复制代码
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:使用函数移动鼠标

cs 复制代码
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 函数

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

先理解:什么是 "窗口消息"?

Windows 系统中,所有窗口交互都是通过 "消息" 机制实现的。例如:

点击按钮 → 窗口收到 WM_LBUTTONDOWN(左键按下)消息

键盘输入 → 窗口收到 WM_CHAR(字符输入)消息

窗口关闭 → 窗口收到 WM_CLOSE 消息

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

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

cs 复制代码
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 消息)

以关闭记事本为例:

cs 复制代码
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"),需要先找到它的句柄,再发送输入消息:

cs 复制代码
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 输入的文本!"。

相关推荐
黄焖鸡能干四碗4 小时前
固定资产管理系统(蓝牙标签打印+移动端Java+Vue+Uniapp源码)
java·开发语言·vue.js·eclipse·uni-app
我好喜欢你~4 小时前
C#---共享项目
开发语言·c#
丨 丨4 小时前
Python 爬虫基础教学
开发语言·爬虫·python
烟雨迷5 小时前
web自动化测试(selenium)
运维·开发语言·前端·python·selenium·测试工具
NRatel6 小时前
Unity项目基本风格/规范
unity·c#·游戏引擎·代码规范·规范
潼心1412o6 小时前
C语言(长期更新)第12讲:指针二详解
c语言·开发语言
荼蘼6 小时前
Python 爬虫实战:爬取 B 站视频的完整教程
开发语言·爬虫·python
小菜全7 小时前
使用Java获取本地PDF文件并解析数据
java·开发语言·python
chinesegf7 小时前
浏览器内存 (JavaScript运行时内存)存储的优劣分析
开发语言·javascript·ecmascript