[toc]

#C++使用Direct2D画点线面

1.Direct2D绘制点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <windows.h>
#include <d2d1.h>

#pragma comment(lib, "d2d1.lib")

// 全局变量
ID2D1Factory* pFactory = NULL;
ID2D1HwndRenderTarget* pRenderTarget = NULL;

void CreateGraphics(HWND hwnd) {
// 创建Direct2D工厂
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);

// 创建渲染目标
RECT rc;
GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
pFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(hwnd, size),
&pRenderTarget
);
}

void Render() {
// 清除背景
pRenderTarget->BeginDraw();
pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));

// 创建画刷
ID2D1SolidColorBrush* pBrush;
pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &pBrush);

// 绘制点
const D2D1_POINT_2F points[] = {
D2D1::Point2F(100, 100),
D2D1::Point2F(150, 150),
D2D1::Point2F(200, 200),
D2D1::Point2F(250, 250),
D2D1::Point2F(300, 300)
};

for (const auto& point : points) {
pRenderTarget->FillEllipse(D2D1::Ellipse(point, 5.0f, 5.0f), pBrush); // 绘制半径为5的圆形作为点
}

// 释放画刷
pBrush->Release();

// 结束绘制
pRenderTarget->EndDraw();
}

// 窗口过程函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
CreateGraphics(hwnd); // 创建图形
break;

case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

// 清除窗口背景
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

// 调用绘制点的函数
Render();

EndPaint(hwnd, &ps);
} break;

case WM_SIZE: {
if (pRenderTarget) {
RECT rc;
GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
pRenderTarget->Resize(size);
}
} break;

case WM_DESTROY:
if (pRenderTarget) {
pRenderTarget->Release();
pRenderTarget = NULL;
}
if (pFactory) {
pFactory->Release();
pFactory = NULL;
}
PostQuitMessage(0);
return 0;

default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}

// WinMain 函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
const WCHAR CLASS_NAME[] = L"Point Window Class";

WNDCLASSW wc = { 0 };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;

RegisterClass(&wc);

HWND hwnd = CreateWindowExW(
0, CLASS_NAME, L"Draw Points",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 400,
NULL, NULL, hInstance, NULL
);

ShowWindow(hwnd, nShowCmd);

// 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

2.绘制直线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <windows.h>
#include <d2d1.h>

#pragma comment(lib, "d2d1.lib")

// 全局变量
ID2D1Factory* pFactory = NULL;
ID2D1HwndRenderTarget* pRenderTarget = NULL;

void CreateGraphics(HWND hwnd) {
// 创建Direct2D工厂
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);

// 创建渲染目标
RECT rc;
GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
pFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(hwnd, size),
&pRenderTarget
);
}

void Render() {
// 清除背景
pRenderTarget->BeginDraw();
pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));

// 创建画刷
ID2D1SolidColorBrush* pBrush;
pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &pBrush);

// 绘制直线
pRenderTarget->DrawLine(
D2D1::Point2F(50, 50), // 起点
D2D1::Point2F(350, 350), // 终点
pBrush, // 画刷
2.0f // 线宽
);

// 释放画刷
pBrush->Release();

// 结束绘制
pRenderTarget->EndDraw();
}

// 窗口过程函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
CreateGraphics(hwnd); // 创建图形
break;

case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

// 清除窗口背景
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

// 调用绘制直线的函数
Render();

EndPaint(hwnd, &ps);
} break;

case WM_SIZE: {
if (pRenderTarget) {
RECT rc;
GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
pRenderTarget->Resize(size);
}
} break;

case WM_DESTROY:
if (pRenderTarget) {
pRenderTarget->Release();
pRenderTarget = NULL;
}
if (pFactory) {
pFactory->Release();
pFactory = NULL;
}
PostQuitMessage(0);
return 0;

default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}

// WinMain 函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
const WCHAR CLASS_NAME[] = L"Line Window Class";

WNDCLASSW wc = { 0 };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;

RegisterClass(&wc);

HWND hwnd = CreateWindowExW(
0, CLASS_NAME, L"Draw a Line",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 400,
NULL, NULL, hInstance, NULL
);

ShowWindow(hwnd, nShowCmd);

// 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

3.绘制矩形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <windows.h>
#include <d2d1.h>

#pragma comment(lib, "d2d1.lib")

// 全局变量
ID2D1Factory* pFactory = NULL;
ID2D1HwndRenderTarget* pRenderTarget = NULL;

void CreateGraphics(HWND hwnd) {
// 创建Direct2D工厂
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);

// 创建渲染目标
RECT rc;
GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
pFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(hwnd, size),
&pRenderTarget
);
}

void Render() {
// 清除背景
pRenderTarget->BeginDraw();
pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));

// 绘制图形(例如:矩形)
ID2D1SolidColorBrush* pBrush;
pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &pBrush);
pRenderTarget->FillRectangle(D2D1::RectF(100, 100, 200, 200), pBrush);
pBrush->Release();

// 结束绘制
pRenderTarget->EndDraw();
}

// 绘制球形的函数
void DrawSphere(HDC hdc) {
// 在这里调用 Render 函数进行绘制
if (pRenderTarget) {
Render();
}
}

// 窗口过程函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
CreateGraphics(hwnd); // 创建图形
break;

case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

// 清除窗口背景
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

// 调用绘制球形的函数
DrawSphere(hdc);

EndPaint(hwnd, &ps);
} break;
case WM_SIZE: {
if (pRenderTarget) {
RECT rc;
GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
pRenderTarget->Resize(size);
}
} break;
case WM_DESTROY:
if (pRenderTarget) {
pRenderTarget->Release();
pRenderTarget = NULL;
}
if (pFactory) {
pFactory->Release();
pFactory = NULL;
}
PostQuitMessage(0);
return 0;

default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}

// WinMain 函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
const WCHAR CLASS_NAME[] = L"Sphere Window Class";

WNDCLASSW wc = { 0 };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;

RegisterClass(&wc);

HWND hwnd = CreateWindowExW(
0, CLASS_NAME, L"Draw a Sphere",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 400,
NULL, NULL, hInstance, NULL
);

ShowWindow(hwnd, nShowCmd);

// 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}

4.绘制其他图形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <windows.h>
#include <d2d1.h>

#pragma comment(lib, "d2d1.lib")

// 全局变量
ID2D1Factory* pFactory = NULL;
ID2D1HwndRenderTarget* pRenderTarget = NULL;

void CreateGraphics(HWND hwnd) {
// 创建Direct2D工厂
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);

// 创建渲染目标
RECT rc;
GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
pFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(hwnd, size),
&pRenderTarget
);
}

void Render() {
// 清除背景
pRenderTarget->BeginDraw();
pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));

// 创建画刷
ID2D1SolidColorBrush* pBrush;
pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &pBrush);

// 绘制直线
pRenderTarget->DrawLine(D2D1::Point2F(50, 50), D2D1::Point2F(350, 50), pBrush, 2.0f);

// 绘制矩形
pRenderTarget->FillRectangle(D2D1::RectF(50, 70, 150, 170), pBrush);

// 绘制圆形
pRenderTarget->FillEllipse(D2D1::Ellipse(D2D1::Point2F(250, 120), 40.0f, 40.0f), pBrush);

// 创建多边形几何体
ID2D1PathGeometry* pPolygonGeometry;
pFactory->CreatePathGeometry(&pPolygonGeometry);

ID2D1GeometrySink* pSink;
pPolygonGeometry->Open(&pSink);
pSink->BeginFigure(D2D1::Point2F(50, 200), D2D1_FIGURE_BEGIN_FILLED);
pSink->AddLine(D2D1::Point2F(100, 250));
pSink->AddLine(D2D1::Point2F(0, 250));
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
pSink->Close();
pSink->Release();

// 填充多边形
pRenderTarget->FillGeometry(pPolygonGeometry, pBrush, NULL);

// 释放几何体
pPolygonGeometry->Release();

// 释放画刷
pBrush->Release();

// 结束绘制
pRenderTarget->EndDraw();
}

// 窗口过程函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE:
CreateGraphics(hwnd); // 创建图形
break;

case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

// 清除窗口背景
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

// 调用绘制的函数
Render();

EndPaint(hwnd, &ps);
} break;

case WM_SIZE: {
if (pRenderTarget) {
RECT rc;
GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
pRenderTarget->Resize(size);
}
} break;

case WM_DESTROY:
if (pRenderTarget) {
pRenderTarget->Release();
pRenderTarget = NULL;
}
if (pFactory) {
pFactory->Release();
pFactory = NULL;
}
PostQuitMessage(0);
return 0;

default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}

// WinMain 函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
const WCHAR CLASS_NAME[] = L"Polygon Window Class";

WNDCLASSW wc = { 0 };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;

RegisterClass(&wc);

HWND hwnd = CreateWindowExW(
0, CLASS_NAME, L"Draw Polygon",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 400,
NULL, NULL, hInstance, NULL
);

ShowWindow(hwnd, nShowCmd);

// 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;
}