弧、饼、弦的绘制是用Arc()、Pie()、Chord()这三个函数来完成的,这三个函数的参数和使用方法完全一致。
BOOL Arc( BOOL Pie( BOOL Chord(
HDC hdc, HDC hdc, HDC hdc, //设备句柄
int nLeftRect, int nLeftRect, int nLeftRect, //包含整个椭圆的矩形的左上角x座标
int nTopRect, int nTopRect, int nTopRect, //包含整个椭圆的矩形的左上角y座标
int nRightRect, int nRightRect, int nRightRect, //包含整个椭圆的矩形的右下角x座标
int nBottomRect, int nBottomRect, int nBottomRect, //包含整个椭圆的矩形的右下角y座标
int nXRadial1, int nXRadial1, int nXRadial1, //起点半径的点的x座标
int nYRadial1, int nYRadial1, int nYRadial1, //起点半径的点的y座标
int nXRadial2, int nXRadial2, int nXRadial2, //终点半径的点的x座标
int nYRadial2 int nYRadial2 int nYRadial2 //终点半径的点的y座标
); ); );
上面是Arc()、Pie()、Chord()这三个函数的原型。小雅在5年前学习这三个函数时,怎么也不能理解MSDN中对第2到第5个参数的说明,譬如第二个参数的说明是“包含弧线的矩形的左上角x座标”,我想我任意画一段弧线,这矩形座标怎么确定?反复拍head之后豁然开朗,原来,弧线是椭圆的一部分,而椭圆有一个外切矩形,于是,我用这个外切矩形的左上右下座标一试,果然OK。
随后又对后4个参数发生了疑问,这起点半径和终点半径我可怎么确定?当然现在搞 清楚了,原来这起点和终点座标并否一个点,而是从矩形的中心开始的一条射线上的任一点,所画的结果都是一 样。例如,下例中32行,只要小于rc.right/2都是一样的结果,甚至超出窗口的点也可以,譬如将32行的10改成-100,结果一样。
起点和终点确定了之后,又有一个问题,即同样起点和终点应该有两条弧线,究竟算 是哪一条?经过实践终于知道是起点到终点按逆时针方向的弧线。后来发现这一点在MSDN上有说明。好了,了解 了这些内容就可以做出来了,下面看一下函数。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{;
PAINTSTRUCT ps;
HDC hdc;
HPEN hPen, hOldPen;
HBRUSH hBrush, hOldBrush;
RECT rc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rc);
hPen = CreatePen(PS_SOLID, 1, RGB(255, 100, 0)); //红色实线画笔
hOldPen = (HPEN)SelectObject(hdc, hPen);
hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 255, 0)); //绿色方格刷
hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Rectangle(hdc,10, 10, rc.right-10, rc.bottom-10); //画一个矩形作参照
DeleteObject(hPen);
DeleteObject(hBrush);
hPen = CreatePen(PS_SOLID, 1, RGB(0, 100, 255)); //兰色实线画笔
SelectObject(hdc, hPen);
hBrush = CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 255)); //45度斜线刷
SelectObject(hdc, hBrush);
Pie(hdc,
10, //矩形左上角x座标
10, //矩形左上角y座标
rc.right-10, //矩形右下角x座标
rc.bottom-10, //矩形右下角y座标
10, //起点x座标
re.bottom/2, //起点y座标
rc.right/2, //终点x座标
10 //终点y座标
); //画饼图
MoveToEx(hdc, 10, 10, NULL); //移动到矩形左上角
LineTo(hdc, rc.right-10, rc.bottom-10); //画参照用的对角线
MoveToEx(hdc, 10, rc.bottom-10,NULL); //移动到矩形左下角
LineTo(hdc, rc.right-10, 10); //画参照用的对角线
SelectObject(hdc, hOldPen); //恢复旧笔
SelectObject(hdc, hOldBrush); //恢复旧刷
DeleteObject(hPen); //删除新笔
DeleteObject(hBrush); //删除新刷
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
将最后4个参数的起点和终点换一下,便得到另外一部分图形。下面例子请参考。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{;
PAINTSTRUCT ps;
HDC hdc;
RECT rc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rc1);
rc2 = rc1;
rc1.bottom = rc1.bottom / 2 + 5;
Draw(hdc, rc1, FALSE);
rc2.top = rc2.bottom / 2 - 5;
Draw(hdc, rc2, TRUE);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void Draw(HDC hdc, RECT rc, BOOL flg) {
HPEN hPen, hOldPen;
HBRUSH hBrush, hOldBrush;
//画一个矩形作参照
hPen = CreatePen(PS_SOLID, 1, RGB(255, 100, 0));
hOldPen = (HPEN)SelectObject(hdc, hPen);
hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 255, 0));
hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
Rectangle(hdc,rc.left+10, rc.top+10, rc.right-10, rc.bottom-10);
DeleteObject(hPen);
DeleteObject(hBrush);
hPen = CreatePen(PS_SOLID, 1, RGB(0, 100, 255)); //兰色实线画笔
SelectObject(hdc, hPen);
hBrush = CreateHatchBrush(HS_BDIAGONAL, RGB(0, 0, 255)); //45度斜线刷
SelectObject(hdc, hBrush);
if (flg) {
Pie(hdc, rc.left+10, rc.top+10, rc.right-10, rc.bottom-10,
rc.left+10, (rc.top+rc.bottom)/2, (rc.left+rc.right)/2, rc.top+10); //画饼图(下半个)
} else {
Pie(hdc, rc.left+10, rc.top+10, rc.right-10, rc.bottom-10,
(rc.left+rc.right)/2, rc.top+10, rc.left+10, (rc.top+rc.bottom)/2); //画饼图(上半个)
}
//画参照用的对角线
MoveToEx(hdc, rc.left+10, rc.top+10, NULL);
LineTo(hdc, rc.right-10, rc.bottom-10);
MoveToEx(hdc, rc.left+10, rc.bottom-10,NULL);
LineTo(hdc, rc.right-10, rc.top+10);
//恢复旧笔刷,删除新笔刷
SelectObject(hdc, hOldPen);
SelectObject(hdc, hOldBrush);
DeleteObject(hPen);
DeleteObject(hBrush);
}
将pie()函数换成arc()函数和chord()函数便可画出弧和弦的图形。
//......(省略)
if(flg) { Chord(hdc, rc.left+10, rc.top+10, rc.right-10, rc.bottom-10, rc.left+10, (rc.top+rc.bottom)/2, (rc.left+rc.right)/2, rc.top+10 ); //画弦图 }else{ Arc(hdc, rc.left+10, rc.top+10, rc.right-10, rc.bottom-10, (rc.left+rc.right)/2, rc.top+10, rc.left+10, (rc.top+rc.bottom)/2 ); //画弧线 } //......(省略)
当上例中的起点和终点相同时,便画成了椭圆。当然,画椭圆还有另外一个函数Ellipse()。
//......(省略)
if(flg) { Chord(hdc, rc.left+10, rc.top+10, rc.right-10, 10, 20, 10, 20, ); //画弦图 }else{ Arc(hdc, rc.left+10, rc.top+10, rc.right-10, rc.bottom-10, 30, 25, 30, 25, ); //画弧线 } //......(省略)