1 #include <Windows.h>
2 #include <tchar.h>
3 #include <math.h>
4 BOOLEAN InitWindowClass(HINSTANCE hInstance, int nCmdShow);
5 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
6 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
7 {
8 MSG msg;
9 if (!InitWindowClass(hInstance, nCmdShow))
10 {
11 MessageBox(NULL, L"创建窗口失败!", _T("创建窗口"), NULL);
12 return 1;
13 }
14 while (GetMessage(&msg, NULL, 0, 0))
15 {
16 TranslateMessage(&msg);
17 DispatchMessage(&msg);
18 }
19 return(int)msg.wParam;
20 }
21
22 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
23 {
24 HDC hDC;
25 PAINTSTRUCT ps;
26 HBRUSH hBrush;
27 HPEN hPen;
28 RECT clientRect;
29 static RECT oldClientRect = { 0, 0, 0, 0 };
30 float sita = 0;
31 int a[4] = { 75, 50, 60, 90 }, maxValue, i, xOrg, yOrg, deltaX, deltaY, xBegin, yBegin, xEnd, yEnd, s = 0;
32 int hatchBrushStyle[4] = { HS_BDIAGONAL, HS_FDIAGONAL, HS_CROSS, HS_DIAGCROSS }; //四个阴影样式
33 COLORREF colorIndex[4] = { RGB(255, 0, 0), RGB(0, 255, 0), RGB(0, 0, 255), RGB(255, 0, 255) }; //四种颜色
34 switch (message)
35 {
36 case WM_PAINT:
37 maxValue = a[0];
38 for (i = 0; i < 4; i++)
39 {
40 s += a[i];
41 if (a[i]>maxValue)
42 maxValue = a[i];
43 } //计算所有数据总值和最大值
44 hDC = BeginPaint(hWnd, &ps);
45 GetClientRect(hWnd, &clientRect); //获取用户区的尺寸
46 if ((clientRect.right - clientRect.left) < 300 || (clientRect.bottom - clientRect.top) < 300) //判断屏幕尺寸
47 {
48 MessageBox(hWnd, L"屏幕尺寸大小,无法绘图!", L"错误信息", 0);
49 //EndPaint(hWnd, &ps); //结束绘图
50 break;
51 }
52 hPen = (HPEN)GetStockObject(BLACK_PEN); //设置画笔为系统预定义的黑色画笔
53 SelectObject(hDC, hPen); //选择画笔
54 Rectangle(hDC, clientRect.left + 10, clientRect.top + 10, clientRect.right - 10, clientRect.bottom - 10);
55 MoveToEx(hDC, (clientRect.left + clientRect.right) / 2, clientRect.top + 10, NULL);
56 LineTo(hDC, (clientRect.left + clientRect.right) / 2, clientRect.bottom - 10); //从窗口的中间将窗口分为左右两部分
57 //------------------------------以下是在左半部分用柱形图表示的数据分布图------------------------------
58 xOrg = clientRect.left + 60;
59 yOrg = clientRect.bottom - 60; //柱形图的坐标原点
60 xEnd = (clientRect.left + clientRect.right) / 2 - 50; //坐标轴的最右边
61 yEnd = yOrg;
62 deltaX = (xEnd - xOrg - 100) / 4; //计算水平坐标的单位像素
63 MoveToEx(hDC, xOrg, yOrg, NULL);
64 LineTo(hDC, xEnd, yEnd); //画水平坐标轴
65 xEnd = xOrg;
66 yEnd = clientRect.top + 60; //坐标轴的最上边
67 MoveToEx(hDC, xOrg, yOrg, NULL);
68 LineTo(hDC, xEnd, yEnd); //画垂直坐标轴
69 deltaY = (yOrg - yEnd - 100) / maxValue; //计算垂直坐标的单位像素
70 hPen = CreatePen(PS_SOLID, 1, RGB(127, 127, 127)); //用灰色作为画笔
71 SelectObject(hDC, hPen); //选择画笔
72 for (i = 0; i < 4; i++)
73 {
74 hBrush = CreateHatchBrush(hatchBrushStyle[i], colorIndex[i]); //创建带阴影的画刷
75 SelectObject(hDC, hBrush); //选择画刷
76 xBegin = xOrg + deltaX*i;
77 yBegin = yOrg;
78 xEnd = xBegin + deltaX;
79 yEnd = yOrg - a[i] * deltaY;
80 Rectangle(hDC, xBegin, yBegin, xEnd, yEnd); //每一部分的柱形图
81 }
82 //------------------------------以下是在右半部分用饼图表示的数据分布图------------------------------
83 xOrg = clientRect.left + (clientRect.right - clientRect.left) * 3 / 4 + 10;
84 yOrg = clientRect.top + (clientRect.bottom - clientRect.top) / 2 + 10; //xOrg,yOrg为右半部分的中心点坐标
85 deltaX = deltaY = min((clientRect.right - clientRect.left) / 4, (clientRect.bottom - clientRect.top) / 2) - 50;
86 xBegin = xOrg + 10;
87 yBegin = yOrg;
88 for (i = 0; i < 4; i++)
89 {
90 hBrush = CreateSolidBrush(colorIndex[i]); //创建单色的画刷
91 SelectObject(hDC, hBrush); //选择画刷
92 sita = sita + 2 * 3.1415*a[i] / s;
93 xEnd = xOrg + 10 * cos(sita);
94 yEnd = yOrg - 10 * sin(sita); //计算饼图终点的坐标
95 Pie(hDC, xOrg - deltaX, yOrg - deltaY, xOrg + deltaX, yOrg + deltaY, xBegin, yBegin, xEnd, yEnd);//各部分饼图
96 xBegin = xEnd;
97 yBegin = yEnd; //下次饼图起点的坐标
98 }
99 DeleteObject(hPen);
100 DeleteObject(hBrush);
101 EndPaint(hWnd, &ps); //结束绘图
102 break;
103 case WM_SIZE: //窗口尺寸发生变化时,应刷新窗口
104 InvalidateRect(hWnd, NULL, true);
105 break;
106 case WM_DESTROY:
107 PostQuitMessage(0); //调用PostQuitMessage发出WM_QUIT消息
108 break;
109 default:
110 return DefWindowProc(hWnd, message, wParam, lParam); //默认时采用系统消息默认处理函数
111 break;
112 }
113 return 0;
114 }
115 BOOLEAN InitWindowClass(HINSTANCE hInstance, int nCmdShow)
116 {
117 WNDCLASSEX wcex;
118 HWND hWnd;
119 TCHAR szWindowClass[] = L"窗口示例";
120 TCHAR szTitle[] = L"柱形图及饼图显示数据统计";
121 wcex.cbSize = sizeof(WNDCLASSEX);
122 wcex.style = 0;
123 wcex.lpfnWndProc = WndProc;
124 wcex.cbClsExtra = 0;
125 wcex.cbWndExtra = 0;
126 wcex.hInstance = hInstance;
127 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
128 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
129 wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
130 wcex.lpszMenuName = NULL;
131 wcex.lpszClassName = szWindowClass;
132 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
133 if (!RegisterClassEx(&wcex))
134 return FALSE;
135 hWnd = CreateWindow(
136 szWindowClass,
137 szTitle,
138 WS_OVERLAPPEDWINDOW,
139 CW_USEDEFAULT, CW_USEDEFAULT,
140 CW_USEDEFAULT, CW_USEDEFAULT,
141 NULL,
142 NULL,
143 hInstance,
144 NULL
145 );
146 if (!hWnd)
147 return FALSE;
148 ShowWindow(hWnd, nCmdShow);
149 UpdateWindow(hWnd);
150 return TRUE;
151 }