C#基础(⑦user32.dll)

发布于:2025-09-05 ⋅ 阅读:(22) ⋅ 点赞:(0)

我们来详细学习如何使用 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 输入的文本!”。


    网站公告

    今日签到

    点亮在社区的每一天
    去签到