这一章比较简单,是画封闭图形的例子,画圆、画方框等都是同样原理,要注意的是背景的设置。
上一章的程序的基础上,将画线语句换成画圆的语句就可以了。画圆是用Ellipse()函数。
BOOL Ellipse( HDC hdc, //HDCint
nLeftRect, //外切矩形的“左上”x座标int
nTopRect, //外切矩形的“左上”y座标int
nRightRect, //外切矩形的“右下”x座标int
nBottomRect //外切矩形的“右下”y座标 );
LONG clsCur;bool
bDrawing =false
; //画图状态为true POINTS start, end, prev; //开始点、结束点、前一个移动点 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {switch
(message) { //与上例相同,省略 }return
0; } //作图 void Draw(HDC hdc, POINTS beg, POINTS end) { SetROP2(hdc, R2_NOT); //设置前景配色方式为象素反转 Ellipse(hdc, beg.x, beg.y, end.x, end.y); //画圆return
; } void Draw2(HDC hdc, POINTS beg, POINTS end) { HPEN hPen, hOldPen; SetROP2(hdc, R2_COPYPEN); //设置前景配色方式为画笔颜色 hPen = CreatePen(PS_SOLID, 5, RGB(0, 100, 255)); //兰色实线画笔 hOldPen = (HPEN)SelectObject(hdc, hPen); Ellipse(hdc, beg.x, beg.y, end.x, end.y); //画圆 SelectObject(hdc, hOldPen); DeleteObject(hPen);return
; }
上面的例子导热一个问题,就是在拖动鼠标画圆时,圆圈里的颜色也被反转了。这是SetROP2(hdc, R2_NOT)函数造成的,也是画封闭图形必然遇到的问题。解决办法很简单,画图前将画刷设置为“空画刷”,画完后恢复为原来的画刷。下例中的HOLLOW_BRUSH与NULL_BRUSH相同。
void Draw(HDC hdc, POINTS beg, POINTS end) { HBRUSH hOldBrush; hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH)); //注意:选用空画刷 SetROP2(hdc, R2_NOT); //设置前景配色方式为象素反转 Ellipse(hdc, beg.x, beg.y, end.x, end.y); //画圆 SelectObject(hdc, hOldBrush); //恢复旧刷return
; } void Draw2(HDC hdc, POINTS beg, POINTS end) { HPEN hPen, hOldPen; HBRUSH hOldBrush; SetROP2(hdc, R2_COPYPEN); //设置前景配色方式为画笔颜色 hPen = CreatePen(PS_SOLID, 5, RGB(0, 100, 255)); //兰色实线画笔 hOldPen = (HPEN)SelectObject(hdc, hPen); hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH)); //注意:选用空画刷 Ellipse(hdc, beg.x, beg.y, end.x, end.y); //画圆 SelectObject(hdc, hOldPen); DeleteObject(hPen); SelectObject(hdc, hOldBrush); //恢复旧刷return
; }
上面画的其实是椭圆,如果要画正圆,只要比较外切矩形的长和宽,一般以短边为正方形边长。
void Draw(HDC hdc, POINTS beg, POINTS end) {int
x, y, z; HBRUSH hOldBrush; hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH)); //注意:选用空画刷 //计算外切正方形 x = abs(beg.x - end.x), y = abs(beg.y - end.y); z = min(x, y); //正方形的边长 if (end.x > beg.x) { x = beg.x + z; } else { x = beg.x - z; } if (end.y > beg.y) { y = beg.y + z; } else { y = beg.y - z; } SetROP2(hdc, R2_NOT); //设置前景配色方式为象素反转 Ellipse(hdc, beg.x, beg.y, x, y); //画圆 SelectObject(hdc, hOldBrush); //恢复旧刷return
; } void Draw2(HDC hdc, POINTS beg, POINTS end) {int
x, y, z; HPEN hPen, hOldPen; HBRUSH hOldBrush; //计算外切正方形 x = abs(beg.x - end.x), y = abs(beg.y - end.y); z = min(x, y); //正方形的边长 if (end.x > beg.x) { x = beg.x + z; } else { x = beg.x - z; } if (end.y > beg.y) { y = beg.y + z; } else { y = beg.y - z; } SetROP2(hdc, R2_COPYPEN); //设置前景配色方式为画笔颜色 hPen = CreatePen(PS_SOLID, 5, RGB(0, 100, 255)); //兰色实线画笔 hOldPen = (HPEN)SelectObject(hdc, hPen); hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH)); //注意:选用空画刷 Ellipse(hdc, beg.x, beg.y, x, y); //画圆 SelectObject(hdc, hOldPen); DeleteObject(hPen); SelectObject(hdc, hOldBrush); //恢复旧刷return
; }
上面的例子中,拖动鼠标画圆时,鼠标点为外切矩形的右下角(也可能是左上角)。如果要画一条经过当前点的圆,则首先要计算出开始点到当前点的距离,并作为半径,从而计算出外切正方形的位置。
void Draw(HDC hdc, POINTS beg, POINTS end) {double
x, y;int
r; HBRUSH hOldBrush; hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH)); //注意:选用空画刷 //计算半径 x = beg.x - end.x, y = beg.y - end.y; r = (int
)sqrt(x * x + y * y); SetROP2(hdc, R2_NOT); //设置前景配色方式为象素反转 Ellipse(hdc, beg.x - r, beg.y-r, beg.x + r, beg.y + r); //画圆 SelectObject(hdc, hOldBrush); //恢复旧刷return
; } void Draw2(HDC hdc, POINTS beg, POINTS end) {double
x, y;int
r; HPEN hPen, hOldPen; HBRUSH hOldBrush; //计算半径 x = beg.x - end.x, y = beg.y - end.y; r = (int
)sqrt(x * x + y * y); SetROP2(hdc, R2_COPYPEN); //设置前景配色方式为画笔颜色 hPen = CreatePen(PS_SOLID, 5, RGB(0, 100, 255)); //兰色实线画笔 hOldPen = (HPEN)SelectObject(hdc, hPen); hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH)); //注意:选用空画刷 Ellipse(hdc, beg.x - r, beg.y-r, beg.x + r, beg.y + r); //画圆 SelectObject(hdc, hOldPen); DeleteObject(hPen); SelectObject(hdc, hOldBrush); //恢复旧刷return
; }
上面的例子是一步一步演化而来,将画图部分提取出来,
void doDraw(HDC hdc, POINTS beg, POINTS end) {double
x, y;int
r; //计算半径 x = beg.x - end.x, y = beg.y - end.y; r = (int
)sqrt(x * x + y * y); Ellipse(hdc, beg.x - r, beg.y-r, beg.x + r, beg.y + r); //画圆 } void Draw(HDC hdc, POINTS beg, POINTS end) { HBRUSH hOldBrush; hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH)); //注意:选用空画刷 SetROP2(hdc, R2_NOT); //设置前景配色方式为象素反转 doDraw(hdc, beg, end); SelectObject(hdc, hOldBrush); //恢复旧刷return
; } void Draw2(HDC hdc, POINTS beg, POINTS end) { HPEN hPen, hOldPen; HBRUSH hOldBrush; SetROP2(hdc, R2_COPYPEN); //设置前景配色方式为画笔颜色 hPen = CreatePen(PS_SOLID, 5, RGB(0, 100, 255)); //兰色实线画笔 hOldPen = (HPEN)SelectObject(hdc, hPen); hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH)); //注意:选用空画刷 doDraw(hdc, beg, end); SelectObject(hdc, hOldPen); DeleteObject(hPen); SelectObject(hdc, hOldBrush); //恢复旧刷return
; }