精华内容
下载资源
问答
  • MFC绘图

    2016-08-24 15:24:22
    MFC绘图
    class CMyDrawView : public CView
    {
        DECLARE_DYNCREATE(CMyDrawView)
    
    protected:
        CMyDrawView();           // 动态创建所使用的受保护的构造函数
        virtual ~CMyDrawView();
    
    public:
        void drawCarSpace(CDC* pDC,int x,int y,int width,int height);//绘制车位
        void drawBody(CDC* pDC,int x,int y,int width,int height);//绘制整体框图
        void drawText(CDC* pDC,int x,int y,CString text);//绘制文字
        void drawCar(CDC* pDC);//绘制车辆
    
    public:
        virtual void OnDraw(CDC* pDC);      // 重写以绘制该视图
    #ifdef _DEBUG
        virtual void AssertValid() const;
    #ifndef _WIN32_WCE
        virtual void Dump(CDumpContext& dc) const;
    #endif
    #endif
    
    protected:
        DECLARE_MESSAGE_MAP()
    public:
        afx_msg void OnMouseMove(UINT nFlags, CPoint point);
        afx_msg void OnAddcar();
    };
    
    void CMyDrawView::OnDraw(CDC* pDC)
    {
        int space_width=50;
        int space_height=50;
        CDocument* pDoc = GetDocument();
        // TODO: 在此添加绘制代码
        drawBody(pDC,20,20,1030,615);
        drawCarSpace(pDC,40,40,50,100);
        drawText(pDC,62,87,_T("1"));
        drawCarSpace(pDC,150,40,50,100);
        drawText(pDC,172,87,_T("2"));
    }
    
    void CMyDrawView::drawCar(CDC* pDC)
    {
    
        CBitmap bitmap;
        bitmap.LoadBitmapW(IDB_Car1);
    
        BITMAP bm;
        bitmap.GetBitmap(&bm);
    
        CDC memDC;
        memDC.CreateCompatibleDC(pDC);
        CBitmap *oldBitmap=(CBitmap *)memDC.SelectObject(&bitmap);
    
        CRect rect(40,40,bm.bmWidth+40,bm.bmHeight+40);
        TransparentBlt(pDC->GetSafeHdc(),rect.left,rect.top,rect.Width(),
            rect.Height(),memDC.GetSafeHdc(),0,0,bm.bmWidth,bm.bmHeight,
            RGB(0,0,0));
    
    }
    
    void CMyDrawView::drawText(CDC* pDC,int x,int y,CString text)
    {
        pDC->TextOutW(x,y,text);
    }
    
    void CMyDrawView::drawBody(CDC* pDC,int x,int y,int width,int height)
    {
        CPen pen;
        pen.CreatePen(PS_SOLID,2,RGB(0,255,0));
        CPen *oldPen=(CPen *)pDC->SelectObject(&pen);
        pDC->SelectObject(oldPen);
        pDC->Rectangle(x,y,width+x,height+y);
    
        pen.DeleteObject();
    }
    
    void CMyDrawView::drawCarSpace(CDC* pDC,int x,int y,int width,int height)
    {
        CBrush brush(HS_HORIZONTAL,RGB(0,255,0));
        CBrush *oldBrush=pDC->SelectObject(&brush);
        pDC->Rectangle(CRect(x,y,width+x,height+y));
        brush.DeleteObject();
    }
    
    // CMyDrawView 消息处理程序
    
    void CMyDrawView::OnMouseMove(UINT nFlags, CPoint point)
    {
        CMainFrame *pFrmWnd = (CMainFrame *)GetTopLevelFrame();
        CString str;
        str.Format(_T("横坐标:%d"),point.x);
        pFrmWnd->m_wndStatusBar.SetPaneText(2,str);
        str.Format(_T("纵坐标:%d"),point.y);
        pFrmWnd->m_wndStatusBar.SetPaneText(3,str);
        CView::OnMouseMove(nFlags, point);
    }
    
    void CMyDrawView::OnAddcar()
    {
        CDC* pdc=GetDC();
        drawCar(pdc);
    }
    
    展开全文
  • MFC 绘图

    千次阅读 2012-03-29 16:42:20
    mfc绘图(转载) 4 画图 在Windows中,绘图一般在视图窗口的客户区进行,使用的是设备上下文类CDC中各种绘图函数。 1. 映射模式与坐标系 1)默认映射模式 映射模式(map mode)影响所有的图形和文本绘制函数...

    mfc绘图(转载)

    4 画图
    在Windows中,绘图一般在视图窗口的客户区进行,使用的是设备上下文类CDC中各种绘图函数。
    1. 映射模式与坐标系
    1)默认映射模式
    映射模式(map mode)影响所有的图形和文本绘制函数,它定义(将逻辑单位转换为设备单位所使用的)度量单位和坐标方向,Windows总是用逻辑单位来绘图。
    缺省情况下,绘图的默认映射模式为MM_TEXT,其绘图单位为像素(只要不打印输出,屏幕绘图使用该模式就够了)。若窗口客户区的宽和高分别为w和h像素,则其x坐标是从左到右,范围为0 ~ w-1;y坐标是从上到下,范围为0 ~ h-1。

    2)设置映射模式
    可以使用CDC类的成员函数GetMapMode和SetMapMode来获得和设置当前的映射模式:
    int GetMapMode( ) const; // 返回当前的映射模式
    virtual int SetMapMode( int nMapMode ); // 返回先前的映射模式


    映射模式的nMapMode取值与含义
    符号常量 数字常量 x方向 y方向 逻辑单位的大小 
    MM_TEXT 1 向右 向下 像素 
    MM_LOMETRIC 2 向右 向上 0.1 mm 
    MM_HIMETRIC 3 向右 向上 0.01 mm 
    MM_LOENGLISH 4 向右 向上 0.01 in 
    MM_HIENGLISH 5 向右 向上 0.001 in 
    MM_TWIPS 6 向右 向上 1/1440 in 
    MM_ISOTROPIC 7 自定义 自定义 自定义 
    MM_ANISOTROPIC 8 自定义 自定义 自定义


    可见,除了两种自定义映射模式外,x方向都是向右,y方向也只有MM_TEXT的向下,其余的都是向上,与数学上一致。除了MM_ANISOTROPIC外,其他所有映射模式的x与y方向的单位都是相同的。所有映射模式的逻辑坐标的原点(0, 0)最初都是在窗口的左上角,但在CScrollView的派生类中,MFC会随用户滚动文档而自动调整逻辑原点的相对位置(改变视点的原点属性)。
    3)自定义映射模式
    自定义映射模式MM_ISOTROPIC(各向同性,x与y方向的单位必须相同)和MM_ANISOTROPIC(各向异性,x与y方向的单位可以不同)的单位和方向,可以通过用CDC类的成员函数G/SetWindowExt和G/SetViewportExt来获取/设置窗口和视口的大小来确定:
    CSize GetWindowExt( ) const;
    virtual CSize SetWindowExt( int cx, int cy );

    virtual CSize SetWindowExt( SIZE size );
    CSize GetViewportExt( ) const;
    virtual CSize SetViewportExt( int cx, int cy );

    virtual CSize SetViewportExt( SIZE size );
    其中,cx或size.cx和cy或size.cy分别为窗口/视口的宽度与高度(逻辑单位)。
    还可以用CDC类的成员函数SetViewportOrg来设置坐标原点的位置:
    virtual CPoint SetViewportOrg( int x, int y );
    CPoint SetViewportOrg( POINT point );
    例如
    void CDrawView::OnDraw(CDC* pDC) {
           CRect rect;
           GetClientRect(rect);
           pDC->SetMapMode(MM_ANISOTROPIC);
           pDC->SetWindowExt(1000,1000);
           pDC->SetViewportExt(rect.right, -rect.bottom);

           pDC->SetViewportOrg(rect.right / 2, rect.bottom /2);

           pDC->Ellipse(CRect(-500, -500, 500, 500));

    }
    将当前的映射模式设置为各向异性自定义映射模式,窗口大小为1000个逻辑单位宽和1000个逻辑单位高,视口大小同当前客户区,视口的坐标原点设置在当前客户区的中央。由于使用了负数作为SetViewportExt函数的第2个参数,所以y轴方向是向上的。

    可见,圆被画成了椭圆,x与y方向上的逻辑单位不相同。
    4)单位转换
    对所有非MM_TEXT映射模式,有如下重要规则:
    <!--[if !supportLists]-->l         <!--[endif]-->CDC的成员函数(如各种绘图函数)具有逻辑坐标参数

    <!--[if !supportLists]-->l         <!--[endif]-->CWnd的成员函数(如各种响应函数)具有设备坐标参数(如鼠标位置point)

    <!--[if !supportLists]-->l         <!--[endif]-->位置的测试操作(如CRect的PtInRect函数)只有使用设备坐标时才有效

    <!--[if !supportLists]-->l         <!--[endif]-->长期使用的值应该用逻辑坐标保存(如窗口滚动后保存的设备坐标就无效了)


    因此,为了使应用程序能够正确工作,除MM_TEXT映射模式外,其他映射模式都需要进行单位转换。下面是逻辑单位到设备单位(如像素)的转换公式:
    x比例因子 = 视口宽度 / 窗口宽度
    y比例因子 = 视口高度 / 窗口高度
    设备x = 逻辑x * x比例因子 + x原点偏移量
    设备y = 逻辑y * y比例因子 + y原点偏移量
    Windows的GDI负责逻辑坐标和设备坐标之间的转换,这可以调用CDC类的成员函数LPtoDP和DPtoLP来进行:
    void LPtoDP( LPPOINT lpPoints, int nCount = 1 ) const;

    void LPtoDP( LPRECT lpRect ) const;
    void LPtoDP( LPSIZE lpSize ) const;
    void DPtoLP( LPPOINT lpPoints, int nCount = 1 ) const;

    void DPtoLP( LPRECT lpRect ) const;
    void DPtoLP( LPSIZE lpSize ) const;
    例如:
    void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) {

                  CRect rect = m_rect; // 逻辑坐标

                  CClientDC dc(this);
                  dc.SetMapMode(MM_LOENGLISH);
                  dc.LPtoDP(rect); // 转化成设备坐标
           if (rect.PtInRect(point)) // 位置的测试操作只有使用设备坐标时才有效

           ......
    }
    void CDrawView:: OnMouseMove (UINT nFlags, CPoint point) {

           float t,y;

                  char buf[40];
           CDC* pDC = GetDC();

    pDC->SetMapMode(MM_HIMETRIC);
                  pDC->DPtoLP(&point); // 转化成逻辑坐标
    t = t1 + (point.x * dt) / w; sprintf(buf, "%.4fs", t); pSB->SetPaneText(xV, buf);

    y = (y0 - point.y) / dy; sprintf(buf, "%.4f", y); pSB->SetPaneText(yV, buf);
           ......
    }
    2. 画像素点
    画像素点就是设置像素点的颜色,从前面3)(2)已知道这可由CDC的成员函数SetPixel来做,该函数的原型为:
    COLORREF SetPixel( int x, int y, COLORREF crColor ); 或

    COLORREF SetPixel( POINT point, COLORREF crColor );

    其中,x与y分别为像素点的横坐标与纵坐标,crColor为像素的颜色值。例如
    pDC->SetPixel(i, j, RGB(r, g, b));

    3.画线状图
    在Windows中,线状图必须用笔来画(笔的创建与使用见前面的3)(3)),下面是CDC类中可以绘制线状图的常用成员函数:
    <!--[if !supportLists]-->l         <!--[endif]-->当前位置:设置当前位置为(x, y)或point:(返回值为原当前位置的坐标)

    CPoint MoveTo( int x, int y ); 或 CPoint MoveTo( POINT point );

    <!--[if !supportLists]-->l         <!--[endif]-->画线:使用DC中的笔从当前位置画线到点(x, y)或point:(若成功返回非0值):

    BOOL LineTo( int x, int y ); 或BOOL LineTo( POINT point );
    <!--[if !supportLists]-->l         <!--[endif]-->画折线:使用DC中的笔,依次将点数组lpPoints中的nCount(≥2)个点连接起来,形成一条折线:

    BOOL Polyline( LPPOINT lpPoints, int nCount );
    <!--[if !supportLists]-->l         <!--[endif]-->画多边形:似画折线,但还会将最后的点与第一个点相连形成多边形,并用DC中的刷填充其内部区域:

    BOOL Polygon( LPPOINT lpPoints, int nCount );
    <!--[if !supportLists]-->l         <!--[endif]-->画矩形:使用DC中的笔画左上角为(x1, y1)、右下角为(x2, y2)或范围为*lpRect的矩形的边线,并用DC中的刷填充其内部区域:

    BOOL Rectangle( int x1, int y1, int x2, int y2 ); 或
    BOOL Rectangle( LPCRECT lpRect );
                  有时需要根据用户给定的两个任意点来重新构造左上角和右下角的点,例如:
                  rect = CRect(min(p0.x, point.x), min(p0.y, point.y), max(p0.x, point.x), max(p0.y, point.y));

    <!--[if !supportLists]-->l         <!--[endif]-->画圆角矩形:使用DC中的笔画左上角为(x1, y1)、右下角为(x2, y2)或范围为*lpRect的矩形的边线,并用宽x3或point.x高y3或point.y矩形的内接椭圆倒角,再用DC中的刷填充其内部区域:

    BOOL RoundRect( int x1, int y1, int x2, int y2, int x3, int y3 );
    BOOL RoundRect( LPCRECT lpRect, POINT point );
    例如:
    int d = min(rect.Width(), rect.Height()) / 4;

    pDC-> RoundRect(rect, CPoint(d, d));
    <!--[if !supportLists]-->l         <!--[endif]-->画(椭)圆:使用DC中的笔在左上角为(x1, y1)、右下角为(x2, y2)或范围为*lpRect的矩形中画内接(椭)圆的边线,并用DC中的刷填充其内部区域:

    BOOL Ellipse( int x1, int y1, int x2, int y2 );
    BOOL Ellipse( LPCRECT lpRect );
    注意,CDC中没有画圆的专用函数。在这里,圆是作为椭圆的(宽高相等)特例来画的。
    <!--[if !supportLists]-->l         <!--[endif]-->画弧:(x1, y1)与(x2, y2)或lpRect的含义同画(椭)圆,(x3, y3)或ptStart为弧的起点,(x4, y4)或ptEnd为弧的终点:(逆时针方向旋转)

    BOOL Arc( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );

    BOOL Arc( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
    BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);

    BOOL ArcTo(LPCRECT lpRect, POINT ptStart, POINT ptEnd);
    画圆弧:(其中(x, y)为圆心、nRadius为半径、fStartAngle为起始角、fSweepAngle为弧段跨角)
    BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle);

    <!--[if !supportLists]-->l         <!--[endif]-->画弓弦:参数的含义同上,只是用一根弦连接弧的起点和终点,形成一个弓形,并用DC中的刷填充其内部区域:

    BOOL Chord( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );

    BOOL Chord( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
    4.画填充图
    在Windows中,面状图必须用刷来填充(刷的创建与使用见前面的3)(4))。上面(2)中的Polygon、Rectangle、Ellipse和Chord等画闭合线状图的函数,只要DC中的刷不是空刷,都可以用来画对应的面状图(边线用当前笔画,内部用当前刷填充)。下面介绍的是CDC类中只能绘制面状图的其他常用成员函数:
    <!--[if !supportLists]-->l         <!--[endif]-->画填充矩形:用指定的刷pBrush画一个以lpRect为区域的填充矩形,无边线,填充区域包括矩形的左边界和上边界,但不包括矩形的右边界和下边界:

    void FillRect( LPCRECT lpRect, CBrush* pBrush );
    <!--[if !supportLists]-->l         <!--[endif]-->画单色填充矩形:似FillRect,但只能填充单色,不能填充条纹和图案:

    void FillSolidRect( LPCRECT lpRect, COLORREF clr );
    void FillSolidRect( int x, int y, int cx, int cy, COLORREF clr );
    <!--[if !supportLists]-->l         <!--[endif]-->画饼图(扇形):参数含义同Arc,但将起点和终点都与外接矩形的中心相连接,形成一个扇形区域,用DC中的刷填充整个扇形区域,无另外的边线:

    BOOL Pie( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );

    BOOL Pie( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
    <!--[if !supportLists]-->l         <!--[endif]-->画拖动的矩形:先擦除线宽为sizeLast、填充刷为pBrushLast的原矩形lpRectLast,然后再以线宽为size、填充刷为pBrush画新矩形lpRectLast。矩形的边框用灰色的点虚线画,缺省的填充刷为空刷:

    void DrawDragRect( LPCRECT lpRect, SIZE size, LPCRECT lpRectLast,

    SIZE sizeLast, CBrush* pBrush = NULL, CBrush* pBrushLast = NULL );

    如:pDC->DrawDragRect(rect, size, rect0, size);

    <!--[if !supportLists]-->l         <!--[endif]-->填充区域:

    <!--[if !supportLists]-->n     <!--[endif]-->用当前刷从点(x, y)开始向四周填充到颜色为crColor的边界:

    BOOL FloodFill(int x, int y, COLORREF crColor); // 成功返回非0

    <!--[if !supportLists]-->n     <!--[endif]-->用当前刷从点(x, y)开始向四周填充:

    BOOL ExtFloodFill(int x, int y, COLORREF crColor,

    UINT nFillType); // 成功返回非0

    <!--[if !supportLists]-->u <!--[endif]-->nFillType = FLOODFILLBORDER:填充到颜色为crColor的边界(同FloodFill);(用于填充内部颜色不同但边界颜色相同的区域)
    <!--[if !supportLists]-->u <!--[endif]-->nFillType = FLOODFILLSURFACE:填充所有颜色为crColor的点,直到碰到非crColor颜色的点为止。(点(x, y)的颜色也必须为crColor),(用于填充内部颜色相同但边界颜色可以不同的区域)。例如:
    pDC->ExtFloodFill(point.x, point.y, pDC->GetPixel(point), FLOODFILLSURFACE);

    5.清屏
    Windows没有提供专门的清屏函数,可以调用CWnd的下面两个函数调用来完成该功能:
    void Invalidate(BOOL bErase = TRUE);
    void UpdateWindow( );
    或调用CWnd的函数
    BOOL RedrawWindow(
       LPCRECT lpRectUpdate = NULL,

       CRgn* prgnUpdate = NULL,
       UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE

    );
    来完成。
    例如(菜单项ID_CLEAR的事件处理函数):
    CDrawView::OnClear() { // 调用OnDraw来清屏
           //Invalidate();
           //UpdateWindow( );
           RedrawWindow( );
    }
    也可以用画填充背景色矩形的方法来清屏,如:
           RECT rect;
           GetClientRect(&rect);
           pDC->FillSolidRect(&rect, RGB(255, 255, 255));

    6.在控件上绘图
    可以在对话框资源中放置图片控件,并对其类型属性选Frame。可在对话框的绘图消息响应函数OnPaint或其他函数中,用CWnd类的函数GetDlgItem:
    CWnd* GetDlgItem( int nID ) const;
    来获得图片控件的窗口对象,再用函数GetDC:
    CDC* GetDC( );

    由窗口对象得到DC,然后就可以用该DC在控件中画图。如(在ID为IDC_HUESAT的图片控件上画调色板)
    void CColorDlg::OnPaint() 
    {
           if (IsIconic()) {
                  ... ...
           }
           else {
                  CDialog::OnPaint();
                  int i, j;
                  BYTE r, g, b;
                  // get control window and DC of Hue&Saturation

                  CWnd *pWin = GetDlgItem(IDC_HUESAT);

                  CDC *pDC = pWin->GetDC();

                  // draw hue-saturation palette

                  for (i = 0; i < 360; i++)

                         for (j = 0; j <= 255; j++) {

                                HSLtoRGB(i, 255 - j, 128, r, g, b); // 自定义函数,见网络硬盘的

    // res目录中的ColTrans.cpp文件
                                pDC->SetPixel(i, j, RGB(r, g, b));

                         }
                  ... ...
           }
    }
    在非Frame类静态控件上绘图,必须先按顺序依次调用CWnd类的Invalidate和UpdateWindow函数后,再开始用DC画图。如在一个ID为IDC_COLOR的按钮上绘图:
    void CComDlgDlg::DrawColor()
    {
           CWnd* pWnd = GetDlgItem(IDC_COLOR);

           CDC* pDC = pWnd->GetDC();

           CRect rect;

           pWnd->GetClientRect(&rect);
           pWnd->Invalidate();
           pWnd->UpdateWindow();
           pDC->FillRect(&rect, new CBrush(m_crCol));
    }

    若干说明:
    <!--[if !supportLists]-->l     <!--[endif]-->除了基于对话框的程序外,其他对话框类都需要自己添加(重写型)消息响应函数OnInitDialog,来做一些必要的初始化对话框的工作。添加方法是:先在项目区选中“类视图”页,再选中对应的对话框类,然后在属性窗口的“重写”页中添加该函数;

    <!--[if !supportLists]-->l     <!--[endif]-->为了使在运行时能够不断及时更新控件的显示(主要是自己加的显式代码),可以将自己绘制控件的所有代码都全部加入对话框类的消息响应函数OnPaint中。在需要时(例如在绘图参数修改后),自己调用CWnd的Invalidate和UpdateWindow函数,请求系统刷新对话框和控件的显示。因为控件也是窗口,控件类都是CWnd的派生类。所以在对话框和控件中,可以像在视图类中一样,调用各种CWnd的成员函数。

    <!--[if !supportLists]-->l     <!--[endif]-->一般的对话框类,缺省时都没有明写出OnPaint函数。可以自己在对话框类中添加WM_PAINT消息的响应函数OnPaint来进行一些绘图工作。

    <!--[if !supportLists]-->l     <!--[endif]-->为了在鼠标指向按钮时,让按钮上自己绘制的图形不被消去,可以设置按钮控件的“Owner Draw”属性为“True”。

    <!--[if !supportLists]-->l     <!--[endif]-->如果希望非按钮控件(如图片控件和静态文本等),也可以响应鼠标消息(如单击、双击等),需要设置控件的“Notify”属性为“True”。

    <!--[if !supportLists]-->l     <!--[endif]-->使用OnPaint函数在对话框客户区的空白处(无控件的地方)绘制自己的图形,必须屏蔽掉其中缺省的对对话框基类的OnPaint函数的调用:

    //CDialog::OnPaint();
    <!--[if !supportLists]-->l     <!--[endif]-->对话框的背景色,可以用CWnd类的成员函数:

    DWORD GetSysColor( int nIndex);
    得到,其中的nIndex取为COLOR_BTNFACE。例如:
    dc.SetBkColor(GetSysColor(COLOR_BTNFACE));

    下面是部分例子代码:(其中FillColor和ShowImg为自定义的成员函数)
    void CSetDlg::OnBnClickedPenColor()
    {
           // TODO: 在此添加控件通知处理程序代码
           CColorDialog colDlg(m_crLineColor);

           if (colDlg.DoModal() == IDOK) {

                  m_crLineColor = colDlg.GetColor();

                  Invalidate();
                  UpdateWindow();
           }
    }
    // ……
    void CSetDlg::OnPaint()
    {
           CPaintDC dc(this); // device context for painting

           // TODO: 在此处添加消息处理程序代码
           // 不为绘图消息调用 CDialog::OnPaint()
           FillColor(IDC_PEN_COLOR, m_crLineColor);

           FillColor(IDC_BRUSH_COLOR, m_crBrushColor);

           if(m_pBitmap0 != NULL) ShowImg(IDC_BRUSH_IMG, m_hBmp0);

           else if(m_pBitmap != NULL) ShowImg(IDC_BRUSH_IMG, m_hBmp);

    }
    void CSetDlg::FillColor(UINT id, COLORREF col)

    {
           CWnd* pWnd = GetDlgItem(id);

           CDC* pDC = pWnd->GetDC();

           pDC->SelectObject(new CPen(PS_SOLID, 1, RGB(0, 0, 0)));

           pDC->SelectObject(new CBrush(col));

           CRect rect; 
           pWnd->GetClientRect(&rect);
           pWnd->Invalidate();
           pWnd->UpdateWindow();
           pDC->RoundRect(&rect, CPoint(8, 8));

    }
    void CSetDlg::ShowImg(UINT ID, HBITMAP hBmp)

    {
           CWnd* pWnd = GetDlgItem(ID);

           CDC* pDC = pWnd->GetDC();

           CRect rect; 
           pWnd->GetClientRect(&rect);
           pWnd->Invalidate();
           pWnd->UpdateWindow();
           BITMAP bs;
           GetObject(hBmp, sizeof(bs), &bs);

           CDC dc;
           if(dc.CreateCompatibleDC(pDC)) {

                  int x0, y0, w, h;
                  float rx = (float)bs.bmWidth / rect.right,

                         ry = (float)bs.bmHeight / rect.bottom;

                  if (rx >= ry) {

                         x0 = 0; w = rect.right;

                         h = (int)(bs.bmHeight / rx + 0.5);

                         y0 = (rect.bottom - h) / 2;

                  }
                  else {
                         y0 = 0; h = rect.bottom;

                         w = (int)(bs.bmWidth / ry + 0.5);

                         x0 = (rect.right - w) / 2;

                  }
                  ::SelectObject(dc.GetSafeHdc(), hBmp);

                  pDC->SetStretchBltMode(HALFTONE);
                  pDC->StretchBlt(x0, y0, w, h, &dc, 0, 0, bs.bmWidth, bs.bmHeight, SRCCOPY);

                  SetDlgItemInt(IDC_W, bs.bmWidth);

                  SetDlgItemInt(IDC_H, bs.bmHeight);

           }
    }
    //……
    5 设置绘图属性
    除了映射模式外,还有许多绘图属性可以设置,如背景、绘图方式、多边形填充方式、画弧方向、刷原点等。
    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)其他属性
    <!--[if !supportLists]-->l         <!--[endif]-->多边形填充方式:可使用CDC类的成员函数GetPolyFillMode和SetPolyFillMode来确定多边形的填充方式:

    int GetPolyFillMode( ) const;
    int SetPolyFillMode( int nPolyFillMode );
    其中nPolyFillMode 可取值ALTERNATE(交替——填充奇数边和偶数边之间的区域,缺省值)或WINDING(缠绕——根据多边形边的走向来确定是否填充一区域)
    <!--[if !supportLists]-->l         <!--[endif]-->画弧方向:可使用CDC类的成员函数GetArcDirection和SetArcDirection来确定Arc、Chord、Pie等函数的画弧方向:

    int GetArcDirection( ) const;
    int SetArcDirection( int nArcDirection );
    其中,nArcDirection可取值AD_COUNTERCLOCKWISE(逆时针方向,缺省值)和AD_CLOCKWISE(顺时针方向)
    <!--[if !supportLists]-->l         <!--[endif]-->刷原点:可使用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);

    }

    展开全文
  • mfc 绘图

    千次阅读 2011-08-22 16:11:13
    MFC如何高效地绘图 显示图形如何避免闪烁,如何提高显示效率是问得比较多的问题。  而且多数人认为MFC绘图函数效率很低,总是想寻求其它的解决方案。  MFC绘图效率的确不高但也不差,而且它的绘图函数...

    MFC如何高效地绘图


    显示图形如何避免闪烁,如何提高显示效率是问得比较多的问题。 
    而且多数人认为MFC的绘图函数效率很低,总是想寻求其它的解决方案。 
    MFC
    的绘图效率的确不高但也不差,而且它的绘图函数使用非常简单, 
    只要使用方法得当,再加上一些技巧,用MFC可以得到效率很高的绘图程序。 
    我想就我长期(呵呵当然也只有2年多)使用MFC绘图的经验谈谈 
    我的一些观点。


    1
    、显示的图形为什么会闪烁? 
    我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容 反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了。 当然,这样做会使得窗口的显示乱成一团,因为重绘时没有背景色对原来 绘制的图形进行清除,而又叠加上了新的图形。 有的人会说,闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的, 其实这样说并不对,绘图的显示速度对闪烁的影响不是根本性的。 
    例如在OnDraw(CDC *pDC)中这样写: 
    pDC->MoveTo(0,0); 
    pDC->LineTo(100,100); 
    这个绘图过程应该是非常简单、非常快了吧,但是拉动窗口变化时还是会看见闪烁。其实从道理上讲,画图的过程越复杂越慢闪烁应该越少,因为绘图用的时间与用背景清除屏幕所花的时间的比例越大人对闪烁的感觉会越不明显。 比如:清楚屏幕时间为1s绘图时间也是为1s,这样在10s内的连续重画中就要闪 5次;如果清楚屏幕时间为1s不变,而绘图时间为9s,这样10s内的连续重画 只会闪烁一次。这个也可以试验,在OnDraw(CDC *pDC)中这样写: 
    for(int i=0;i<100000;i++) 

    pDC->MoveTo(0,i); 
    pDC->LineTo(1000,i); 

    呵呵,程序有点变态,但是能说明问题。 
    说到这里可能又有人要说了,为什么一个简单图形看起来没有复杂图形那么 闪呢?这是因为复杂图形占的面积大,重画时造成的反差比较大,所以感觉上要 闪得厉害一些,但是闪烁频率要低。 那为什么动画的重画频率高,而看起来却不闪?这里,我就要再次强调了, 闪烁是什么?闪烁就是反差,反差越大,闪烁越厉害。因为动画的连续两个帧之间 的差异很小所以看起来不闪。如果不信,可以在动画的每一帧中间加一张纯白的帧,不闪才怪呢。 

    2
    、如何避免闪烁 
    在知道图形显示闪烁的原因之后,对症下药就好办了。首先当然是去掉MFC 提供的背景绘制过程了。实现的方法很多:
    可以在窗口形成时给窗口的注册类的背景刷置为NULL 
    也可以在形成以后修改背景 
    static CBrush brush(RGB(255,0,0)); 
    SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush); 
    要简单也可以重载OnEraseBkgnd(CDC* pDC)直接返回TRUE 
    这样背景没有了,结果图形显示的确不闪了,但是显示也象前面所说的一样,变得一团乱。怎么办?这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有 图形进行显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存中绘制好,然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去(这个过程非常快,因为是非常规整的内存拷贝)。这样在内存中绘图时,随便用什么反差大的背景色进行清除都不会闪,因为看不见。当贴到屏幕上时,因为内存中最终的图形与屏幕显示图形差别很小(如果没有运动,当然就没有差别),这样看起来就不会闪。 

    3
    、如何实现双缓冲 
    首先给出实现的程序,然后再解释,同样是在OnDraw(CDC *pDC)中: 
    CDC MemDC; //
    首先定义一个显示设备对象 
    CBitmap MemBitmap;//
    定义一个位图对象 
    //
    随后建立与屏幕显示兼容的内存显示设备 
    MemDC.CreateCompatibleDC(NULL); 
    //
    这时还不能绘图,因为没有地方画 ^_^ 
    //
    下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小 
    MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight); 

    //
    将位图选入到内存显示设备中 
    //
    只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上 
    CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap); 
    //
    先用背景色将位图清除干净,这里我用的是白色作为背景 
    //
    你也可以用自己应该用的颜色 
    MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255)); 
    //
    绘图 
    MemDC.MoveTo(……); 
    MemDC.LineTo(……); 

    //
    将内存中的图拷贝到屏幕上进行显示 
    pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY); 
    //
    绘图完成后的清理 
    MemBitmap.DeleteObject(); 
    MemDC.DeleteDC(); 
    上面的注释应该很详尽了,废话就不多说了。 

    4
    、如何提高绘图的效率 
         我主要做的是电力系统的网络图形的CAD软件,在一个窗口中往往要显示成千上万个电力元件,而每个元件又是由点、线、圆等基本图形构成。如果真要在一次重绘过程重画这么多元件,可想而知这个过程是非常漫长的。如果加上了图形的浏览功能,鼠标拖动图形滚动时需要进行大量的重绘,速度会慢得让用户将无法忍受。怎么办?只有再研究研究MFC的绘图过程了。 
        实际上,在OnDraw(CDC *pDC)中绘制的图并不是所有都显示了的,例如:你在OnDraw中画了两个矩形,在一次重绘中虽然两个矩形的绘制函数都有执行,但是很有可能只有一个显示了,这是因为MFC本身为了提高重绘的效率设置了裁剪区。裁剪区的作用就是:只有在这个区内的绘图过程才会真正有效,在区外的是无效的,即使在区外执行了绘图函数也是不会显示的。因为多数情况下窗口重绘的产生大多是因为窗口部分被遮挡或者窗口有滚动发生,改变的区域并不是整个图形而只有一小部分,这一部分需要改变的就是pDC中的裁剪区了。因为显示(往内存或者显存都叫显示)比绘图过程的计算要费时得多,有了裁剪区后显示的就只是应该显示的部分,大大提高了显示效率。但是这个裁剪区是MFC设置的,它已经为我们提高了显示效率,在进行复杂图形的绘制时如何进一步提高效率呢?那就只有去掉在裁剪区外的绘图过程了。可以先用pDC->GetClipBox()得到裁剪区,然后在绘图时判断你的图形是否在这个区内,如果在就画,不在就不画。如果你的绘图过程不复杂,这样做可能对你的绘图效率不会有提高。

    展开全文
  • MFC绘图 简单绘图

    2011-05-04 09:29:52
    MFC 绘图 简单的MFC绘图程序 划线 画矩形但是 还不能保存
  • MFC绘图软件

    2017-11-16 19:28:35
    MFC绘图软件,可以绘制基本图元,例如矩形圆形三角形箭头等,可以移动更改颜色,更改样式。可以在图形中编辑字体。可以保存和读取。
  • 经典MFC绘图

    2012-04-27 17:06:18
    经典MFC绘图,各种绘图详解,清华大学经典教程,轻松入门MFC绘图
  • MFC绘图基础

    2013-07-10 10:21:28
    MFC绘图详解,双缓存去闪机制,MFC绘图必备知识,绘制直线,圆形,矩形等
  • MFC绘图示例

    2015-12-21 15:14:18
    应用程序向导已为您创建了此 MFC绘图示例 应用程序。此应用程序 不仅介绍了使用 Microsoft 基础类的基本知识, 而且是编写应用程序的起点。
  • 简单的MFC绘图软件

    2018-01-29 18:11:20
    简单的MFC绘图软件 ...
  • 实现mfc绘图,通过代码实现绘制简单几何图形的旋转,填充裁剪,平移
  • mfc 绘图

    2013-08-31 08:24:56
    mfc 绘图板,采用mfc框架和sdk api
  • MFC绘图程序

    2014-07-31 19:43:38
    MFC 绘图程序 很多小功能, 还有背景音乐哦,能改变颜色,线宽,输入文字,移动图,删除图等等
  • 首先我们先上效果图,如果你需要这样的Demo请点击此处下载:High-speed Charting Control--MFC绘图Demo 在开始之前,我们首先推荐一篇博客,该博客主要对该控件的英文开发文档进行了翻译,如果各位需要进一步...

    首先我们先上效果图,如果你需要这样的Demo请点击此处下载:High-speed Charting Control--MFC绘图Demo

    在开始之前,我们首先推荐一篇博客,该博客主要对该控件的英文开发文档进行了翻译,如果各位需要进一步开发该控件的其他功能可以详细阅读该博客或官方文档:High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件

    接下来是该控件的下载地址:

    免费官方下载地址(需要注册下载,页面有时会打不开):https://www.codeproject.com/Articles/14075/High-speed-Charting-Control

    CSDN下载地址(需要积分):https://download.csdn.net/download/qq_15029743/10956256

    好了,接下来正式介绍我们是如何画图的:

    Step1:建立一个新的MFC工程文件,并将下载的控件的源文件(CSDN下载中的ChartCtrl_source.zip文件)解压放到MFC工程目录下:

    Step2:导入控件类:

     

     Step3:程序界面拖入控件:

     

     选中拖入的自定义控件并更改属性,这里要改的属性有Style,就在5右边的0改为2,0x52010000,Class命名为ChartCtrl,ID我们可以自定义(这里就使用默认的IDC_CUSTOM1):

    Step4: 添加头文件,在对话框类的头文件中把控件包含进来,具体代码及实现效果如下如下:

    #include "ChartCtrl/ChartCtrl.h"

    Step5: 创建控件的成员变量:

    CChartCtrl m_ChartCtrl1;  //这里的成员变量名称根据实际需要命名即可

    关联控件的成员变量和ID:

    DDX_Control(pDX, IDC_CUSTOM1, m_ChartCtrl1);

    此时,我们编译运行,控件就显示出来了:

     Step6: 为控件添加坐标轴:

    CChartAxis *pAxis = NULL;
    pAxis = m_ChartCtrl1.CreateStandardAxis(CChartCtrl::BottomAxis);
    pAxis->SetAutomatic(true);
    pAxis = m_ChartCtrl1.CreateStandardAxis(CChartCtrl::LeftAxis);
    pAxis->SetAutomatic(true);

     Step7:创建标题

    首先导入标题类的头文件:

    #include "ChartCtrl\ChartTitle.h"  //标题头文件

     代码实现:

    TChartString str1;
    str1 = _T("High-speed Charting画图Demo");
    m_ChartCtrl1.GetTitle()->AddString(str1);

     

     

     Step8:一些外观上的设计(通常白底绘图看久了比较累,我们这里进行一些颜色的改变)

    
    	m_ChartCtrl.GetTitle()->SetColor(RGB(255, 255, 255));   //标题字体白色
    	m_ChartCtrl.GetLeftAxis()->SetTextColor(RGB(255, 255, 255));  //左坐标轴白色
    	m_ChartCtrl.GetBottomAxis()->SetTextColor(RGB(255, 255, 255));  //底部坐标轴白色
    	m_ChartCtrl.SetBorderColor(RGB(255, 255, 255));  //边框颜色白色
    	m_ChartCtrl.SetBackColor(RGB(85, 85, 85));  //背景颜色深灰色

    修改之后看起来舒服多了,不扎眼了:

    Step9:画线

    先导入画线的头文件:

    #include "ChartCtrl\ChartLineSerie.h"  //画线头文件

    代码实现:这里我们把代码添加到一个按钮响应里(按钮画图):

     

    这里我们画一条过原点的直线,代码如下:

     

    
    	double X1Values[10], Y1Values[10];
    	for (int i = 0; i<10; i++)
    	{
    		X1Values[i] = i;
    		Y1Values[i] = i;
    	}
    
    	CChartLineSerie *pLineSerie2;
    
    	m_ChartCtrl1.SetZoomEnabled(true);
    	m_ChartCtrl1.RemoveAllSeries();//先清空
    	pLineSerie2 = m_ChartCtrl1.CreateLineSerie();
    	pLineSerie2->SetSeriesOrdering(poNoOrdering);//设置为无序
    	pLineSerie2->SetPoints(X1Values, Y1Values, 10);

     这样,我们点击之后就可以画出一条直线了:

    Step10:添加鼠标响应,很多时候我们需要知道绘图控件中的某个点的具体坐标,这时候我们可以通过添加十字光标来实现

     添加鼠标响应头文件:

    #include "ChartCtrl\ChartMouseListener.h"  //鼠标响应头文件

    定义两个全局变量来存储坐标:

    double x, y;

    添加一个自定义消息来传递坐标:

     

     点击编辑代码,然后我们来写处理代码:

    
    	CString s;
    	s.Format(_T("x = %.2f,y = %.2f"), x, y);
    	CStatic* pStatic;
    	pStatic = (CStatic*)GetDlgItem(IDC_STATIC);
    	pStatic->SetWindowText(s);
    	return 1;

     这里的IDC_STATIC是我们提前准备的一个静态文本框,用于显示坐标信息

     这里我们还需要定义一下消息:

    #define MESSAGE_UPDATEPOS WM_USER+1001

     加下来我们用代码实现派生类:

    class CCustomCursorListener : public CChartCursorListener
    {
    public:
    	void OnCursorMoved(CChartCursor *pCursor, double xValue, double yValue)
    	{
    		x = xValue;
    		y = yValue;
    		SendMessage(m_hwnd, MESSAGE_UPDATEPOS, 0, 0);
    		// Do something with the string...
    	}
    
    	void GetHwnd(HWND hwnd)
    	{
    		m_hwnd = hwnd;
    	}
    	HWND m_hwnd;
    };

     

     最后,我们在按钮下添加实现代码:

        CCustomCursorListener* m_pCursorListener;
    	CChartCrossHairCursor* pCrossHair =
    		m_ChartCtrl1.CreateCrossHairCursor();
    
    	HWND hWnd = this->GetSafeHwnd();
    	m_pCursorListener = new CCustomCursorListener;
    	m_pCursorListener->GetHwnd(hWnd);
    	pCrossHair->RegisterListener(m_pCursorListener);

     

    至此,我们完成了整个Demo,点击画图即可获得博客开头的效果:

    展开全文
  • MFC绘图操作

    2020-12-28 10:30:21
    有些事说出来显得我不大度,但我确实不开心,如果你不懂我,那错的都是我。...void CMFC绘图View::OnHuahua(){ //创建对象,在视图对象里画 CClientDC dc(this); dc.TextOutA(100, 100, "aiyou");//::Te...
  • mfc绘图教程

    2012-04-14 12:19:54
    mfc绘图板程序教程总集,这是我们老师写的!望大家多多指教……
  • High-speed Charting Control(MFC绘图控件),主要用于MFC绘图,具体参考博主博客
  • mfc绘图的文档

    2012-07-28 18:53:06
    介绍mfc绘图ppt
  • MFC绘图与数据库

    2012-06-21 10:33:29
    通过串口传输数据,通过mfc绘图并存入数据库中
  • 简单mfc绘图

    2017-10-08 16:28:48
    使用vc++6.0进行mfc绘图,包括直线,矩形,椭圆的绘图
  • MFC绘图波形图演示程序 MFC 定时器实现 GDI
  • 试验报告 试验报告对你没看错就是实验...结合我刚传上去的“MFC绘图小软件源代码”10分绝对超值,帮你剩下很多很多的时间,你还在犹豫什么呢? 由于没分了。将我1年前的,写的报告也贡献出来了。本文仅供学习参考用!
  • 经典MFC绘图.rar

    2012-06-05 22:30:36
    经典MFC绘图.rar 初学者看看吧。
  • 关于MFC绘图板的参考报告
  • MFC绘图 简单操作

    2010-07-10 09:06:55
    MFC绘图的简单操作分部介绍, 适合初学者。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,199
精华内容 6,079
关键字:

mfc绘图