博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Direct2D Brush操作
阅读量:5083 次
发布时间:2019-06-13

本文共 7710 字,大约阅读时间需要 25 分钟。

为方便,将D2D的一个基本类DesktopWindow写成如下所示:

View Code
#include "Precompiled.h"#include 
#include
#pragma comment(lib, "d2d1")using namespace D2D1;using namespace Microsoft::WRL;template
struct DesktopWindow : CWindowImpl
>{ ComPtr
m_factory; ComPtr
m_target; DECLARE_WND_CLASS_EX(L"My D2D1 Window", CS_HREDRAW | CS_VREDRAW, -1); BEGIN_MSG_MAP(DesktopWindow) MESSAGE_HANDLER(WM_PAINT, PaintHandler) MESSAGE_HANDLER(WM_DESTROY, DestroyHandler) MESSAGE_HANDLER(WM_SIZE, SizeHandler) MESSAGE_HANDLER(WM_DISPLAYCHANGE, DisplayChangeHandler) END_MSG_MAP() LRESULT DisplayChangeHandler(UINT, WPARAM, LPARAM, BOOL&) { Invalidate(); return 0; } LRESULT SizeHandler(UINT, WPARAM, LPARAM lparam, BOOL&) { if (m_target) { if (m_target->Resize(SizeU(LOWORD(lparam), HIWORD(lparam))) != S_OK) { m_target.Reset(); } } return 0; } LRESULT PaintHandler(UINT, WPARAM, LPARAM, BOOL&) { PAINTSTRUCT ps; VERIFY(BeginPaint(&ps)); Render(); EndPaint(&ps); return 0; } LRESULT DestroyHandler(UINT, WPARAM, LPARAM, BOOL&) { PostQuitMessage(0); return 0; } void Invalidate() { VERIFY(InvalidateRect(nullptr, false)) } void Render() { if (!m_target) { RECT rect; VERIFY(GetClientRect(&rect)); auto size = SizeU(rect.right, rect.bottom); m_factory->CreateHwndRenderTarget(RenderTargetProperties(), HwndRenderTargetProperties(m_hWnd, size), m_target.GetAddressOf()); static_cast
(this)->CreateDeviceResources(); } if (!(m_target->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED)) { m_target->BeginDraw(); static_cast
(this)->Draw(); if (m_target->EndDraw() == D2DERR_RECREATE_TARGET) { m_target.Reset(); } } } int Run() { D2D1_FACTORY_OPTIONS fo = {};#ifdef DEBUG fo.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;#endif D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, fo, m_factory.GetAddressOf()); CreateDeviceIndependentResources(); VERIFY(__super::Create(nullptr, 0, L"title")); MSG msg; BOOL result; while (result = GetMessage(&msg, 0, 0, 0)) { if (result != -1) { DispatchMessage(&msg); } } return msg.wParam; } virtual void CreateDeviceIndependentResources() {}};

所有的画笔(Brush)都有SetOpacity和SetTransform两个方法,所有的单色画笔(SolidColorBrush)都有SetColor方法,可以设置颜色。

画笔是可修改的(mutable),因此,可以只声明一个画笔,然后在使用的时候,不断地更换颜色。

最简单的单色画笔(SolidColorBrush)示例如下所示:

View Code
#include "Precompiled.h"#include "DesktopWindow.h"D2D1_COLOR_F const COLOR_BLUE    = { 0.26f, 0.56f, 0.87f, 1.0f };D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f,  1.0f };D2D1_COLOR_F const COLOR_BLACK  = { 0.0f,  0.0f,  0.0f,  1.0f };D2D1_COLOR_F const COLOR_WHITE  = { 1.0f,  1.0f,  1.0f,  1.0f };struct SampleWindow : DesktopWindow{    ComPtr
m_brush; void CreateDeviceResources() { m_target->CreateSolidColorBrush(COLOR_BLUE, m_brush.ReleaseAndGetAddressOf()); } void Draw() { m_target->Clear(COLOR_BLUE); auto size = m_target->GetSize(); m_brush->SetOpacity(1.0f); m_brush->SetColor(COLOR_BLACK); auto br = RectF(100.0f, 100.0f, size.width - 100.0f, 200.0f); m_target->FillRectangle(br, m_brush.Get()); m_brush->SetColor(COLOR_WHITE); auto bw = RectF(100.0f, 300.0f, size.width - 100.0f, 400.0f); m_target->FillRectangle(bw, m_brush.Get()); m_brush->SetOpacity(.5f); m_brush->SetColor(COLOR_YELLOW); auto ry = RectF(150.0f, 150.0f, size.width - 150.0f, 350.0f); m_target->FillRectangle(ry, m_brush.Get()); }};int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int){ SampleWindow window; window.Run();}

 线性渐变画笔(LinearGradientBrush)稍微麻烦,需要先定义关键点(D2D1_GRADIENT_STOP),然后将关键点加入渐变集合(ID2D1GradientStopCollection),最后将渐变集合定义为渐变画笔,其示例如下所示: 

View Code
#include "Precompiled.h"#include "DesktopWindow.h"D2D_COLOR_F const COLOR_BLUE    = { 0.26f, 0.56f, 0.87f, 1.0f };D2D_COLOR_F const COLOR_WHITE    = { 1.0f,  1.0f,  1.0f,  1.0f };struct SampleWindow : DesktopWindow
{ ComPtr
m_brush; void CreateDeviceResources() { D2D1_GRADIENT_STOP stops[] = { { 0.0f, COLOR_WHITE }, { 1.0f, COLOR_BLUE } }; ComPtr
collection; m_target->CreateGradientStopCollection(stops, _countof(stops), collection.GetAddressOf()); D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES props = {}; m_target->CreateLinearGradientBrush(props, collection.Get(), m_brush.ReleaseAndGetAddressOf()); } void Draw() { auto size = m_target->GetSize(); m_brush->SetEndPoint(Point2F(size.width, size.height)); auto r = RectF(0.0f, 0.0f, size.width, size.height); m_target->FillRectangle(r, m_brush.Get()); }};int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int){ SampleWindow window; window.Run();}

 可以使用环形渐变画笔(RadialGradientBrush),其定义方法和线性渐变画笔类似,也是定义关键点、渐变集合(COM),然后再定义渐变画笔,其救命如下所示:

View Code
#include "Precompiled.h"#include "DesktopWindow.h"D2D1_COLOR_F const COLOR_BLUE    = { 0.26f, 0.56f, 0.87f, 1.0f };D2D_COLOR_F const COLOR_WHITE     = { 1.0f,  1.0f,  1.0f,  1.0f };struct SampleWindow : DesktopWindow
{ ComPtr
m_brush; void CreateDeviceResources() { D2D1_GRADIENT_STOP stops[] = { { 0.0f, COLOR_WHITE }, { 1.0f, COLOR_BLUE } }; ComPtr
collection; m_target->CreateGradientStopCollection(stops, _countof(stops), collection.GetAddressOf()); D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES props = {}; m_target->CreateRadialGradientBrush(props, collection.Get(), m_brush.ReleaseAndGetAddressOf()); } void Draw() { auto size = m_target->GetSize(); m_brush->SetCenter(Point2F(size.width / 2.0f, size.height / 2.0f)); m_brush->SetRadiusX(size.width / 2.0f); m_brush->SetRadiusY(size.height / 2.0f); auto r = RectF(0.0f, 0.0f, size.width, size.height); m_target->FillRectangle(r, m_brush.Get()); }};int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int){ SampleWindow window; window.Run();}

 在创建渐变集合时(CreateGradientStopCollection),可以设置D2D1_GAMMA_1_0或者D2D1_GAMMA_2_2,默认是D2D1_GAMMA_2_2,具体区别如下图所示(上图为2.2),直观上的区别就是D2D1_GAMMA_2_2的渐变性更好。

最后,还可以通过设置边框样式(ID2D1StrokeStyle)来显示各种边框,注意边框样式是独立于设备的资源,因此,只需将边框样式的定义放在CreateDeviceIndependentResources方法中即可:

View Code
#include "Precompiled.h"#include "DesktopWindow.h"D2D1_COLOR_F const COLOR_BLUE    = { 0.26f, 0.56f, 0.87f, 1.0f };D2D_COLOR_F const COLOR_WHITE     = { 1.0f,  1.0f,  1.0f,  1.0f };struct SampleWindow : DesktopWindow
{ ComPtr
m_brush; ComPtr
m_style; void CreateDeviceIndependentResources() { D2D1_STROKE_STYLE_PROPERTIES props = {}; props.lineJoin = D2D1_LINE_JOIN_ROUND; props.dashStyle = D2D1_DASH_STYLE_DASH_DOT; props.dashCap = D2D1_CAP_STYLE_ROUND; m_factory->CreateStrokeStyle(props, nullptr, 0, m_style.GetAddressOf()); } void CreateDeviceResources() { m_target->CreateSolidColorBrush(COLOR_WHITE, m_brush.ReleaseAndGetAddressOf()); } void Draw() { m_target->Clear(COLOR_BLUE); auto size = m_target->GetSize(); auto r = RectF(100.0f, 100.0f, size.width - 100.0f, size.height - 100.0f); m_target->DrawRectangle(r, m_brush.Get(), 20.0f, m_style.Get()); }};int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int){ SampleWindow window; window.Run();}

 

转载于:https://www.cnblogs.com/sdflysha/archive/2013/04/18/3028225.html

你可能感兴趣的文章
故障转移
查看>>
清空dataset中的某行某列的数据
查看>>
盒模型
查看>>
js中闭包和作用域
查看>>
CI框架整合UEditor编辑器上传功能
查看>>
树的层号表示
查看>>
最大整数
查看>>
[转] 数据模型建设的几点思考与总结
查看>>
[1].Common SSIS Applications
查看>>
stm8s + si4463 寄存器配置
查看>>
Asp.NetCore取配置信息
查看>>
自动变量提示
查看>>
css中盒模型的理解与整理
查看>>
Thread.currentThread().getName() ,对象实例.getName() 和 this.getName()区别
查看>>
如果你是程序员,这些细节会害死你(3)
查看>>
xmlhttp的OnReadyStateChange事件
查看>>
python连接oracle数据库
查看>>
C++异常处理
查看>>
捕获键盘和鼠标的消息机制
查看>>
Csharp 简单操作Word模板文件
查看>>