现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

MFC绘图总结(5):设置绘图属性

2012-12-24 23:22 工业·编程 ⁄ 共 4354字 ⁄ 字号 暂无评论
除了映射模式外,还有许多绘图属性可以设置,如背景、绘图方式、多边形填充方式、画弧方向、刷原点等。
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 ); // 返回先前背景模式
背景模式的取值
nBkMode值
名称
作用
OPAQUE
不透明的(缺省值)
空隙用背景色填充
TRANSPARENT
透明的
空隙处保持原背景图不变
2. 绘图模式
绘图模式(drawing mode)指前景色的混合方式,它决定新画图的笔和刷的颜色(pbCol)如何与原有图的颜色(scCol)相结合而得到结果像素色(pixel)。
1)设置绘图模式
可使用CDC类的成员函数SetROP2 (ROP = Raster OPeration光栅操作)来设置绘图模式:

int SetROP2( int nDrawMode );

其中,nDrawMode可取值:
绘图模式nDrawMode的取值
符号常量
作用
运算结果
R2_BLACK
黑色
pixel = black
R2_WHITE
白色
pixel = white
R2_NOP
不变
pixel = scCol
R2_NOT
反色
pixel = ~scCol
R2_COPYPEN
覆盖
pixel = pbCol
R2_NOTCOPYPEN
反色覆盖
pixel = ~pbCol
R2_MERGEPENNOT
反色或
pixel = ~scCol | pbCol
R2_MERGENOTPEN
或反色
pixel = scCol | ~pbCol
R2_MASKNOTPEN
与反色
pixel = scCol & ~pbCol
R2_MERGEPEN
pixel = scCol | pbCol
R2_NOTMERGEPEN
或非
pixel = ~(scCol | pbCol)
R2_MASKPEN
pixel = scCol & pbCol
R2_NOTMASKPEN
与非
pixel = ~(scCol & pbCol)
R2_XORPEN
异或
pixel = scCol ^ pbCol
R2_NOTXORPEN
异或非
pixel = ~(scCol ^ pbCol)
其中,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);

}

给我留言

留言无头像?