1: //D2dProgressBar.h
2: #pragma once3:4: #include "afxwin.h"
5: #include "D2dPrerequisite.h"
6:7: class CD2dProgressBar : public CWnd8: {9: public:
10: CD2dProgressBar(void);
11: ~CD2dProgressBar(void);
12:13: private:
14: ID2D1Factory* m_pD2d1Factory;15: ID2D1HwndRenderTarget* m_pRenderTarget;16: ID2D1SolidColorBrush* m_pSolidColorBrush;17: ID2D1LinearGradientBrush* m_pLinearGradientBrush;18:19: private:
20: BOOL CreateDeviceIndependentResource();21: BOOL CreateDeviceDependentResource();22: void DiscardDeviceDependentResource();
23: void DestoryResource();
24:25: void Render();
26: void ResizeRenderTarget(int width,int height);27:28: public:
29: void SetValue(int progressValue);30: int GetValue(void);31:32: private:
33: int m_ProgressValue;
34:35: public:
36: DECLARE_MESSAGE_MAP()37: afx_msg void OnPaint();
38: afx_msg BOOL OnEraseBkgnd(CDC* pDC);39: afx_msg void OnSize(UINT nType, int cx, int cy);40: afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
41: virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
42: };
1: //D2dProgressBar.cpp
2: #include "StdAfx.h"
3: #include "D2dProgressBar.h"
4: using namespace D2D1;5:6: CD2dProgressBar::CD2dProgressBar(void)
7: :m_ProgressValue(0)8: ,m_pD2d1Factory(NULL)9: ,m_pRenderTarget(NULL)10: ,m_pSolidColorBrush(NULL)11: ,m_pLinearGradientBrush(NULL)12: {13: }14:15: CD2dProgressBar::~CD2dProgressBar(void)
16: {17: DestoryResource();18: }19:20: void CD2dProgressBar::SetValue(int progressValue)21: {22: ASSERT((progressValue>=0) && (progressValue<=100));23: m_ProgressValue = progressValue;24: Invalidate(FALSE); //Repaint
25: }26:27: int CD2dProgressBar::GetValue(void)28: {29: return m_ProgressValue;
30: }31:32: BEGIN_MESSAGE_MAP(CD2dProgressBar, CWnd)33: ON_WM_PAINT()34: ON_WM_ERASEBKGND()35: ON_WM_SIZE()36: ON_WM_LBUTTONUP()37: END_MESSAGE_MAP()38:39: void CD2dProgressBar::OnPaint()
40: {41: CPaintDC dc(this); // device context for painting42: // TODO: Add your message handler code here
43: // Do not call CWnd::OnPaint() for painting messages
44: Render();45: }46:47: BOOL CD2dProgressBar::OnEraseBkgnd(CDC* pDC)48: {49: // TODO: Add your message handler code here and/or call default
50: return TRUE;
51:52: //return CWnd::OnEraseBkgnd(pDC);
53: }54:55: BOOL CD2dProgressBar::CreateDeviceIndependentResource()56: {57: HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,&m_pD2d1Factory);58: ASSERTHR(hr);59: return SUCCEEDED(hr);
60: }61:62: BOOL CD2dProgressBar::CreateDeviceDependentResource()63: {64: ASSERT(m_pD2d1Factory != NULL);65: ASSERT(m_pRenderTarget == NULL);66:67: CRect rc;68: GetClientRect(&rc);69: D2D1_RENDER_TARGET_PROPERTIES prop = RenderTargetProperties();70: HRESULT hr = m_pD2d1Factory->CreateHwndRenderTarget(71: prop,72: HwndRenderTargetProperties(m_hWnd,SizeU(rc.Width(),rc.Height())),73: &m_pRenderTarget);74: ASSERTHR(hr);75: if (SUCCEEDED(hr))
76: {77: hr = m_pRenderTarget->CreateSolidColorBrush(ColorF(ColorF::LightSeaGreen),&m_pSolidColorBrush);78: ASSERTHR(hr);79:80: ID2D1GradientStopCollection* pGradientStops = NULL;81: D2D1_GRADIENT_STOP stops[2];82: stops[0].color = ColorF(ColorF::Yellow);83: stops[0].position = 0.0f;84: stops[1].color = ColorF(ColorF::Red);85: stops[1].position = 1.0f;86: HRESULT hr = m_pRenderTarget->CreateGradientStopCollection(87: stops,88: 2,89: D2D1_GAMMA_2_2,90: D2D1_EXTEND_MODE_CLAMP,91: &pGradientStops);92: ASSERTHR(hr);93:94: //Create linear gradient brush
95: hr = m_pRenderTarget->CreateLinearGradientBrush(96: LinearGradientBrushProperties(Point2F(0,0),Point2F(0,40)),97: pGradientStops,98: &m_pLinearGradientBrush);99: ASSERTHR(hr);100:101: SafeRelease(&pGradientStops);102: }103: return SUCCEEDED(hr);
104: }105:106: void CD2dProgressBar::DiscardDeviceDependentResource()
107: {108: SafeRelease(&m_pLinearGradientBrush);109: SafeRelease(&m_pSolidColorBrush);110: SafeRelease(&m_pRenderTarget);111: }112:113: void CD2dProgressBar::DestoryResource()
114: {115: DiscardDeviceDependentResource();116:117: SafeRelease(&m_pD2d1Factory);118: }119:120: void CD2dProgressBar::Render()
121: {122: ASSERT(m_pD2d1Factory);123: if (m_pRenderTarget == NULL)
124: {125: BOOL succeeded = CreateDeviceDependentResource();126: if (!succeeded)
127: return;
128: }129:130: if (m_pRenderTarget->CheckWindowState()& D2D1_WINDOW_STATE_OCCLUDED)
131: return;
132:133: CRect rc;134: GetClientRect(&rc);135: //rc.DeflateRect(8,8);
136:137: m_pRenderTarget->BeginDraw();138: m_pRenderTarget->Clear(ColorF(ColorF::LightGray));139: m_pRenderTarget->SetTransform(Matrix3x2F::Identity());140: D2D1_ROUNDED_RECT boundRect = D2D1::RoundedRect(RectF(rc.left,rc.top,rc.right,rc.bottom),5,5);141: int width = (rc.right-rc.left)*m_ProgressValue/100;
142: D2D1_ROUNDED_RECT filledRect = D2D1::RoundedRect(RectF(rc.left,rc.top,rc.left+width,rc.bottom),5,5);143: //Draw the outline
144: m_pRenderTarget->DrawRoundedRectangle(boundRect,m_pSolidColorBrush);145: //Fill the outline
146: m_pRenderTarget->FillRoundedRectangle(filledRect,m_pLinearGradientBrush);147: HRESULT hr = m_pRenderTarget->EndDraw();148: if (hr == D2DERR_RECREATE_TARGET)
149: {150: DiscardDeviceDependentResource();151: }152: }153:154: void CD2dProgressBar::ResizeRenderTarget(int width,int height)155: {156: if (m_pRenderTarget)
157: {158: m_pRenderTarget->Resize(SizeU(width,height));159: }160: }161:162: BOOL CD2dProgressBar::PreCreateWindow(CREATESTRUCT& cs)163: {164: // TODO: Add your specialized code here and/or call the base class
165: BOOL succeeded = CreateDeviceIndependentResource();166: ASSERT(succeeded);167:168: return CWnd::PreCreateWindow(cs);
169: }170:171: void CD2dProgressBar::OnSize(UINT nType, int cx, int cy)172: {173: CWnd::OnSize(nType, cx, cy);174:175: // TODO: Add your message handler code here
176: ResizeRenderTarget(cx,cy);177: Invalidate(FALSE); //Repaint
178: }179:180: void CD2dProgressBar::OnLButtonUp(UINT nFlags, CPoint point)
181: {182: // TODO: Add your message handler code here and/or call default
183: CRect rc;184: GetClientRect(&rc);185: ASSERT(point.x >= rc.left && point.x <= rc.right186: && point.y >= rc.top && point.y <= rc.bottom);187:188: m_ProgressValue = 100*(point.x - rc.left)/rc.Width();189: Invalidate(FALSE); //Repaint
190:191: CWnd::OnLButtonUp(nFlags, point);192: }
创建一个简单的MFC对话框,在OnInitDialog()函数中添加如下代码:
1: // TODO: Add extra initialization here
2: this->ModifyStyle(0,WS_CLIPCHILDREN); //Modify the window style of the parent window3:4: //Create our Direct2D control and set it's properties
5: m_ProgressBar.Create(NULL,_T(""),WS_CHILD|WS_VISIBLE,CRect(50,50,150,100),this,1234);
6: m_ProgressBar.SetValue(40);
实际运行效果: