Direct2D中,最常用的渲染目标是从窗口句柄建立的HwndRenderTarget,但是有些时候,我们并不希望在整个窗口上绘图,而是在其中的一部分上。这个问题可以通过把创建RenderTarget时引入的窗口句柄设定为某一控件的句柄来解决,但是这有诸多弊端。首先,一些框架的控件没有独立的句柄,例如WPF。其次,在控件重绘时,如果绘图速度不够快可能造成闪烁。
要解决第二个问题,通常的方法是双缓冲,而如果要在解决第二个问题的基础上,同时解决第一个问题,我想到的一个方法就是绘制的结果作为一个Source显示在Image控件上。Direct2D自然没有提供相关的支持,所以我们要自己搭建这个桥梁,造桥材料的其中一个选择是WriteableBitmap。
如图的代码可以创建一个新的WriteableBitmap对象。前两个参数是位图的大小,第三、四个参数分别是横纵的dpi,第五个参数是位图的像素格式,最后一个是调色盘,通常留空。
WriteableBitmap类可以作为Image控件的Source,并且可以实时更新内容。然而Direct2D不能直接在它上面绘图,我们需要一个间接的过程,比如使用WIC图片。
创建WIC图片的过程不多赘述,但是要注意,WIC图片的各个参数必须与作为缓冲区的WriteableBitmap图片相同。
然后我们要做的就是创建一个WicRenderTarget,使Direct2D绘制的结果保存在其中。
WicRenderTarget的第二个参数为创建的WIC对象,剩余参数一般填默认。
在绘制完成后,我们需要把WIC缓冲区中的数据复制到WriteableBitmap中,然而并没有安全的手段来进行这一操作,我们就必须用一些“暴力”的方式。
首先,调用WriteableBitmap的Lock方法,开始改写缓冲区。然后再调用WICBitmap的Lock方法,得到缓冲区的地址,并使用CopyMemory把WICBitmap的缓冲区数据复制到WriteableBitmap中,缓冲区的大小可以通过像素高度*每行的字节数来计算。在数据复制完成后要调用WriteableBitmap的AddDirtyRect或者WritePixels方法,来刷新前台的数据,把绘制的结果显示在屏幕上。
总结:这种方法可以实现Direct2D在局部窗口中绘图,并且无需响应WM_PAINT事件,缺点则是对CPU负担较重,在高帧率时性能欠佳。
要解决第二个问题,通常的方法是双缓冲,而如果要在解决第二个问题的基础上,同时解决第一个问题,我想到的一个方法就是绘制的结果作为一个Source显示在Image控件上。Direct2D自然没有提供相关的支持,所以我们要自己搭建这个桥梁,造桥材料的其中一个选择是WriteableBitmap。
如图的代码可以创建一个新的WriteableBitmap对象。前两个参数是位图的大小,第三、四个参数分别是横纵的dpi,第五个参数是位图的像素格式,最后一个是调色盘,通常留空。
WriteableBitmap类可以作为Image控件的Source,并且可以实时更新内容。然而Direct2D不能直接在它上面绘图,我们需要一个间接的过程,比如使用WIC图片。
创建WIC图片的过程不多赘述,但是要注意,WIC图片的各个参数必须与作为缓冲区的WriteableBitmap图片相同。
然后我们要做的就是创建一个WicRenderTarget,使Direct2D绘制的结果保存在其中。
WicRenderTarget的第二个参数为创建的WIC对象,剩余参数一般填默认。
在绘制完成后,我们需要把WIC缓冲区中的数据复制到WriteableBitmap中,然而并没有安全的手段来进行这一操作,我们就必须用一些“暴力”的方式。
首先,调用WriteableBitmap的Lock方法,开始改写缓冲区。然后再调用WICBitmap的Lock方法,得到缓冲区的地址,并使用CopyMemory把WICBitmap的缓冲区数据复制到WriteableBitmap中,缓冲区的大小可以通过像素高度*每行的字节数来计算。在数据复制完成后要调用WriteableBitmap的AddDirtyRect或者WritePixels方法,来刷新前台的数据,把绘制的结果显示在屏幕上。
总结:这种方法可以实现Direct2D在局部窗口中绘图,并且无需响应WM_PAINT事件,缺点则是对CPU负担较重,在高帧率时性能欠佳。