本帖最后由 hill_qd 于 2010-01-09 06:14:12 编辑

解决方案 »

  1.   

    用SetROP2是出现这种情况建议用双缓冲绘制, 不会闪烁, 而且绝对不会出现你这种情况
      

  2.   

    楼上两个人仔细看看代码,帮我解决实际问题,sandyandy说的跟我的问题不一样
      

  3.   

    afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
    ON_WM_GETMINMAXINFO()void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 
    {
    // TODO: Add your message handler code here and/or call default
        lpMMI->ptMinTrackSize.x   = 640 ;   
        lpMMI->ptMinTrackSize.y   = 456 ;
    CFrameWnd::OnGetMinMaxInfo(lpMMI);
    }
      

  4.   

    我运行了一下你的程序,那个Cross(十字线怎么是跟着鼠标变化的,不是固定大小的?)
      

  5.   


    OnLButtonDblClk(UINT nFlags, CPoint point) 
    {
      // TODO: Add your message handler code here and/or call default
      CDC* pDC = GetDC();   if(m_rectCross.PtInRect(point)) 
      { 
        if(m_bDispCross) 
        { 
          if(m_rectCross.PtInRect(m_ptCrossLast) && m_bNeedEraseCross) 
            DrawSelectCross(pDC, m_ptCrossLast); 
          m_bNeedEraseCross = FALSE; 
          m_bDispCross = FALSE;       ReleaseCapture();
        } 
        else 
        { 
          //DrawSelectCross(pDC, m_ptCrossLast); 
          DrawSelectCross(pDC, point); 
          m_bDispCross = TRUE; 
          m_bNeedEraseCross = TRUE; 
          m_ptCrossLast = point;       SetCapture( );
        } 
      } 
      ReleaseDC(pDC); 

      CView::OnLButtonDblClk(nFlags, point);
    }
      

  6.   

    schlafenhamster:m_rectCross是随窗口大小而变化的,他是窗口的一部分,可以说是小于最小窗口的尺寸的
      

  7.   

    zgl7903:按照你的方法,当进入画十字状态后,不能点别的地方了,我本来的意思是,鼠标离开绘图区域后,还可以干别的,回来后继续画十字,除非在绘图区双击鼠标后才能退出这种状态。
    schlafenhamster:那个画十字就是跟随鼠标的
      

  8.   

    “m_rectCross是随窗口大小而变化的,他是窗口的一部分,可以说是小于最小窗口的尺寸的“,保证他随窗口改变而改变,并小于窗口一些,你的程序就没问题,
      

  9.   

    你可以定义一个m_rectCross试试
      

  10.   

    CXxxxView::CXxxxView()
    {
    // TODO: add construction code here
    m_rectCross.left=60;
    m_rectCross.right=360;// 当窗口right小于时,cross就不擦除了!
    m_rectCross.top=60;
    m_rectCross.bottom=160;
    m_bDispCross=TRUE;
    }
      

  11.   

    绘图区的大小是变化的,但一定要小于几个点,看看WM_SIZE用户改变窗口大小时,检查绘图区的大小。
      

  12.   

    void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 
    {
    // TODO: Add your message handler code here and/or call default
        lpMMI->ptMinTrackSize.x  = 220 ;  
        lpMMI->ptMinTrackSize.y  = 320 ; 

    CFrameWnd::OnGetMinMaxInfo(lpMMI);
    }
    //是这个吗?
    关键是鼠标不能落在绘图区域内!
      

  13.   

    CXxxxView::CXxxxView()
    {
    // TODO: add construction code here
    m_rectCross.left=20;
        m_rectCross.right=60;
        m_rectCross.top=60;
        m_rectCross.bottom=160;
    m_bDispCross=TRUE;
    }
    //试试再也不会留cross了!
    void CXxxxView::OnSize(UINT nType, int cx, int cy) 
    {
    CView::OnSize(nType, cx, cy);
    if(cx==0) return;
    m_rectCross.right=cx-20;//Only horizondle processed
    //  afxDump << cx << "," << cy <<"\n";
    // TODO: Add your message handler code here

    }
      

  14.   

    不太理解楼主的做法,我简单用CWnd实现了一下,不知道是否是楼主的意思,如果不是也可以做一下参考class CXXWnd : public CWnd
    {
    DECLARE_DYNAMIC(CXXWnd)public:
    CXXWnd();
    virtual ~CXXWnd();public:
    BOOL m_bMouseIn;
    BOOL m_bOpenDrawCross;protected:
    void DrawCross(CDC* pDC);protected:
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
    public:
    DECLARE_MESSAGE_MAP()
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnPaint();
    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
    };// TransparentWnd.cpp : implementation file
    //#include "stdafx.h"
    #include "XXWnd.h"
    // CXXWndIMPLEMENT_DYNAMIC(CXXWnd, CWnd)CXXWnd::CXXWnd()
    {
        m_bMouseIn = FALSE;
        m_bOpenDrawCross = FALSE;
    }CXXWnd::~CXXWnd()
    {
    }
    BEGIN_MESSAGE_MAP(CTransparentWnd, CWnd)
    ON_WM_CREATE()
    ON_WM_PAINT()
    ON_WM_LBUTTONDBLCLK()
    ON_WM_MOUSEMOVE()
    ON_MESSAGE(WM_MOUSELEAVE, &CXXWnd::OnMouseLeave)
    END_MESSAGE_MAP()// CXXWndmessage handlersBOOL CXXWnd::PreCreateWindow(CREATESTRUCT& cs)
    {
        return CWnd::PreCreateWindow(cs);
    }int CXXWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CWnd::OnCreate(lpCreateStruct) == -1)
    return -1;
        return 0;
    }void CXXWnd::OnPaint() // 视图在OnDraw中处理
    {
        CPaintDC dc(this); // device context for painting
        DrawCross(&dc);
    }void CXXWnd::OnLButtonDblClk(UINT nFlags, CPoint point)
    {
        CWnd::OnLButtonDblClk(nFlags, point);
        m_bOpenDrawCross = !m_bOpenDrawCross;
        Invalidate();
    }void CXXWnd::OnMouseMove(UINT nFlags, CPoint point)
    {
        CWnd::OnMouseMove(nFlags, point);
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.hwndTrack = m_hWnd;
        tme.dwFlags = TME_LEAVE;
        ::TrackMouseEvent(&tme);
        m_bMouseIn = TRUE;
        Invalidate();
    }LRESULT CXXWnd::OnMouseLeave(WPARAM wParam, LPARAM lParam)
    {
        m_bMouseIn = FALSE;
        Invalidate();
        return TRUE;
    }void CXXWnd::DrawCross(CDC* pDC)
    {
        ASSERT(pDC);
        CDC memDC;
        CBitmap bitmap, *pOldBitmap = NULL;
        CRect rcClient;
        GetClientRect(rcClient);
        if ( memDC.CreateCompatibleDC(pDC) && bitmap.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()) )
        {
    pOldBitmap = memDC.SelectObject(&bitmap);
    COLORREF clrBk = pDC->GetBkColor();
    memDC.FillRect(rcClient, &CBrush(clrBk));
    if ( m_bOpenDrawCross && m_bMouseIn )
    {
        CPoint ptMouse;
        GetCursorPos(&ptMouse);
        ScreenToClient(&ptMouse);
                memDC.MoveTo(rcClient.left, ptMouse.y);
        memDC.LineTo(rcClient.right, ptMouse.y);
        memDC.MoveTo(ptMouse.x, rcClient.top);
        memDC.LineTo(ptMouse.x, rcClient.bottom);
    }
    pDC->BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY);
    memDC.SelectObject(pOldBitmap);
        }
    }
      

  15.   

    memDC.FillRect(rcClient, &CBrush(clrBk));
    不能重画背景
      

  16.   

    用CBitmap类是你在画的时候要在dc上画一幅图片也可以理解直接在dc画位图,CBitmap类实际就是HBITMAP,mfc将这个HBITMAP句柄抽象成一个类的形式。不能重绘,是不是你看到的是白色的内容啊,如果是白色的内容,可能是我的背景画刷设置的是白色,你那m_clrBk的颜色改一下看看,可能是因为这个原因吧。
      

  17.   

    写错了COLORREF clrBk = pDC->GetBkColor();
    memDC.FillRect(rcClient, &CBrush(clrBk));这句话是获取默认的背景颜色,你用clrBk = RGB(255, 0, 0)看看是否重绘背景了。
      

  18.   

       pDC->BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY);
    绘图完毕后,这个应该是吧绘制的图拷贝到屏幕上吧?
    我感觉我主要是因为没处理好WM_SIZE事件,其实我根本就没处理
      

  19.   


    int CXXWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
        BITMAP bitinfo;
        m_bitmap.LoadBitmap(IDB_XXX); // 加载图片资源
        m_bitmap.GetBitmap(&bitinfo);
        m_szImage = CSize(bitinfo.bmWidth, bitinfo.bmHeight);
        return 0;
    }void CXXWnd::DrawCross(CDC* pDC)
    {
        ASSERT(pDC);
        // 这里用双缓冲
        CDC memDC1, memDC2;
        CBitmap bitmap, *pOldBitmap1 = NULL, *pOldBitmap2 = NULL;
        CPen pen(PS_SOLID, 2, RGB(255, 0, 0)), *pOldPen = NULL;
        CRect rcClient;
        GetClientRect(rcClient);
        if ( memDC1.CreateCompatibleDC(pDC)
          && memDC2.CreateCompatibleDC(pDC)
          && bitmap.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()) )
        {
            // 选入背景资源的内存DC
            pOldBitmap1 = memDC1.SelectObject(&m_bitmap);
            // 完整内容的内存DC
            pOldBitmap2 = memDC2.SelectObject(&bitmap);
            pOldPen = memDC2.SelectObject(&pen);
            memDC2.StretchBlt(0, 0, rcClient.Width(), rcClient.Height(), &memDC1, 0, 0, m_szImage.cx, m_szImage.cy, SRCCOPY);
            if ( m_bOpenDrawCross && m_bMouseIn )
            {
                CPoint ptMouse;
                GetCursorPos(&ptMouse);
                ScreenToClient(&ptMouse);
                memDC2.MoveTo(rcClient.left, ptMouse.y);
                memDC2.LineTo(rcClient.right, ptMouse.y);
                memDC2.MoveTo(ptMouse.x, rcClient.top);
                memDC2.LineTo(ptMouse.x, rcClient.bottom);
            }
            pDC->BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &memDC2, 0, 0, SRCCOPY);
            memDC2.SelectObject(pOldPen);
            memDC2.SelectObject(pOldBitmap2);
            memDC1.SelectObject(pOldBitmap1);
        }
    }
      

  20.   

    学到了很多东西,hahaking119,你把下面的代码复制到你的程序中试试
    afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); 
    ON_WM_GETMINMAXINFO() void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 

    // TODO: Add your message handler code here and/or call default 
        lpMMI->ptMinTrackSize.x  = 640 ;  
        lpMMI->ptMinTrackSize.y  = 456 ; 
    CFrameWnd::OnGetMinMaxInfo(lpMMI); 
    }
      

  21.   


    如果不处理背景图重绘,那么你画是十字线就无法用在背景图上实现,因为你十字线在你鼠标移动的时候是会发生变化的,这样毕竟在背景中的位置会发生改变,还有如果你鼠标位置不发生改变,那么就不会产生ON_MOUSEMOVE消息,也就不会重绘。个人觉得重绘不会太影响效率。你减少重绘量好像不容易实现,你可以试试。