弧、饼、弦的绘制是用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
nYRadial2int
nYRadial2int
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, ); //画弧线 } //......(省略)