这一章比较简单,是画封闭图形的例子,画圆、画方框等都是同样原理,要注意的是背景的设置。
上一章的程序的基础上,将画线语句换成画圆的语句就可以了。画圆是用Ellipse()函数。
BOOL Ellipse( HDC hdc, //HDCintnLeftRect, //外切矩形的“左上”x座标intnTopRect, //外切矩形的“左上”y座标intnRightRect, //外切矩形的“右下”x座标intnBottomRect //外切矩形的“右下”y座标 );
LONG clsCur;boolbDrawing =false; //画图状态为true POINTS start, end, prev; //开始点、结束点、前一个移动点 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
switch(message) { //与上例相同,省略 }return0; } //作图 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) {
doublex, y;intr; //计算半径 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; }