• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2024-06-15 17:07 Aet 隐藏边栏 |   抢沙发  16 
文章评分 3 次,平均分 5.0

程序A盖着程序B上面

关于鼠标的消息响应问题

  1. 为什么点击公共区域,响应的是上面那个
    1. Windows操作系统按照Z顺序处理窗口,这意味着最上层的窗口优先接收输入事件
    2. 操作系统使用Hit Testing方法,根据点击坐标判断哪个窗口包含该坐标

关于未被遮盖部分的显示问题

概述

  1. Windows操作系统中,窗口的渲染由窗口管理器和图形设备接口(GDI)处理
  2. 当一个窗口覆盖另一个窗口时,Windows会管理这些窗口的绘制区域,并确保每个窗口都能正确地显示其可见部分

窗口重叠的处理:

  1. 剪裁区域
    1. 每个窗口都有一个剪裁区域,表示该窗口当前可见的部分
    2. 当一个窗口部分被另一个窗口覆盖时,Windows会计算被覆盖窗口的可见区域,并只绘制这部分内容
  2. 无效区域
    1. 当窗口被移动、调整大小或被其他窗口覆盖时,系统会将需要重绘的区域标记为无效区域
    2. 无效区域会在下一次WM_PAINT消息处理中被重绘
  3. Z序(Z-order
    1. Windows窗口系统维护一个Z序列表,用于管理窗口的前后顺序
    2. 最前面的窗口会首先被绘制,依次往后绘制
    3. 当窗口A覆盖窗口B时,窗口A的可见部分会覆盖B的对应部分,但B未被覆盖的部分仍然会显示

渲染过程

  1. 当一个窗口被部分覆盖时,Windows会根据窗口的Z序来决定哪些部分需要重绘,步骤如下:
  2. 计算无效区域:
    1. 当窗口A覆盖窗口B时,系统会计算出窗口B的无效区域,即需要重绘的部分
  3. 发送WM_PAINT消息:
    1. 对于无效区域,系统会发送WM_PAINT消息给对应的窗口,通知它们进行重绘
    2. 窗口B会接收到WM_PAINT消息并重绘其未被覆盖的部分
  4. 绘制窗口内容:
    1. 每个窗口在处理WM_PAINT消息时,会根据其剪裁区域绘制内容
    2. 窗口B只会绘制其可见的部分,即未被窗口A覆盖的部分

无效区域和裁剪区域的理解

  1. 无效区域
    1. 无效区域由系统计算,解决“哪里需要更新”的问题
  2. 裁剪区域
    1. 裁剪区域由程序设定,解决“允许在哪里绘制”的问题
  3. 一句话总结
    1. 裁剪区域是程序定义的绘图允许范围(比如一个正方向窗口我通过代码让它显示成圆心窗口),无效区域是系统标记的重绘需求范围(比如这个圆形窗口或其他窗口被遮盖部分,或因为移动、改变大小,被系统计算出需要重绘的部分)

关于消息的传递

  1. 当你在桌面上点击程序A的界面时,输入设备(如鼠标或键盘)会生成硬件中断
  2. 这些中断被操作系统处理,然后转化为相应的输入消息(如鼠标点击消息WM_LBUTTONDOWN
  3. 这些输入消息首先会进入操作系统维护的系统消息队列
    1. 系统消息队列是全局的,用于暂时存储系统范围内的输入事件
  4. 操作系统会从系统消息队列中取出消息,并根据消息的目标窗口,将消息分发到相应的线程消息队列中
    1. 操作系统根据输入事件的坐标来确定目标窗口
      会选择Z序列表里面第一个匹配的窗口
      操作系统使用Hit Testing方法,根据点击坐标判断哪个窗口包含该坐标
    2. 每个窗口与创建它的线程关联
      操作系统根据目标窗口找到相应的线程
    3. 操作系统将消息从系统消息队列中移出,并放入目标线程的消息队列中
  5. 每个GUI线程都有一个消息循环,它从线程的消息队列中提取消息
    1. 并将消息分发到相应的窗口过程函数

关于线程的消息循环

  1. 只有当线程调用了用户界面相关的API(如CreateWindowPeekMessageGetMessage)时,操作系统才会为该线程创建消息队列
    1. 这是为了优化资源使用,避免为不需要消息处理的线程创建不必要的消息队列
  2. 至于怎么检测到我调用了这些函数:
    1. 是通过内部的函数调用和检测机制实现的
  3. 用户模式调用:
    1. 当应用程序调用CreateWindowCreateWindowEx函数时,这些函数属于User32.dll库提供的用户模式API
    2. CreateWindowCreateWindowEx实际上是高级API,它们内部会调用更多底层的API和函数来完成窗口的创建
  4. 内部API调用:
    1. CreateWindowCreateWindowEx最终会调用CreateWindowStationCreateDesktopNtUserCreateWindow等更低层次的API
    2. 这些低层次API负责实际的窗口创建工作,并进行与窗口管理相关的各种操作
  5. 在底层API(如NtUserCreateWindow)调用之前,User32.dll会首先检查当前线程是否已经有消息队列
    1. 这是通过内部的线程数据结构和状态标志来实现的
    2. 每个线程都有一个线程本地存储区,用于存储线程特定的数据
    3. Windows使用TLS来跟踪每个线程的消息队列状态
  6. 如果当前线程还没有消息队列,User32.dll会调用相应的内部函数来创建消息队列
    1. 这些函数会与内核模式的窗口管理器组件(如Win32k.sys)交互,分配和初始化消息队列数据结构

对于窗口管理器

概述

  1. 窗口管理器是由Windows操作系统的内核和用户模式组件共同管理的
  2. Windows中,窗口管理器的主要职责是处理窗口的创建、销毁、移动、调整大小、层次管理以及输入事件的分发等

用户模式组件

  1. 用户模式下的窗口管理器包括User32.dllGDI32.dll
  2. User32.dll负责窗口管理的核心功能,如窗口的创建、消息处理、输入事件的分发等
  3. GDI32.dll则负责图形设备接口的实现,提供绘图功能

内核模式组件

  1. 内核模式下的窗口管理器包括Win32k.sys,负责低级别的图形和窗口管理操作,如窗口的合成和渲染

窗口在创建后是怎么被窗口管理器接管的?

  1. 在创建窗口之前,应用程序需要注册一个窗口类(使用RegisterClassRegisterClassEx
    1. 窗口类包含窗口过程的指针,用于处理窗口消息
  2. 应用程序调用CreateWindowEx(或CreateWindow)函数来创建一个窗口
    1. 这是一个User32.dll提供的函数
  3. CreateWindowEx函数调用User32.dllUser32.dll负责创建窗口并分配资源,如窗口句柄HWND
    1. User32.dll会将窗口信息记录在系统的窗口数据结构中
  4. User32.dll与内核模式组件Win32k.sys交互,将窗口信息传递给内核,确保窗口被正确地管理和渲染
  5. 在窗口创建成功后,窗口管理器接管窗口的管理
    1. 它负责窗口的消息分发、Z序管理(前后顺序)、输入事件处理等

是窗口管理器调用GDI进行绘制窗口的吗?

  1. 当窗口需要绘制时(例如,窗口的无效区域需要重绘),窗口管理器会发送WM_PAINT消息给窗口
  2. BeginPaintEndPaint之间,应用程序使用GDI函数进行绘制
    1. GDI(图形设备接口)是Windows提供的用于绘制图形和文本的API

  1. 内核模式处理:
    1. GDI函数调用会通过User32.dllGDI32.dll传递到内核模式组件Win32k.sys
    2. Win32k.sys负责实际的绘制操作,将绘制指令发送到显卡驱动进行渲染

关于Z序列表

概述

  1. Windows操作系统的Z序列表(Z-order list)是由窗口管理器维护的,保存在内核空间
    1. 具体来说,这些信息由操作系统的图形子系统(Windows Graphics Subsystem)管理,尤其是Win32k.sys驱动程序
    2. 这些数据结构不直接暴露给用户模式代码,但它们的管理和操作由系统提供的API间接进行

内核空间

  1. Z序列表是由内核模式组件管理的,包括Win32k.sys驱动程序
  2. 这个驱动程序负责维护所有顶层窗口的Z序顺序

图形子系统

  1. 图形子系统(Windows Graphics Subsystem)是Windows操作系统的一部分,负责处理所有与图形和窗口管理相关的操作
  2. 这个子系统在内核模式下运行,确保对窗口的管理和渲染是高效且安全的

关于图形设备接口

概述

  1. 图形设备接口(Graphics Device InterfaceGDI)是Windows操作系统的核心组件之一,负责与图形输出设备(如显示器和打印机)进行交互
  2. GDI提供了一套API,用于绘制图形、显示文本和管理图形对象

概念

  1. 图形设备上下文(Device Context, DC
    1. 图形设备上下文是一个数据结构,包含了绘图属性和绘图状态
    2. 通过设备上下文,应用程序可以绘制图形、文本,并与图形设备进行交互
    3. 设备上下文通常用一个句柄(HDC)来表示

  1. 图形对象
    1. GDI使用一系列图形对象来描述绘图属性,包括笔(Pen)、刷子(Brush)、字体(Font)、调色板(Palette)等
    2. 这些对象需要选择到设备上下文中,才能应用于绘图操作

  1. 绘图操作
    1. GDI提供了丰富的绘图函数,用于绘制直线、矩形、椭圆、多边形、位图、文本等

主要功能

  1. 绘制图形
    1. GDI提供了绘制基本图形的函数,如直线、矩形、椭圆、多边形等

  1. 显示文本
    1. GDI支持在窗口和设备上下文中绘制文本,支持不同的字体、颜色和对齐方式

  1. 管理图形对象
    1. GDI使用图形对象来定义绘图属性,如笔、刷子、字体、调色板等
    2. 应用程序可以创建、选择和删除这些对象

  1. 位图操作
    1. GDI支持位图操作,可以加载、显示、操作位图图像
    2. 支持的格式包括BMPJPEGPNG

  1. 打印支持
    1. GDI提供了与打印设备交互的功能,支持打印预览、分页打印和打印属性设置

每个应用程序会有一个图形设备上下文吗

  1. Windows操作系统中,每个应用程序可能有多个图形设备上下文(Device Context, DC),具体取决于应用程序的需要
  2. 窗口设备上下文
    1. 与窗口相关联的设备上下文,用于在窗口的客户区内绘图

  1. 客户区设备上下文(Client DC
    1. 仅用于窗口的客户区

  1. 屏幕设备上下文(Screen DC
    1. 与整个屏幕相关联的设备上下文,用于在屏幕上绘图

  1. 打印机设备上下文
    1. 与打印机相关联的设备上下文,用于打印操作

示例

  1. 窗口绘图
    1. 当应用程序需要在窗口内绘制内容时,会获取窗口设备上下文或客户区设备上下文

  1. 离屏绘图
    1. 当应用程序需要在内存中绘制内容(如双缓冲技术),以减少屏幕闪烁时,会使用内存设备上下文

  1. 打印
    1. 当应用程序需要打印内容时,会创建打印机设备上下文

GDI和GDI+

概述

  1. 都是Windows操作系统中的图形处理API
  2. 但它们在功能、性能和编程模型上有显著区别

GDI

  1. GDIWindows操作系统中最早的图形处理API之一,自Windows 1.0以来一直存在
  2. GDI直接与图形设备(如显示器和打印机)交互,主要用于绘制基本的2D图形和文本
  3. GDI提供的图形功能相对有限,主要包括基本的形状绘制(如线条、矩形、椭圆)、位图操作和简单的文本绘制
  4. GDI的绘图操作主要是基于像素的,缺乏高级的绘图功能(如反锯齿、透明度和复杂的变换)
  5. 由于GDI直接与硬件交互,其性能在某些情况下可能优于GDI+,特别是在处理简单的图形操作时

GDI+

  1. GDI+GDI的增强版,提供了更丰富的图形功能和更现代化的编程接口
  2. GDI+采用面向对象的设计,提供了更高层次的抽象,使用起来比GDI更简洁和直观
  3. GDI+支持高级图形功能,如反锯齿、透明度、渐变、纹理填充、复杂变换和图形路径等
  4. GDI+提供了更强大的文本处理功能,支持复杂的文本布局和格式设置
  5. GDI+的绘图操作主要是基于矢量的,支持更高质量的图形输出
  6. 由于GDI+提供了更多的高级功能,其性能在某些情况下可能不如GDI,特别是在需要大量绘图操作时

CPU还是GPU渲染

  1. GDI
    1. GDI主要使用CPU进行渲染
    2. 虽然在某些情况下,GDI会利用显卡的硬件加速功能(例如通过DirectDraw),但大部分的绘图操作还是由CPU完成的
    3. GDI的设计和实现主要是基于软件渲染
  2. GDI+
    1. GDI+主要使用CPU进行渲染

绘制异形窗口

概述

  1. 绘制异形窗口是一个涉及窗口区域(Window Region)和图形处理的任务
  2. Windows应用程序中,异形窗口是通过设置窗口的区域来实现的

步骤

  1. 定义窗口的形状:创建一个复杂的区域来定义窗口的形状
  2. 设置窗口区域:将该区域应用到窗口上,使其具有特定的形状

使用GDI

  1. 使用GDI的区域函数(如CreateRectRgnCreateEllipticRgnCreatePolygonRgn等)创建一个复杂的区域
  2. 使用SetWindowRgn函数将该区域应用到窗口,使窗口具有特定的形状

使用GDI+

  1. 使用GDI+GraphicsPath对象创建复杂的形状
  2. 使用Region类将GraphicsPath对象转换为区域
  3. 使用SetWindowRgn函数将该区域应用到窗口

关于Skia

概述

  1. 一个开源的2D图形库
  2. 支持多种操作系统,包括WindowsmacOSLinuxAndroidiOS
  3. 提供了丰富的图形功能,包括路径绘制、位图操作、反锯齿、渐变填充、图像滤镜、阴影等
  4. 利用硬件加速(如GPU)来提升绘图性能,同时也提供了软件渲染的支持
  5. Skia使用C++进行开发,提供了面向对象的编程接口

硬件加速是怎么做的

  1. Skia可以通过使用GPU(图形处理单元)来加速图形渲染

  2. 与传统的CPU渲染相比,GPU在处理并行计算任务(如图形渲染)时具有更高的效率

  3. Skia支持多种GPU图形API,包括OpenGLVulkanDirect3D

  4. OpenGL

    1. Skia通过Skia's Ganesh(其GPU图形子系统)来支持OpenGL
    2. Ganesh负责将Skia的绘图命令转换为OpenGL命令,从而在GPU上执行渲染操作
  5. Vulkan:

    1. 是一个现代的低开销、高性能的图形和计算API
    2. SkiaVulkan的支持允许它在支持Vulkan的设备上利用该API进行硬件加速渲染
  6. Direct3D:

    1. Skia也支持Direct3D,这是Windows平台上的一种广泛使用的图形API
    2. 通过Direct3DSkia可以在Windows设备上利用GPU进行加速渲染
  7. 硬件加速的优点

    1. 并行处理
      GPU能够同时处理大量的图形计算任务,特别适合用于处理复杂的图形操作(如反锯齿、多边形填充、纹理映射等)
      这使得绘图操作可以并行进行,而不是在CPU上串行处理,从而大幅提升渲染性能

    2. 专用硬件单元

      GPU包含专门设计用于图形渲染的硬件单元,如着色器单元、纹理单元和光栅化单元
      这些硬件单元能够高效地执行特定的图形操作,比通用处理器更快

  8. 示例:

    1. 一个使用SkiaOpenGL进行硬件加速渲染的简单示例:

对CPU渲染的理解

  1. Windows上,使用像GDIGDI+这样的库,这些库提供了绘图的API,让开发者可以在窗口或屏幕的某个位置进行绘图
  2. 绘图过程
    1. 你调用GDIGDI+的函数,例如绘制一个矩形或文本
    2. 这些API调用最终由CPU来执行,CPU负责处理这些绘图操作,并将结果渲染到内存或屏幕上
    3. CPU完成绘图操作后,结果显示在你指定的屏幕位置或窗口位置

对硬件渲染的理解

  1. 使用能够利用GPU的库,例如SkiaDirect2DOpenGLVulkan
  2. 绘图过程
    1. 你调用这些库的绘图函数,例如绘制一个圆或渲染一个3D对象
    2. 这些API调用被翻译成GPU能理解的命令或指令,这些指令通过图形驱动程序发送到GPU
    3. GPU根据接收到的指令执行绘图操作,利用其强大的并行计算能力快速完成绘图任务
    4. GPU完成绘图操作后,结果显示在你指定的屏幕位置或窗口位置

是怎么显示在屏幕上的

  1. 绘图操作
    1. 无论是CPU还是GPU进行渲染,首先会通过绘图API(如GDIGDI+OpenGLDirect3DSkia等)执行绘图操作,将图形数据绘制到一个帧缓冲区中
    2. 帧缓冲区是一个内存区域,存储了每个像素的颜色值
  2. 帧缓冲区
    1. CPU 渲染:绘图操作由CPU完成,结果存储在系统内存中的一个帧缓冲区
    2. GPU 渲染:绘图操作由GPU完成,结果存储在显存(VRAM)中的一个帧缓冲区
  3. 显示控制器
    1. 显示控制器负责管理从帧缓冲区到屏幕显示的过程
      显示控制器通常由显卡(GPU)或集成在主板上的图形芯片(如集成显卡)实现
    2. 显示控制器的主要任务包括:
    3. 扫描转换:将帧缓冲区的内容转换为显示器能够理解的信号(如HDMIDisplayPort信号)
    4. 刷新率管理:控制帧缓冲区的内容何时被传输到显示器,通常以一定的刷新率(如60Hz120Hz)进行更新
  4. 垂直同步
    1. 为了避免屏幕撕裂,许多系统使用垂直同步(V-Sync)技术
    2. 垂直同步确保帧缓冲区的内容更新与显示器的刷新周期同步:
    3. 双缓冲:使用两个帧缓冲区,一个用于当前显示,一个用于绘制下一帧
      当绘制完成后,两个缓冲区交换角色(交换缓冲,Swap Buffers
    4. 三缓冲:增加一个额外的缓冲区,以提高性能和减少延迟
  5. 显示器
    1. 显示器接收来自显示控制器的信号,将信号转换为光信号,显示最终的图像
    2. 显示器的类型可以是LCDLEDOLED等,不同类型的显示器有不同的显示技术和特性

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2025-03-10
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享