C#开发基础:WPF和WinForms关于句柄使用的区别

1、前言

在 Windows 应用程序开发中,WPF(Windows Presentation Foundation)和 WinForms(Windows Forms)是两种常见的用户界面(UI)框架。它们各自有不同的架构和处理方式,其中一个显著的区别就是它们对于 句柄(Handle)的使用。了解这些差异对于开发人员在选择合适的框架以及处理 UI 事件时非常重要。

2、什么是句柄?

句柄是操作系统用来唯一标识窗口或控件的一个数字标识符。在 Windows 操作系统中,每个窗口、控件、以及其他图形用户界面元素都有一个与之相关的句柄。句柄通常由操作系统内核分配,并且由应用程序在后台管理,用来与操作系统进行交互。

3、窗口句柄获取方式

WPF(Windows Presentation Foundation)

WPF 是一种用于创建现代化用户界面的框架,是.NET的一部分。在 WPF 中,UI 元素以XML形式定义,并使用 XAML(eXtensible Application Markup Language)作为标记语言。WPF 使用 DirectX 渲染引擎,具有强大的图形渲染能力和可扩展性。

WPF 中的 UI 元素不直接依赖于底层操作系统的窗口句柄(handle),而是通过一个称为 HWNDSource 的包装类间接管理句柄。这样做的好处是,WPF 可以将多个 UI 元素绘制到单个窗口句柄上,从而提高性能和效率。WPF将整个窗口作为单个句柄,而不是每个UI元素一个句柄。这种设计使WPF能够更好地利用现代图形硬件进行渲染,并提供更高的性能和可扩展性。

WPF使用DirectX渲染引擎来绘制图形,而不是传统的GDI+。这使得WPF能够在屏幕上呈现出更丰富、更吸引人的用户界面,支持3D效果、动画和混合模式等功能。

在WPF中,如果需要与操作系统的句柄交互,可以通过WindowInteropHelper类获取窗口句柄。这允许在WPF的ViewModel或其他代码中使用句柄,以便调用Win32 API或执行与句柄相关的操作。

WinForms(Windows Forms)

WinForms 是一种基于传统的 Windows 应用程序开发框架,也是.NET的一部分。它采用了基于消息循环的模型,使用 GDI+(Graphics Device Interface)进行图形渲染。通过处理窗口消息来更新和呈现UI控件。每个UI控件都有自己的句柄,可以使用句柄来操作和控制该控件。在WinForms中,每个UI控件都对应一个操作系统的窗口句柄。当创建一个WinForms窗体时,会同时创建一个窗口句柄,并将其与该窗体关联。

在WinForms中,可以直接在窗体类或控件类中使用句柄,无需额外的封装或包装。这使得WinForms更容易与底层的Win32 API进行交互,并执行与句柄相关的操作。

4、句柄使用方式:

WPF ViewModel 中使用 Win32 API

在WPF中,可以使用WindowInteropHelper类来获取窗口句柄,并在ViewModel或其他代码中使用该句柄进行Win32 API调用或执行与句柄相关的操作。进而可以实现一些与底层窗口交互的功能,例如:

在WPF窗口上显示Win32控件:可以将Win32控件嵌入到WPF窗口中。
调用Win32 API函数:可以使用窗口句柄调用各种Win32 API函数,来实现一些特定的功能,例如修改窗口样式、发送窗口消息等。
下面是一个示例代码,演示如何使用WindowInteropHelper获取窗口句柄以及如何使用句柄调用Win32 API函数来修改窗口样式。

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;namespace WpfInteropExample
{public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}protected override void OnSourceInitialized(EventArgs e){base.OnSourceInitialized(e);// 获取窗口句柄IntPtr hwnd = new WindowInteropHelper(this).Handle;// 修改窗口样式为无边框窗口const int WS_BORDER = 0x00800000;const int WS_CAPTION = 0x00C00000;const int WS_SYSMENU = 0x00080000;const int WS_MAXIMIZEBOX = 0x00010000;const int WS_MINIMIZEBOX = 0x00020000;const int GWL_STYLE = -16;int style = GetWindowLong(hwnd, GWL_STYLE);SetWindowLong(hwnd, GWL_STYLE, style & ~(WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX));// 重新应用窗口样式SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0004);// 设置窗口位置和大小SetWindowPos(hwnd, IntPtr.Zero, 100, 100, 400, 300, 0x0001 | 0x0002);// 设置窗口标题SetWindowText(hwnd, "Modified Window Title");}// 导入需要使用的Win32 API函数[DllImport("user32.dll", SetLastError = true)]private static extern int GetWindowLong(IntPtr hWnd, int nIndex);[DllImport("user32.dll")]private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);[DllImport("user32.dll")]private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);[DllImport("user32.dll", CharSet = CharSet.Auto)]private static extern int SetWindowText(IntPtr hwnd, string lpString);}
}

仅演示了如何获取窗口句柄并修改窗口样式。
查看设计图和运行时的区别:
在这里插入图片描述

WinForms 中使用 Win32 API

在WinForms中,通过获取窗口句柄你可以实现一些底层的窗口交互功能,例如:

调用Win32 API函数:可以使用窗口句柄调用各种Win32 API函数,来实现一些特定的功能,比如修改窗口样式、发送窗口消息等。
使用原生窗口控件:可以将原生的Win32控件嵌入到WinForms窗口中。
下面是一个示例代码,演示了如何在WinForms中获取窗口句柄,并使用句柄调用Win32 API函数来修改窗口样式。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;namespace WinFormsInteropExample
{public partial class Form1 : Form{public Form1(){InitializeComponent();}protected override void OnHandleCreated(EventArgs e){base.OnHandleCreated(e);// 获取窗口句柄IntPtr hwnd = this.Handle;// 修改窗口样式为无边框窗口const int WS_BORDER = 0x00800000;const int WS_CAPTION = 0x00C00000;const int WS_SYSMENU = 0x00080000;const int WS_MAXIMIZEBOX = 0x00010000;const int WS_MINIMIZEBOX = 0x00020000;const int GWL_STYLE = -16;int style = GetWindowLong(hwnd, GWL_STYLE);SetWindowLong(hwnd, GWL_STYLE, style & ~(WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX));// 重新应用窗口样式SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0004);// 设置窗口位置和大小SetWindowPos(hwnd, IntPtr.Zero, 100, 100, 400, 300, 0x0001 | 0x0002);// 设置窗口标题SetWindowText(hwnd, "Modified Window Title");}// 导入需要使用的Win32 API函数[DllImport("user32.dll", SetLastError = true)]private static extern int GetWindowLong(IntPtr hWnd, int nIndex);[DllImport("user32.dll")]private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);[DllImport("user32.dll")]private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);[DllImport("user32.dll", CharSet = CharSet.Auto)]private static extern int SetWindowText(IntPtr hwnd, string lpString);}
}

这个示例代码演示了如何在WinForms中获取窗口句柄并修改窗口样式
查看设计图和运行时的区别:
在这里插入图片描述

5、均可以通过句柄与第三方组件交互

WPF和WinForms都是Windows桌面应用程序开发框架,它们可以通过窗口句柄与第三方程序交互。

在WPF中,可以使用WindowInteropHelper类获取窗口句柄,然后调用Win32 API函数来与第三方程序进行交互。例如,可以使用FindWindow函数查找第三方程序的窗口句柄,然后使用SendMessage函数向该窗口发送消息,或者使用SetWindowPos函数控制该窗口的位置和大小等。

在WinForms中,可以使用Control.Handle属性获取窗口句柄,然后调用Win32 API函数来与第三方程序进行交互。例如,可以使用FindWindow函数查找第三方程序的窗口句柄,然后使用SendMessage函数向该窗口发送消息,或者使用SetWindowPos函数控制该窗口的位置和大小等。

这种基于窗口句柄的交互方式,可以让WPF和WinForms应用程序与其他Windows应用程序无缝地集成,实现各种功能的互通和共享。但需要注意的是,由于涉及到与外部程序的交互,因此需要谨慎处理,避免出现安全和稳定性问题。

6、通过句柄与第三方程序交互的好处有以下几点:

  1. 可以实现与其他Windows应用程序的无缝集成
    通过窗口句柄,WPF和WinForms应用程序可以直接访问和控制其他Windows应用程序的窗口、消息、位置、大小等属性和方法,从而实现各种功能的互通和共享。
  2. 可以扩展应用程序的功能
    通过与其他Windows应用程序交互,WPF和WinForms应用程序可以获取一些原生应用程序无法提供的功能和数据,从而使应用程序更加丰富和强大。
  3. 可以提高应用程序的用户体验
    通过与其他Windows应用程序交互,WPF和WinForms应用程序可以让用户更加方便地完成一些任务,例如在文本编辑器中插入图片、在浏览器中打开链接等,从而提高用户的满意度和忠诚度。

7、总结

WinForms:控件和窗口直接依赖句柄来进行渲染和事件处理,开发者可以显式访问句柄并进行低级操作。基于 GDI 渲染,性能较为简单直接,适合传统桌面应用。依赖于 Windows 消息机制,每个控件有独立的句柄处理消息。
WPF:句柄的使用较为隐式,主要通过 Windows API 进行兼容,开发者不需要直接操作句柄,更多依赖于事件和数据绑定。基于 DirectX 渲染,支持更丰富的图形效果和硬件加速,适合需要复杂 UI 的应用。采用事件驱动机制,消息通过路由事件传递,不直接依赖句柄。

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

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

相关文章

WPS Office手机去广高级版

工具介绍功能特点 WPS Office是使用人数最多的移动办公软件,独有手机阅读模式,字体清晰翻页流畅;完美支持文字,表格,演示,PDF等51种文档格式;新版本具有海量精美模版及高级功能 安装环境 [名称…

【Three.js基础学习】21.Realistic rendering

前言 课程回顾 渲染器 1.色调映射 值意在将高动态范围](HDR)值转换为低动态范围(LDR) Three.is中的色调映射实际上会伪造将LDR转换为HDR的过程,即使颜色不是HDR, 结果会产生非常逼真的渲染效果 THREE .NoToneMapping (default) 无色调映射 THREE.Linear…

TeamTalk知识点梳理一(单聊)

文章目录 db_proxy_serverdb_proxy_server reactor响应处理流程连接池redis连接池MySQL连接池 单聊消息消息如何封装?如何保证对端完整解析一帧消息?协议格式?单聊消息流转流程消息序号(msg_id )为什么使用redis生成&a…

LLaMA-Factory学习笔记(1)——采用LORA对大模型进行SFT并采用vLLM部署的全流程

该博客是我根据自己学习过程中的思考与总结来写作的,由于初次学习,可能会有错误或者不足的地方,望批评与指正。 1. 安装 1.1 LLaMA-Factory安装 安装可以参考官方 readme (https://github.com/hiyouga/LLaMA-Factory/blob/main/…

Linux -- 进程初印象

目录 预备知识 切入点 PCB 看见进程 pid getpid 函数 预备知识 Linux -- 冯诺依曼体系结构(硬件)-CSDN博客https://blog.csdn.net/2301_76973016/article/details/143598784?spm1001.2014.3001.5501 Linux -- 操作系统(软件&#xf…

342--358作业整理(错误 + 重点)

目录 1. 在需要运行的类中 定义 main 方法 2. this 。访问逻辑:先访问本类中,再访问父类中可以访问的成员(不包括和本类中重名的成员) 3. super 。访问逻辑:super(父类对象)直接访问父类及以…

Jekins篇(搭建/安装/配置)

目录 一、环境准备 1. Jenkins安装和持续集成环境配置 2. 服务器列表 3. 安装环境 Jekins 环境 4. JDK 环境 5. Maven环境 6. Git环境 方法一:yum安装 二、JenKins 安装 1. JenKins 访问 2. jenkins 初始化配置 三、Jenkins 配置 1. 镜像配置 四、Mave…

【Linux】冯诺依曼体系结构

目录 一、冯诺依曼体系结构二、冯诺依曼体系结构的基本组成三、关于冯诺依曼体系结构的一些问题结尾 一、冯诺依曼体系结构 冯诺依曼体系结构,也称为普林斯顿结构,是现代计算机设计的基础框架。这一体系结构由数学家冯诺依曼在20世纪40年代提出&#xf…

M1M2 MAC安装windows11 虚拟机的全过程

M1/M2 MAC安装windows11 虚拟机的全过程 这两天折腾了一下windows11 arm架构的虚拟机,将途中遇到的坑总结一下。 1、虚拟机软件:vmware fusion 13.6 或者 parallel 19 ? 结论是:用parellel 19。 这两个软件都安装过&#xff0…

NAT、代理服务与内网穿透技术全解析

🍑个人主页:Jupiter. 🚀 所属专栏:Linux从入门到进阶 欢迎大家点赞收藏评论😊 目录 NAT 技术背景NAT IP 转换过程NAPTNAT 技术的缺陷 代理服务器正向代理工作原理功能特点应用场景 反向代理基本原理应用场景 NAT 和代理…

优选算法 - 1 ( 双指针 移动窗口 8000 字详解 )

一&#xff1a;双指针 1.1 移动零 题目链接&#xff1a;283.移动零 class Solution {public void moveZeroes(int[] nums) {for(int cur 0, dest -1 ; cur < nums.length ; cur){if(nums[cur] 0){}else{dest; // dest 先向后移动⼀位int tmp nums[cur];nums[cur] num…

qt配合映美精取图开发

最近开发一个项目&#xff0c;用映美精相机配合halcon做取图开发&#xff0c;由于网上资料小特意写个记录。到映美精官网下载驱动&#xff0c;映美精官网&#xff0c;下载映美精的工具开发包SDK 映美精的SDK下载SDK后找到classlib文件夹 里面就是SDK新建一个qt程序&#xff0c…

华为云计算HCIE-Cloud Computing V3.0试验考试北京考场经验分享

北京试验考场 北京考场位置 1.试验考场地址 北京市海淀区北清路156号中关村环保科技示范园区M地块Q21楼 考试场选择北京&#xff0c;就是上面这个地址&#xff0c;在预约考试的时候会显示地址&#xff0c;另外在临近考试的时候也会给你发邮件&#xff0c;邮件内会提示你考试…

LeetCode 509.斐波那契数

动态规划思想 五步骤&#xff1a; 1.确定dp[i]含义 2.递推公式 3.初始化 4.遍历顺序 5.打印dp数组 利用状态压缩&#xff0c;简化空间复杂度。在原代码中&#xff0c;dp 数组保存了所有状态&#xff0c;但实际上斐波那契数列的计算只需要前两个状态。因此&#xff0c;我们…

反向代理开发

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…

RabbitMQ — 异步调用

RabbitMQ 是一个开源的消息代理中间件&#xff0c;它使用高级消息队列协议&#xff08;AMQP, Advanced Message Queuing Protocol&#xff09;来实现不同系统之间的消息传递。它以 Erlang 语言编写&#xff0c;具有高可靠性、灵活性和易于扩展的特点&#xff0c;被广泛应用于异…

2025 年使用 Python 和 Go 解决 Cloudflare 问题

作为一名从事网络自动化和爬取工作的开发者&#xff0c;我亲眼目睹了日益复杂的安全性措施带来的挑战。其中一项挑战是 Cloudflare 的 Turnstile CAPTCHA 系统&#xff0c;目前该系统已在全球 2600 多万个网站上使用。这种先进的解决方案重新定义了我们对机器人检测的处理方式&…

大数据的实时处理:工具和最佳实践

在当今的数字世界中&#xff0c;数据以前所未有的速度从无数来源生成&#xff0c;包括社交媒体、物联网设备、电子商务平台等。随着组织认识到这些数据的潜在价值&#xff0c;他们越来越多地转向实时处理&#xff0c;以获得即时、可操作的见解。但是&#xff0c;实时处理大数据…

104、Python并发编程:基于事件Event实现多线程间的同步

引言 继续介绍关于多线程同步的实现方式&#xff0c;本文将介绍基于Event的线程同步方式。 本文的主要内容有&#xff1a; 1、什么是Event 2、Event的使用场景 3、Event的代码实例 4、Event与Condition的比较 什么是Event 在Python的多线程编程中&#xff0c;Event是一个…

第2章2.3立项【硬件产品立项的核心内容】

硬件产品立项的核心内容 2.3 硬件产品立项的核心内容2.3.1 第一步&#xff1a;市场趋势判断2.3.2 第二步&#xff1a;竞争对手分析1.竞争对手识别2.根据竞争对手分析制定策略 2.3.3 第三步&#xff1a;客户分析2.3.4 第四步&#xff1a;产品定义2.3.5 第五步&#xff1a;开发执…