WPF如何把东西画出来
2015-08-19 15:26
316 查看
你或许已经通过重载OnRender函数非常熟练的画出了图形。那么OnRender方法中的DrawingContext参数到底来自哪呢?
因为DrawingContext是抽象类,所以微软创建了一个叫做RenderDataDrawingContext的具体类以及它的子类VisualDrawingContext,我们所用的DrawingContext实际上就是VisualDrawingContext这个类,不过微软把他们都定义成internal,我们在程序集外部无法访问,既然无法访问,那么当我们需要多个这样的对象时如何创建呢?
DrawingVisual这个类为我们实现多个DrawingContext成为可能,因为它的实例犯法RenderOpen()在内部创建了VisualDrawingContext。DrawingVisual也可以说继承于Visual,当我们用DrawingContext的Drawing绘制一些东西的时候i,其实产生的是绘图数据,数据有了,可要把数据给UI线程才能被显示,WPF似乎使用ContextLayoutManager这个类来把UI重绘的请求发送到Dispatcher队列,用Visual里的DUCE发送消息和线程对话。
我们创建可视数据的代码可以写成这样:
以上是创建画图的数据,那么怎么用ContextLayoutManager把数据给Dispatcher队列呢?UIElement中的ProgpagateResumeLayout方法循环递归把需要刷新的Visual对象放到队列中,经过这样的分装我们只需要把需要呈现的Visual扔给系统就可以了,系统自己会判断是否需要刷新。
怎么把Visual给系统呢?微软要求我们先给Visual的数量,这需要我们通过以下方式来给定
然后系统会用一个for循环来得到需要的Visual对象
internalVisualChildrenCount的数量就是VisualChildrenCount的返回值,InternalGetVisualChild的方法实际做的就是调用我们重载的GetVisualChild()方法。
一个WPF应用程序从两个线程开始,分别负责用户界面(UI)的管理和渲染。托管代码为用户提供构建WPF所需要的各种功能,如布局和绑定等,通常用户界面管理线程使用该部分代码;非托管代码主要负责图形的叠加显示和渲染,那么使用该部分代码的是不能被用户接触的渲染线程,这两个线程之间通过消息来传递数据。
1.在最上层 是逻辑树,如在页面中添加一个按钮或矩形,其实质都是在逻辑树上添加一个节点。
2.WPF的托管代码部分包含一个重要的子系统,即Visual System,它是托管代码与非托管代码沟通的桥梁,其内部保存WPF程序需要显示的可视树结构。从可视树的角度来 说,其实质是添加多个Visual到可视树。
3.前两步均在用户界面线程中,添加Visual之后用户界面线程和渲染线程会通过消息传递可视化数据。
4.非托管代码部分(Milcore)又称为“媒体整合层(Media Integration Layer)”。其中包含了合成子系统(Composition System)和渲染引擎(Rendering Engine)。合成子系统接受Visual之后会将其转换为Composition节点,并添加到Composition Tree中。
5.渲染引擎将Composition Tree转换为DirectX可以识别的三角形,这个过程称为“Tesellate(三角剖分)”。
6.DirectX经过驱动(WDDM或者XPDM)通知显卡开始绘制像素到屏幕。
通过VisualChildrenCount和GetVisualChild()方法会将Visual传递给VisualSystem。
需要Composition Tree的原因如下:
1.可视树只存在用户界面线程中,如果渲染线程需要绘制WPF的用户界面,则也需要一个数据结构。这个数据结构就是Composition Tree,它存在于渲染线程中。也就是说Composition System会将Visual System传递过来的Visual Tree转换为Composition Tree。
2.渲染引擎并不知道可视树,它只知道Composition Tree,并将其转换为DirectX可以识别的三角形。
因为DrawingContext是抽象类,所以微软创建了一个叫做RenderDataDrawingContext的具体类以及它的子类VisualDrawingContext,我们所用的DrawingContext实际上就是VisualDrawingContext这个类,不过微软把他们都定义成internal,我们在程序集外部无法访问,既然无法访问,那么当我们需要多个这样的对象时如何创建呢?
DrawingVisual这个类为我们实现多个DrawingContext成为可能,因为它的实例犯法RenderOpen()在内部创建了VisualDrawingContext。DrawingVisual也可以说继承于Visual,当我们用DrawingContext的Drawing绘制一些东西的时候i,其实产生的是绘图数据,数据有了,可要把数据给UI线程才能被显示,WPF似乎使用ContextLayoutManager这个类来把UI重绘的请求发送到Dispatcher队列,用Visual里的DUCE发送消息和线程对话。
我们创建可视数据的代码可以写成这样:
DrawingVisual boardVisual = new DrawingVisual(); using(DrawingContext drawingContext=boardVisual.RenderOpen()) { //绘制 }
以上是创建画图的数据,那么怎么用ContextLayoutManager把数据给Dispatcher队列呢?UIElement中的ProgpagateResumeLayout方法循环递归把需要刷新的Visual对象放到队列中,经过这样的分装我们只需要把需要呈现的Visual扔给系统就可以了,系统自己会判断是否需要刷新。
怎么把Visual给系统呢?微软要求我们先给Visual的数量,这需要我们通过以下方式来给定
protected override int VisualChildrenCount { return visual的数量; }
然后系统会用一个for循环来得到需要的Visual对象
for(int I=0;i<internalVisualChildrenCount;i++) { Visual visualChild = v.InternalGetVisualChild(i); if(visualChild!=null) { PropagateResumeLayout(v,visualChild); } }
internalVisualChildrenCount的数量就是VisualChildrenCount的返回值,InternalGetVisualChild的方法实际做的就是调用我们重载的GetVisualChild()方法。
protected override Visual GetVisualChild(int index) { return visual对象; }
一个WPF应用程序从两个线程开始,分别负责用户界面(UI)的管理和渲染。托管代码为用户提供构建WPF所需要的各种功能,如布局和绑定等,通常用户界面管理线程使用该部分代码;非托管代码主要负责图形的叠加显示和渲染,那么使用该部分代码的是不能被用户接触的渲染线程,这两个线程之间通过消息来传递数据。
1.在最上层 是逻辑树,如在页面中添加一个按钮或矩形,其实质都是在逻辑树上添加一个节点。
2.WPF的托管代码部分包含一个重要的子系统,即Visual System,它是托管代码与非托管代码沟通的桥梁,其内部保存WPF程序需要显示的可视树结构。从可视树的角度来 说,其实质是添加多个Visual到可视树。
3.前两步均在用户界面线程中,添加Visual之后用户界面线程和渲染线程会通过消息传递可视化数据。
4.非托管代码部分(Milcore)又称为“媒体整合层(Media Integration Layer)”。其中包含了合成子系统(Composition System)和渲染引擎(Rendering Engine)。合成子系统接受Visual之后会将其转换为Composition节点,并添加到Composition Tree中。
5.渲染引擎将Composition Tree转换为DirectX可以识别的三角形,这个过程称为“Tesellate(三角剖分)”。
6.DirectX经过驱动(WDDM或者XPDM)通知显卡开始绘制像素到屏幕。
通过VisualChildrenCount和GetVisualChild()方法会将Visual传递给VisualSystem。
需要Composition Tree的原因如下:
1.可视树只存在用户界面线程中,如果渲染线程需要绘制WPF的用户界面,则也需要一个数据结构。这个数据结构就是Composition Tree,它存在于渲染线程中。也就是说Composition System会将Visual System传递过来的Visual Tree转换为Composition Tree。
2.渲染引擎并不知道可视树,它只知道Composition Tree,并将其转换为DirectX可以识别的三角形。
相关文章推荐
- hdu 5402 Travelling Salesman Problem (构造)
- 菜鸟系列——欧几里德与扩展欧几里
- MySQL下载安装、配置与使用(win7x64/32)
- Java内存分配
- tomcat server.xml配置详解
- 静态测试和动态测试
- java连接数据库
- Java Mail 发送邮件 接收邮件
- Hadoop的伪分布安装 hadoop的核心思想
- uva10071-Back to High School Physics
- EasyUI combobox--给combobox绑定值
- SpringMVC -jquery实现分页
- 桌面支持--打印服务未启动--需要开启
- cplusplus 模板类学习笔记
- Spring 的两种定时器
- ZOJ 3703 Happy Programming Contest
- 硬件十万个为什么——运放篇(三)如何估算多级放大器的频宽
- 重定向
- 大端模式和小端模式
- struts2中的ActionContext