WPF如何把东西画出来

你或许已经通过重载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发送消息和线程对话。


我们创建可视数据的代码可以写成这样:

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可以识别的三角形。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值