百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

掌握.Net桌面开发的精髓之一:句柄,一种特殊的数据类型3

liebian365 2024-10-26 12:59 30 浏览 0 评论

自定义的句柄封装类

要创建自定义的句柄封装类以提供更高级的句柄管理功能,可以继承SafeHandle类并重写一些方法。下面是一个示例,演示了如何创建自定义的句柄封装类:

class MyCustomHandle : SafeHandle
{
    public MyCustomHandle() : base(IntPtr.Zero, true)
    {
        // 初始化句柄
        handle = NativeMethods.CreateCustomHandle();
    }

    public override bool IsInvalid
    {
        get { return handle == IntPtr.Zero; }
    }

    protected override bool ReleaseHandle()
    {
        // 释放句柄
        return NativeMethods.CloseCustomHandle(handle);
    }
}

·在这个示例中,我们创建了一个名为MyCustomHandle的自定义句柄封装类,它继承自SafeHandle类。在构造函数中,我们通过调用NativeMethods.CreateCustomHandle()方法初始化句柄。IsInvalid属性被重写为判断句柄是否为无效的逻辑。如果句柄为IntPtr.Zero,则表示句柄无效。ReleaseHandle方法被重写为释放句柄的逻辑。在此示例中,我们调用了NativeMethods.CloseCustomHandle()方法来释放句柄。在使用自定义句柄封装类时,可以使用using语句或者手动调用Dispose方法来释放句柄:

using (MyCustomHandle handle = new MyCustomHandle())
{
    // 使用handle对象
}

或者:

MyCustomHandle handle = new MyCustomHandle();
try
{
    // 使用handle对象
}
finally
{
    handle.Dispose();
}

使用自定义句柄封装类,可以在SafeHandle的基础上实现更高级的句柄管理功能。例如,可以添加额外的方法来执行特定的操作,或者在Dispose方法中释放其他相关资源。这样,可以确保句柄及其相关资源在对象不再使用时得到正确释放和清理。

当使用自定义句柄封装类时,可以通过以下示例代码演示如何安全地管理句柄:

class Program
{
    static void Main(string[] args)
    {
        using (MyCustomHandle handle = new MyCustomHandle(NativeMethods.CreateCustomHandle()))
        {
            if (!handle.IsInvalid)
            {
                // 使用句柄
                NativeMethods.SomeOperation(handle);
            }
            else
            {
                Console.WriteLine("无效的句柄");
            }
        }
    }
}

class MyCustomHandle : SafeHandle
{
    public MyCustomHandle(IntPtr handle) : base(handle, true)
    {
        // 可选的初始化逻辑
    }

    public override bool IsInvalid
    {
        get { return handle == IntPtr.Zero; }
    }

    protected override bool ReleaseHandle()
    {
        // 可选的释放句柄逻辑
        // 例如,调用NativeMethods.CloseHandle(handle)等
        return true; // 返回true表示成功释放句柄
    }
}

static class NativeMethods
{
    [DllImport("CustomLibrary.dll")]
    public static extern IntPtr CreateCustomHandle();

    [DllImport("CustomLibrary.dll")]
    public static extern void SomeOperation(MyCustomHandle handle);
}

在这个示例中,我们使用了一个简单的Console应用程序作为示例。在Main方法中,我们使用using语句创建了一个MyCustomHandle对象,并在构造函数中调用NativeMethods.CreateCustomHandle()方法来获取句柄。然后,我们检查句柄是否有效,如果有效,就可以使用句柄执行相应的操作。在此示例中,我们调用了NativeMethods.SomeOperation方法,并将句柄作为参数传递给该方法。在使用完毕后,using语句会自动调用MyCustomHandle对象的Dispose方法,释放句柄。在Dispose方法中,我们可以执行句柄的释放逻辑。

需要注意的是,示例中的NativeMethods类是一个静态类,通过DllImport特性引入了使用句柄的外部方法。这些外部方法可根据实际情况来定义和实现,用于操作句柄。通过使用自定义句柄封装类,我们可以确保句柄及其相关资源在对象不再使用时得到正确释放和清理,提供了更安全和可靠的句柄管理方式。

句柄的最佳实践

当使用句柄时,以下是一些关于句柄使用的最佳实践:

  1. 避免句柄滥用:只有在必要的情况下使用句柄,避免将其用于不需要的场景。滥用句柄可能导致资源泄漏、内存泄漏或其他问题。
  2. 确保传递句柄的上下文一致性:在使用句柄的过程中,确保传递句柄的上下文保持一致。这意味着在创建、使用和释放句柄的各个阶段,确保句柄在正确的上下文中使用,并且句柄的生命周期得到正确管理。
  3. 使用安全句柄封装类:尽可能使用安全句柄封装类来管理句柄。安全句柄封装类(如SafeHandle类)提供了自动释放句柄和资源的功能,可以大大简化句柄的管理和错误处理。
  4. 明确句柄的所有权:在多个对象之间传递句柄时,明确句柄的所有权。谁拥有句柄,谁负责释放句柄。避免多个对象都试图释放同一个句柄,或者在不再拥有句柄的对象上使用句柄。
  5. 注意句柄的有效性检查:在使用句柄之前,始终进行有效性检查。确保句柄不为无效值(如IntPtr.Zero),以避免使用无效句柄导致的错误。
  6. 及时释放句柄:在不再需要句柄时,尽早释放句柄。这样可以及时回收资源,并确保不会出现资源泄漏的问题。
  7. 错误处理和异常处理:在使用句柄时,适当处理错误和异常。捕获可能发生的异常,并根据情况进行相应的错误处理和清理操作。
  8. 遵循相关文档和最佳实践:对于特定的句柄类型或特定的句柄使用场景,了解和遵循相关的文档和最佳实践。这样可以确保正确地使用和管理句柄,并避免潜在的问题。

通过遵循这些最佳实践,可以更有效地使用和管理句柄,确保句柄的正确性、安全性和一致性,并减少与句柄相关的问题和错误。

句柄使用案例

案例一:

c#使用句柄进行通信_c#句柄-CSDN博客

参考来源:https://blog.csdn.net/u012563853/article/details/124447251

案例二:


C#实现操作Windows窗口句柄:遍历、查找窗体和控件【窗口句柄最全总结之一】 - 掘金 (juejin.cn)

案例三:

在窗口和控件操作中,句柄(Handle)是一个用于标识和操作窗口或控件的唯一标识符。通过使用句柄,我们可以执行各种操作,如获取窗口句柄、发送消息、修改属性等。

以下是窗口和控件操作中句柄的应用:

1.获取窗口句柄:
在进行窗口操作时,首先需要获取目标窗口的句柄。句柄可以通过窗口函数或库函数来获取。例如,在C#中,可以使用
FindWindow函数来根据窗口类名或标题查找窗口句柄。示例如下:

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    static void Main()
    {
        // 查找窗口句柄
        IntPtr hWnd = FindWindow(null, "Notepad");

        if (hWnd != IntPtr.Zero)
        {
            Console.WriteLine("窗口句柄:" + hWnd);
        }
        else
        {
            Console.WriteLine("未找到窗口");
        }
    }
}

2.发送消息:
通过窗口句柄,我们可以向窗口或控件发送消息。消息可以是系统定义的常量,也可以是自定义的消息。例如,在C#中,可以使用
SendMessage函数来向指定窗口发送消息。示例如下:

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("user32.dll")]
    public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    static void Main()
    {
        IntPtr hWnd = FindWindow(null, "Notepad");

        if (hWnd != IntPtr.Zero)
        {
            // 向窗口发送消息
            const int WM_CLOSE = 0x0010;
            SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        }
        else
        {
            Console.WriteLine("未找到窗口");
        }
    }
}

3.修改属性:
使用窗口句柄,我们可以修改窗口或控件的属性。例如,在C#中,可以使用
SetWindowPos函数来修改窗口的位置和大小。示例如下:

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("user32.dll")]
    public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

    static void Main()
    {
        IntPtr hWnd = FindWindow(null, "Notepad");

        if (hWnd != IntPtr.Zero)
        {
            // 修改窗口位置和大小
            const uint SWP_NOSIZE = 0x0001;
            SetWindowPos(hWnd, IntPtr.Zero, 100, 100, 500, 500, SWP_NOSIZE);
        }
        else
        {
            Console.WriteLine("未找到窗口");
        }
    }
}

#挑战30天在头条写日记#

#自律学习计划#

#实话实说#

相关推荐

go语言也可以做gui,go-fltk让你做出c++级别的桌面应用

大家都知道go语言生态并没有什么好的gui开发框架,“能用”的一个手就能数的清,好用的就更是少之又少。今天为大家推荐一个go的gui库go-fltk。它是通过cgo调用了c++的fltk库,性能非常高...

旧电脑的首选系统:TinyCore!体积小+精简+速度极快,你敢安装吗

这几天老毛桃整理了几个微型Linux发行版,准备分享给大家。要知道可供我们日常使用的Linux发行版有很多,但其中的一些发行版经常会被大家忽视。其实这些微型Linux发行版是一种非常强大的创新:在一台...

codeblocks和VS2019下的fltk使用中文

在fltk中用中文有点问题。英文是这样。中文就成这个样子了。我查了查资料,说用UTF-8编码就行了。edit->Fileencoding->UTF-8然后保存文件。看下下边的编码指示确...

FLTK(Fast Light Toolkit)一个轻量级的跨平台Python GUI库

FLTK(FastLightToolkit)是一个轻量级的跨平台GUI库,特别适用于开发需要快速、高效且简单界面的应用程序。本文将介绍Python中的FLTK库,包括其特性、应用场景以及如何通过代...

中科院开源 RISC-V 处理器“香山”流片,已成功运行 Linux

IT之家1月29日消息,去年6月份,中科院大学教授、中科院计算所研究员包云岗,发布了开源高性能RISC-V处理器核心——香山。近日,包云岗在社交平台晒出图片,香山芯片已流片,回片后...

Linux 5.13内核有望合并对苹果M1处理器支持的初步代码

预计Linux5.13将初步支持苹果SiliconM1处理器,不过完整的支持工作可能还需要几年时间才能完全完成。虽然Linux已经可以在苹果SiliconM1上运行,但这需要通过一系列的补丁才能...

Ubuntu系统下COM口测试教程(ubuntu port)

1、在待测试的板上下载minicom,下载minicom有两种方法:方法一:在Ubuntu软件中心里面搜索下载方法二:按“Ctrl+Alt+T”打开终端,打开终端后输入“sudosu”回车;在下...

湖北嵌入式软件工程师培训怎么选,让自己脱颖而出

很多年轻人毕业即失业、面试总是不如意、薪酬不满意、在家躺平。“就业难”该如何应对,参加培训是否能改变自己的职业走向,在湖北,有哪些嵌入式软件工程师培训怎么选值得推荐?粤嵌科技在嵌入式培训领域有十几年经...

新阁上位机开发---10年工程师的Modbus总结

前言我算了一下,今年是我跟Modbus相识的第10年,从最开始的简单应用到协议了解,从协议开发到协议讲解,这个陪伴了10年的协议,它一直没变,变的只是我对它的理解和认识。我一直认为Modbus协议的存...

创建你的第一个可运行的嵌入式Linux系统-5

@ZHangZMo在MicrochipBuildroot中配置QT5选择Graphic配置文件增加QT5的配置修改根文件系统支持QT5修改output/target/etc/profile配置文件...

如何在Linux下给zigbee CC2530实现上位机

0、前言网友提问如下:粉丝提问项目框架汇总下这个网友的问题,其实就是实现一个网关程序,内容分为几块:下位机,通过串口与上位机相连;下位机要能够接收上位机下发的命令,并解析这些命令;下位机能够根据这些命...

Python实现串口助手 - 03串口功能实现

 串口调试助手是最核心的当然是串口数据收发与显示的功能,pzh-py-com借助的是pySerial库实现串口收发功能,今天痞子衡为大家介绍pySerial是如何在pzh-py-com发挥功能的。一、...

为什么选择UART(串口)作为调试接口,而不是I2C、SPI等其他接口

UART(通用异步收发传输器)通常被选作调试接口有以下几个原因:简单性:协议简单:UART的协议非常简单,只需设置波特率、数据位、停止位和校验位就可以进行通信。相比之下,I2C和SPI需要处理更多的通...

同一个类,不同代码,Qt 串口类QSerialPort 与各种外设通讯处理

串口通讯在各种外设通讯中是常见接口,因为各种嵌入式CPU中串口标配,工业控制中如果不够还通过各种串口芯片进行扩展。比如spi接口的W25Q128FV.对于软件而言,因为驱动接口固定,软件也相对好写,因...

嵌入式linux为什么可以通过PC上的串口去执行命令?

1、uboot(负责初始化基本硬bai件,如串口,网卡,usb口等,然du后引导系统zhi运行)2、linux系统(真正的操作系统)3、你的应用程序(基于操作系统的软件应用)当你开发板上电时,u...

取消回复欢迎 发表评论: