学习笔记(C#篇):C#使用WindowsAPI操作系统窗口(1)

1、前言

        本文主要介绍了在C#编程中,使用Windows系统提供的API取操作Windows的窗口应用程序的一些方法。使用到的工具:spy++(基于VS),插件FlaUI.

2、思路简述

        Windows系统为我们提供了可供调用的一些API,存放于诸如user32.dll等类似的文件中,我们可以使用这些dll文件中开放的接口从而去操作Windows的一些应用程序窗口。操作窗口的前提就是需要获取到这些窗口的信息,此处我使用工具spy++来直观的获取一些窗口的信息从而便于程序调用。关于FlaUI插件,在本文中仅作为实现模拟键鼠操作的工具,并没有做深入探讨。

3、工具介绍

        Spy++ (SPYXX.EXE) 是一个基于 Win32 的实用工具,它提供系统的进程、线程、窗口和窗口消息的图形视图。使用 Spy++ 可以执行下列操作: 显示系统对象(包括进程、线程和窗口)之间关系的图形树。 搜索指定的窗口、线程、进程或消息。 查看选定的窗口、线程、进程或消息的属性。(来自百度百科)

        如图,可以看到spy++可以将所有系统窗口一一展示出来,我们也可以对其进行一些查找等操作:

我们可以使用工具栏中第六个,望远镜标识的“查找窗口”操作(默认快捷键ALT+F3),来找到我们想要寻找的窗口:

通过手动拖动查找标识(箭头所指框中原有的圆形标识)到想要寻找的窗口,例如我这边是将其放置在浏览器窗口上,然后我们可以看到下面的介绍中给出了该窗口的一些基本信息,然后点击确定,就会在主页面定位到该窗口的位置,右键->属性,我们就可以看到这个窗口的详细信息.

这里面包含一些窗口的基本信息,诸如窗口标题、窗口句柄、窗口大小等,窗口栏还会显示子窗口以及父窗口信息,类一栏会展示类名等。

        每一个应用程序在启动的时候会占用一个唯一的句柄,我们可以通过句柄去找到并操作这个窗口。窗口的类名是程序本身特有的,也可以根据类名锁定窗口。

        窗口信息右键消息,可以看到这个窗口与系统之间的一些交互信息

点击记录选项,可以对想要查看的消息进行筛选:

在消息栏可以选中自己想要查看的消息类型进行展示,从而提取到想要的信息。

4、API介绍

        在编程过程中,我们需要引入Windows的一些API才能够实现与窗口的交互行为,这些API封装在诸如user32.dll等文件中,我们在C#中引入这些文件就可以使用。

引入方式:

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

这里以其中一个API为例表明了引入的方法,下面列举一些会用到的API的功能介绍:

1、IntPtr FindWindow(string lpClassName, string lpWindowName);根据类名或窗口标题获取窗口句柄,其中一个可以为null

2、bool GetWindowRect(IntPtr hWnd, out RECT lpRect);获取窗口的大小,输入窗口句柄,会将该窗口的大小输出到RECT对象中去

3、bool IsWindowVisible(IntPtr hWnd);判断一个句柄是否属于某个窗口

4、IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);根据窗口大小以及窗口句柄创建一个该窗口的图像,可以使用Image中的方法将该图像的一个句柄转换为可以操作的BitMap格式

5、IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);向hWnd窗口发送一条消息,消息内容一般都是操作数,例如关闭窗口WM_CLOSE = 0x0010,后续参数根据操作需求传入,可以为Zero

6、int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);根据窗口句柄获取窗口类名,输出到 lpCalssName

7、bool ShowWindow(IntPtr hWnd, int nCmdShow);将窗口设置为焦点

8、bool SetCursorPos(int x, int y);将鼠标移动到屏幕中指定的坐标

9、int ShellExecute(IntPtr hwnd, StringBuilder lpszOp, StringBuilder lpszFile, StringBuilder lpszParams, StringBuilder lpszDir, int FsShowCmd);对处在路径lpszDir的程序名lpszFile执行lpszOp操作

10、IntPtr CreateCompatibleDC(IntPtr hdc);创建一个绘图用的设备内存空间,通常与CreateCompatibleBitmap()一起使用

11、IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);将hgdiobj图像选入到hdc内存空间中

12、bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, int nFlags);将创建的图像打印到对应的设备内存

13、int DeleteDC(IntPtr hdc);删除开辟的内存空间句柄,释放资源

-------------

IntPtr:指的是句柄指针,在系统进程中,每个进程都会在开始运行的时候占用一个唯一的整数串,这个整数串称之为句柄,在C#中使用IntPtr这个结构体类型去表示句柄,它拥有指针的属性。

-------------

5、实现窗口截屏

        下面以获取窗口截图为例,来统合上述操作。在截图的过程中,坐标我们都可以根据窗口拿到,如果说想要对这个截屏进行裁剪,我们可以预先在窗口中找到指定坐标(spy++展示鼠标消息然后移动到指定位置记录下坐标即可,spy++展示的位置是相对于整个窗口而言的,并非全屏幕),然后去进行对应的操作即可。

//获取窗口截屏
public static Bitmap GetShotCutImage(IntPtr hWnd)
{
    var hscrdc = GetWindowDC(hWnd);
    var windowRect = new Rectangle();
    RECT rect;
    //获取窗口坐标
    GetWindowRect(hWnd, out rect);
    int width = rect.Right - rect.Left;
    int height = rect.Bottom - rect.Top;
    //创建指定大小的窗口图像
    var hbitmap = CreateCompatibleBitmap(hscrdc, width, height);
    var hmemdc = CreateCompatibleDC(hscrdc);
    //加载位图并绘制窗口
    SelectObject(hmemdc, hbitmap);
    PrintWindow(hWnd, hmemdc, 0);
    var bmp = Image.FromHbitmap(hbitmap);
    //释放资源
    DeleteDC(hscrdc);
    DeleteDC(hmemdc);
    return bmp;
}
//对窗口进行裁剪
public static Bitmap PictureCut(Bitmap orginImage, int X, int Y, int width, int heigth)
{
    string pictureName = "测试" + ProgramHelper.GenerateRandomNumber(6) + ".jpg";
    //裁剪
    Bitmap imageClone = (Bitmap)orginImage.Clone();
    // 定义裁剪区域
    Rectangle sourceRect = new Rectangle(X, Y, width, heigth); // 源图像的矩形区域
    // 创建一个与裁剪区域大小相同的 Bitmap 对象
    Bitmap croppedBitmap = new Bitmap(sourceRect.Width, sourceRect.Height);
    // 创建一个与 croppedBitmap 相关联的 Graphics 对象
    using (Graphics graphics = Graphics.FromImage(croppedBitmap))
    {
        // 将源图像的指定区域绘制到 croppedBitmap 上
        graphics.DrawImage(imageClone, new Rectangle(0, 0, croppedBitmap.Width, croppedBitmap.Height), sourceRect, GraphicsUnit.Pixel);
    }
    return croppedBitmap;
}

//矩形结构体
public struct RECT
{
    public int Left;        // x position of upper-left corner
    public int Top;         // y position of upper-left corner
    public int Right;       // x position of lower-right corner
    public int Bottom;      // y position of lower-right corner

    public override string ToString()
    {
        return $"Left:{Left}, Top:{Top}, Right:{Right}, Bottom:{Bottom}";
    }
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis是一个开源的持久化框架,可以帮助我们将数据从数据库中读取出来,然后转换为Java对象,并将Java对象写入数据库中。 在C#使用MyBatis,需要先安装MyBatis.Net库,然后在项目中引用该库。接着,我们需要创建一个配置文件,用于配置MyBatis的数据库连接信息、SQL语句等。在配置文件中,我们需要指定一个别名,用于在程序中引用这个配置文件。 接下来,我们需要创建一个映射文件,用于将数据库中的数据映射为Java对象。在映射文件中,我们需要定义一个 resultMap,用于定义Java对象与数据库表之间的关系。我们还需要定义一个 SQL 语句,用于从数据库中读取数据,并将其转换为Java对象。 在程序中,我们需要创建一个 SqlSession 对象,用于执行SQL语句。我们可以通过SqlSession对象调用selectOne、selectList、update、delete等方法,来执行SQL语句,并将结果转换为Java对象或者操作数据库。 下面是一个简单的示例,展示了如何在C#使用MyBatis: 1. 安装MyBatis.Net库 在Visual Studio中,选择“工具”-“NuGet包管理器”-“程序包管理器控制台”,然后输入以下命令: ``` Install-Package MyBatisNet ``` 2. 创建配置文件 在项目中创建一个名为“SqlMapConfig.xml”的文件,用于配置数据库连接信息、SQL语句等。以下是一个示例配置文件: ``` xml <?xml version="1.0" encoding="utf-8" ?> <sqlMapConfig> <database> <provider name="SqlServer" connectionString="Data Source=localhost;Initial Catalog=mydatabase;User ID=myuser;Password=mypassword;" /> </database> <sqlMap> <map resource="MyMapper.xml"/> </sqlMap> </sqlMapConfig> ``` 其中,provider元素用于指定数据库类型和连接字符串,map元素用于指定映射文件路径。 3. 创建映射文件 在项目中创建一个名为“MyMapper.xml”的文件,用于将数据库中的数据映射为Java对象。以下是一个示例映射文件: ``` xml <?xml version="1.0" encoding="utf-8" ?> <sqlMap namespace="MyMapper"> <resultMap id="MyResultMap" class="MyClass"> <result property="id" column="id"/> <result property="name" column="name"/> </resultMap> <select id="selectById" resultMap="MyResultMap"> SELECT * FROM mytable WHERE id=#id# </select> </sqlMap> ``` 其中,resultMap元素用于定义Java对象与数据库表之间的关系,select元素用于定义SQL语句。 4. 在程序中使用MyBatis 在程序中,我们需要创建一个 SqlSession 对象,用于执行SQL语句。以下是一个示例代码: ``` csharp using IBatisNet.DataMapper; using IBatisNet.DataMapper.Configuration; using IBatisNet.DataMapper.Configuration.Files; // 创建配置文件 DomSqlMapBuilder builder = new DomSqlMapBuilder(); ISqlMapper sqlMapper = builder.Configure(@"SqlMapConfig.xml"); // 执行SQL语句 MyClass obj = sqlMapper.QueryForObject<MyClass>("MyMapper.selectById", new { id = 1 }); ``` 以上是一个简单的示例,展示了如何在C#使用MyBatis。实际上,MyBatis还有很多其他的用法和功能,需要我们在实际开发中去探索和使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值