除了映射模式外,还有许多绘图属性可以设置,如背景、绘图方式、多边形填充方式、画弧方向、刷原点等。
1.背景
1)背景色
当背景模式为不透明时,背景色决定线状图的空隙颜色(如虚线中的空隙、条纹刷的空隙和文字的空隙),可以使用CDC类的成员函数GetBkColor和SetBkColor来获得和设置当前的背景颜色:
COLORREF GetBkColor( ) const; // 返回当前的背景色
virtual COLORREF SetBkColor( COLORREF crColor ); // 返回先前的背景色
// 若出错返回0x80000000
2)背景模式
背景模式影响有空隙的线状图的空隙(如虚线中的空隙、条纹刷的空隙和文字的空隙)用什么办法填充。可以使用CDC类的成员函数GetBkMode和SetBkMode来获得和设置当前的背景模式:
int GetBkMode( ) const; // 返回当前背景模式
int SetBkMode( int nBkMode ); // 返回先前背景模式
背景模式的取值
2. 绘图模式
绘图模式(drawing mode)指前景色的混合方式,它决定新画图的笔和刷的颜色(pbCol)如何与原有图的颜色(scCol)相结合而得到结果像素色(pixel)。
1)设置绘图模式
可使用CDC类的成员函数SetROP2 (ROP = Raster OPeration光栅操作)来设置绘图模式:
int SetROP2( int nDrawMode ); 其中,nDrawMode可取值:
绘图模式nDrawMode的取值
其中,R2_COPYPEN(覆盖)为缺省绘图模式,R2_XORPEN(异或)较常用。
2)画移动图形
为了能画移动的位置标识(如十字、一字)和随鼠标移动画动态图形(如直线、矩形、椭圆),必须在不破坏原有背景图形的基础上移动这些图形。
移动图形采用的是异或画图方法,移动图形的过程为:异或画图、在原位置再异或化图(擦除)、在新位置异或画图、……。
如
pGrayPen = new CPen(PS_DOT, 0, RGB(128, 128, 128)); pDC->SetBkMode(TRANSPARENT);
pOldPen = pDC->SelectObject(pGrayPen);
pDC->SelectStockObject(NULL_BRUSH);
pDC->SetROP2(R2_XORPEN);
if (m_bErase) pDC->Ellipse(rect0);
pDC->Ellipse(rect);
pDC->SetROP2(R2_COPYPEN);
pDC->SelectObject(pOldPen);
rect0 = rect;
较完整的拖放动态画图的例子,可参照下面的“3. 拖放画动态直线”部分。
3)其他属性
多边形填充方式:可使用CDC类的成员函数GetPolyFillMode和SetPolyFillMode来确定多边形的填充方式: int GetPolyFillMode( ) const;
int SetPolyFillMode( int nPolyFillMode );
其中nPolyFillMode 可取值ALTERNATE(交替——填充奇数边和偶数边之间的区域,缺省值)或WINDING(缠绕——根据多边形边的走向来确定是否填充一区域)
画弧方向:可使用CDC类的成员函数GetArcDirection和SetArcDirection来确定Arc、Chord、Pie等函数的画弧方向: int GetArcDirection( ) const;
int SetArcDirection( int nArcDirection );
其中,nArcDirection可取值AD_COUNTERCLOCKWISE(逆时针方向,缺省值)和AD_CLOCKWISE(顺时针方向)
刷原点:可使用CDC类的成员函数GetBrushOrg和SetBrushOrg来确定可填充绘图函数的条纹或图案刷的起点:(缺省值为客户区左上角的坐标原点(0, 0)) CPoint GetBrushOrg( ) const;
CPoint SetBrushOrg( int x, int y );
CPoint SetBrushOrg( POINT point );
3.拖放画动态直线
下面是一个较完整的拖放动态画直线的例子:
// 类变量
class CDrawView : public CView {
//……
protected:
BOOL m_bLButtonDown, m_bErase; // 判断是否按下左鼠标键 //和是否需要擦除图形的类变量
CPoint p0, pm; // 记录直线起点和动态终点的类变量 CPen * pGrayPen, * pLinePen; // 定义灰色和直线笔 //……
}
// 构造函数
CDrawView::CDrawView() {
m_bLButtonDown = FALSE; // 设左鼠标键按下为假 m_bErase = FALSE; // 设需要擦除为假 pGrayPen = new CPen(PS_SOLID, 0, RGB(128, 128, 128));// 创建灰色笔 pLinePen = new CPen(PS_SOLID, 0, RGB(255, 0, 0));// 创建红色的直线笔 }
// 鼠标消息响应函数
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) { m_bLButtonDown = TRUE; // 设左鼠标键按下为真 SetCapture(); // 设置鼠标捕获 // SetCursor(LoadCursor(NULL, IDC_CROSS)); // 设置鼠标为十字 p0 = point; // 保存矩形左上角 pm = p0; // 让矩形右下角等于左上角
CView::OnLButtonDown(nFlags, point); }
void CDrawView::OnMouseMove(UINT nFlags, CPoint point) { SetCursor(LoadCursor(NULL, IDC_CROSS)); // 设置鼠标为十字 if (m_bLButtonDown) { // 左鼠标键按下为真 CDC* pDC = GetDC(); // 获取设备上下文 pDC->SelectObject(pGrayPen);// 选取灰色笔
pDC->SetROP2(R2_XORPEN);// 设置为异或绘图方式
if (m_bErase) { // 需要擦除为真 pDC->MoveTo(p0); pDC->LineTo(pm); // 擦除原直线 }
else // 需要擦除为假 m_bErase = TRUE; // 设需要擦除为真
pDC->MoveTo(p0); pDC->LineTo(point); // 绘制新直线 pm = point; // 记录老终点 ReleaseDC(pDC); // 释放设备上下文 }
CView::OnMouseMove(nFlags, point); }
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point) { ReleaseCapture(); // 释放鼠标捕获 if (m_bLButtonDown) { // 左鼠标键按下为真 CDC* pDC = GetDC(); // 获取设备上下文 pDC->SelectObject(pGrayPen);// 选取灰色笔
pDC->SetROP2(R2_XORPEN); // 设置为异或绘图方式
pDC->MoveTo(p0); pDC->LineTo(pm); // 擦除原直线 pDC->SelectObject(pLinePen); // 选择直线笔
pDC->SetROP2(R2_COPYPEN);// 设置为覆盖绘图方式
pDC->MoveTo(p0); pDC->LineTo(point); // 绘制最终的直线 m_bLButtonDown = FALSE; // 重设左鼠标键按下为假 m_bErase = FALSE; // 重需要擦除为假 ReleaseDC(pDC); // 释放设备上下文 }
CView::OnLButtonUp(nFlags, point); }
|
|