Direct2D绘制的MFC控件
2013-06-07 16:52
483 查看
1.要点
MFC中已有的控件都是使用GDI/GDI+绘制自身,因此不适合直接从这些已有控件中继承,而应当CWnd中继承,将控件所有外观绘制的工作都交给Direct2D完成;重写OnEraseBkgnd()函数,返回TRUE,已通知框架,控件背景色已由Direct2D负责绘制,框架不需要再绘制背景色;
客户端在使用此控件时,需要在窗口初始化时修改窗口的样式为WS_CLIPCHILDREN,以防止客户端干扰控件自身的绘制。
在控件内部添加私有的Direct2D绘图相关的接口变量,具体的绘制过程和在窗口中绘图类似。
当控件被Resize或客户端设置了控件属性,控件需要立即重绘时,调用Invalidate(FALSE)。
2.一个简单Direct2D控件的实现代码
[code]//D2dProgressBar.h #pragma once #include "afxwin.h" #include <d2d1.h> #include <d2d1helper.h> #include <d2derr.h> #pragma comment(lib, "d2d1.lib") // CD2dProgressBar class CD2dProgressBar : public CWnd { public: CD2dProgressBar(void); ~CD2dProgressBar(void); private: ID2D1Factory* m_pD2d1Factory; ID2D1HwndRenderTarget* m_pRenderTarget; ID2D1SolidColorBrush* m_pSolidColorBrush; ID2D1LinearGradientBrush* m_pLinearGradientBrush; private: BOOL CreateDeviceIndependentResource(); BOOL CreateDeviceDependentResource(); void DiscardDeviceDependentResource(); void DestoryResource(); void Render(); void ResizeRenderTarget(int width,int height); public: void SetValue(int progressValue); int GetValue(void); private: int m_ProgressValue; public: DECLARE_MESSAGE_MAP() afx_msg void OnPaint(); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); virtual BOOL PreCreateWindow(CREATESTRUCT& cs); };
// D2dProgressBar.cpp : implementation file // #include "stdafx.h" #include "D2dProgressBar.h" using namespace D2D1; // // 释放模板. // template<typename Type> void SafeRelease(Type& pObjToRelease) { if(pObjToRelease) { pObjToRelease->Release(); pObjToRelease = 0; } } // CD2dProgressBar //D2dProgressBar.cpp CD2dProgressBar::CD2dProgressBar(void) :m_ProgressValue(0) ,m_pD2d1Factory(NULL) ,m_pRenderTarget(NULL) ,m_pSolidColorBrush(NULL) ,m_pLinearGradientBrush(NULL) { } CD2dProgressBar::~CD2dProgressBar(void) { DestoryResource(); } void CD2dProgressBar::SetValue(int progressValue) { ASSERT((progressValue>=0) && (progressValue<=100)); m_ProgressValue = progressValue; Invalidate(FALSE); //Repaint } int CD2dProgressBar::GetValue(void) { return m_ProgressValue; } BEGIN_MESSAGE_MAP(CD2dProgressBar, CWnd) ON_WM_PAINT() ON_WM_ERASEBKGND() ON_WM_SIZE() ON_WM_LBUTTONUP() END_MESSAGE_MAP() void CD2dProgressBar::OnPaint() { CPaintDC dc(this); // device context for painting // TODO: Add your message handler code here // Do not call CWnd::OnPaint() for painting messages Render(); } BOOL CD2dProgressBar::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default return TRUE; //return CWnd::OnEraseBkgnd(pDC); } BOOL CD2dProgressBar::CreateDeviceIndependentResource() { HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,&m_pD2d1Factory); ASSERT(!hr); return SUCCEEDED(hr); } BOOL CD2dProgressBar::CreateDeviceDependentResource() { ASSERT(m_pD2d1Factory != NULL); ASSERT(m_pRenderTarget == NULL); CRect rc; GetClientRect(&rc); D2D1_RENDER_TARGET_PROPERTIES prop = RenderTargetProperties(); HRESULT hr = m_pD2d1Factory->CreateHwndRenderTarget( prop, HwndRenderTargetProperties(m_hWnd,SizeU(rc.Width(),rc.Height())), &m_pRenderTarget); ASSERT(!hr); if (SUCCEEDED(hr)) { hr = m_pRenderTarget->CreateSolidColorBrush(ColorF(ColorF::LightSeaGreen),&m_pSolidColorBrush); ASSERT(!hr); ID2D1GradientStopCollection* pGradientStops = NULL; D2D1_GRADIENT_STOP stops[2]; stops[0].color = ColorF(ColorF::Yellow); stops[0].position = 0.0f; stops[1].color = ColorF(ColorF::Red); stops[1].position = 1.0f; HRESULT hr = m_pRenderTarget->CreateGradientStopCollection( stops, 2, D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &pGradientStops); ASSERT(!hr); //Create linear gradient brush hr = m_pRenderTarget->CreateLinearGradientBrush( LinearGradientBrushProperties(Point2F(0,0),Point2F(0,40)), pGradientStops, &m_pLinearGradientBrush); ASSERT(!hr); SafeRelease(pGradientStops); } return SUCCEEDED(hr); } void CD2dProgressBar::DiscardDeviceDependentResource() { SafeRelease(m_pLinearGradientBrush); SafeRelease(m_pSolidColorBrush); SafeRelease(m_pRenderTarget); } void CD2dProgressBar::DestoryResource() { DiscardDeviceDependentResource(); SafeRelease(m_pD2d1Factory); } void CD2dProgressBar::Render() { ASSERT(m_pD2d1Factory); if (m_pRenderTarget == NULL) { BOOL succeeded = CreateDeviceDependentResource(); if (!succeeded) return; } if (m_pRenderTarget->CheckWindowState()& D2D1_WINDOW_STATE_OCCLUDED) return; CRect rc; GetClientRect(&rc); //rc.DeflateRect(8,8); m_pRenderTarget->BeginDraw(); m_pRenderTarget->Clear(ColorF(ColorF::LightGray)); m_pRenderTarget->SetTransform(Matrix3x2F::Identity()); D2D1_ROUNDED_RECT boundRect = D2D1::RoundedRect(RectF(rc.left,rc.top,rc.right,rc.bottom),5,5); int width = (rc.right-rc.left)*m_ProgressValue/100; D2D1_ROUNDED_RECT filledRect = D2D1::RoundedRect(RectF(rc.left,rc.top,rc.left+width,rc.bottom),5,5); //Draw the outline m_pRenderTarget->DrawRoundedRectangle(boundRect,m_pSolidColorBrush); //Fill the outline m_pRenderTarget->FillRoundedRectangle(filledRect,m_pLinearGradientBrush); HRESULT hr = m_pRenderTarget->EndDraw(); if (hr == D2DERR_RECREATE_TARGET) { DiscardDeviceDependentResource(); } } void CD2dProgressBar::ResizeRenderTarget(int width,int height) { if (m_pRenderTarget) { m_pRenderTarget->Resize(SizeU(width,height)); } } BOOL CD2dProgressBar::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Add your specialized code here and/or call the base class BOOL succeeded = CreateDeviceIndependentResource(); ASSERT(succeeded); return CWnd::PreCreateWindow(cs); } void CD2dProgressBar::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); // TODO: Add your message handler code here ResizeRenderTarget(cx,cy); Invalidate(FALSE); //Repaint } void CD2dProgressBar::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CRect rc; GetClientRect(&rc); ASSERT(point.x >= rc.left && point.x <= rc.right && point.y >= rc.top && point.y <= rc.bottom); m_ProgressValue = 100*(point.x - rc.left)/rc.Width(); Invalidate(FALSE); //Repaint CWnd::OnLButtonUp(nFlags, point); }
3.测试所创建的控件
创建一个简单的MFC对话框,在OnInitDialog()函数中添加如下代码:实际运行效果:相关文章推荐
- Direct2D绘制的MFC控件
- 完美自绘制CListCtrl控件2[MFC]
- VS2010-MFC:用OpenGL在对话框中的PictureControl(图片控件)中绘制三维模型,可旋转、平移、缩放,可用于三维模型的预览
- C#.NET常见问题(FAQ)-如何使用2D绘图控件ZedGraph绘制坐标轴和坐标曲线
- MFC-WM_CTLCOLOR消息绘制控件颜色
- High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件
- 图表控件TeeChart干货分享(绘制2D、3D实时曲线---VC++示例源代码--网络首发)
- 使用WIC将Direct2D绘制的图形保存为文件
- 使用WIC将Direct2D绘制的图形保存为文件
- Direct2D WIC绘制图片
- MFC控件的绘制与响应顺序——ZOrder
- MFC简单皮肤颜色绘制(SetDialogBkColor不再被支持,看 WM_CTLCOLOR消息如何百变控件颜色)
- VC/MFC CStatic 绘制一个时间选择控件
- C#.NET常见问题(FAQ)-如何使用2D绘图控件ZedGraph绘制坐标轴和坐标曲线
- Direct2D DirectWrite绘制文字
- directdraw YUV直接显示,怎么显示在MFC的picture控件上呢?
- MFC 绘制对话框背景,不绘制子控件
- MFC 绘制界面 控件以及屏幕闪烁的问题
- 利用MFC进行IP地址控件的绘制
- 【Android知识点精讲】(2)2D绘制与控件绘制