小弟最近在做毕设时需要打开一副BMP图片,然后拖动鼠标在图片上画出一个矩形。但因为图片很大,发现拖动矩形的时候,画矩形的速度跟不上鼠标的移动速度。后来改了一下,把图片的句柄改为全局变量,但又出现拖动鼠标,绘出的矩形是一抹黑。我表达的很不清楚,贴出主要代码来,我初来咋到,希望gg jj们帮帮忙,不胜感激!
BOOL CMyDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;

// TODO: Add your specialized creation code here
HBITMAP hBmp=(HBITMAP)::LoadImage(NULL,lpszPathName, 
      IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if(hBmp==NULL)
return FALSE;
if(m_bmp.m_hObject!=NULL)
m_bmp.DeleteObject();
m_bmp.Attach(hBmp);
BITMAP bmpInfo;
m_bmp.GetBitmap(&bmpInfo);
m_nWidth=bmpInfo.bmWidth;
m_nHeight=bmpInfo.bmHeight;
m_bFlag=TRUE;
return TRUE;
}void CMyView::OnLButtonDown(UINT nFlags, CPoint point) 
{
// TODO: Add your message handler code here and/or call default
CMyDoc* pDoc =GetDocument();
int nHitTest;
nHitTest=pDoc->m_rectTracker.HitTest(point); CPoint scrollPos=GetScrollPosition();
CPoint offset;
offset.x=point.x+scrollPos.x;
offset.y=point.y+scrollPos.y;
if(pDoc->m_bFlag){               //是否打开了一副图片
if(nHitTest<0){
pDoc->m_rectTracker.m_rect.SetRect(-1,-1,-1,-1);
pDoc->m_startPt=offset;
m_bDrag=TRUE;
}
else{
pDoc->m_rectTracker.Track(this,offset,TRUE);
pDoc->m_rectTracker.m_rect.NormalizeRect();
OnDraw(this->GetDC());
}
} CScrollView::OnLButtonDown(nFlags, point);
}void CMyView::OnMouseMove(UINT nFlags, CPoint point) 
{
// TODO: Add your message handler code here and/or call default
CMyDoc* pDoc =GetDocument();
CPoint scrollPos=GetScrollPosition();
CPoint offset;
offset.x=point.x+scrollPos.x;
offset.y=point.y+scrollPos.y;
if(m_bDrag){
pDoc->m_rectTracker.m_rect.SetRect(pDoc->m_startPt,offset);
pDoc->m_rectTracker.m_rect.NormalizeRect();
OnDraw(this->GetDC());
}
CScrollView::OnMouseMove(nFlags, point);
}void CMyView::OnDraw(CDC* pDC)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
if(pDoc->m_bFlag==FALSE)
return;
//HBITMAP hBmp=(HBITMAP)::LoadImage(NULL,"D:\\afx\\example01.bmp", 
//       IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
//CBitmap bmp;
//bmp.Attach(hBmp);
CDC dcMem;
dcMem.CreateCompatibleDC(pDC);
dcMem.SelectObject(&pDoc->m_bmp);    //dcMem.SelectObject(&bmp);
pDoc->m_rectTracker.Draw(&dcMem);
pDC->BitBlt(0,0,pDoc->m_nWidth,pDoc->m_nHeight,&dcMem,0,0,SRCCOPY);
dcMem.DeleteDC();
}画出的橡皮筋一抹黑。在OnDraw里换成注释的代码又出现橡皮筋跟不上鼠标的问题,主要是装载图片太慢了。
另外当移动滚动条后,再拖动鼠标画橡皮筋,画出的矩形位置不对,我实在太菜了,实在不知道该怎么处理了,还请大大们帮帮忙,再次感谢!!

解决方案 »

  1.   

    pDoc->m_rectTracker.Draw(&dcMem);
    pDC->BitBlt(0,0,pDoc->m_nWidth,pDoc->m_nHeight,&dcMem,0,0,SRCCOPY);这句话改一下:
     
    CRect rectClient;
    GetClientRect(&rectClient);
    pDoc->m_rectTracker.Draw(&dcMem);
    pDC->BitBlt(0,0,min(rectClient.Width()+1,pDoc->m_nWidth),min(rectClient.Height()+1,pDoc->m_nHeight),&dcMem,0,0,SRCCOPY);
      

  2.   

    感谢楼上帮忙,但是您那样只能把rectClient大小的位图显示出来,拖动滚动条后就有问题了。
      

  3.   

    画橡皮筋的代码就一行,在OnMouseMove里面:
    pDoc->m_rectTracker.m_rect.SetRect(pDoc->m_startPt,offset);
    m_startPt是记录鼠标按下的点,offset是算上了拖动滚动条后的点
      

  4.   

    还是不理解你真正要做什么,如果你的目的是不改变位图,只是在位图上画一个拖动的矩形,就不要在鼠标事件里调用OnDraw()来画,你可以在鼠标事件里创建一个客户区DC设备,用异或方式来画出拖动框,在OnDraw里画位图,这样就可以实现在位图上拖动矩形框也不会产生闪烁,而且你也没必要用内存DC.
      

  5.   

    to chen_wenyue:
    对,你猜的真是我想做的。我是不用改变位图的,只要画出个矩形就行。异或画图我还是第一次听说,方便的话能给一个例子吗?3q
      

  6.   

    void CXKDrawUnitFrame::DoDrawDragFocus( Tint x, Tint y, Tbool bDrawOld, Tbool bDrawNew )
    {
        CClientDC dc(m_pWnd);
        int iOld = dc.SetROP2(R2_NOTXORPEN);
        
        CPoint pt(x,y);
        CRect rcFocuse;
        
        if( bDrawOld )
        {
    rcFocuse = CRect(m_ptStart, m_ptOld);
    rcFocuse.NormalizeRect();
    if( !rcFocuse.IsRectEmpty() )
        DrawRect(dc, rcFocuse);
        }
        if( bDrawNew )
        {
    rcFocuse = CRect(m_ptStart, pt);
    rcFocuse.NormalizeRect();
    if( !rcFocuse.IsRectEmpty() )
        DrawRect(dc, rcFocuse);
        }
        
        dc.SetROP2(iOld);
    }
    给你个函数,实现你说的功能.这个函数在OnMouseMove里调用,传入OnMouseMove函数的x,y坐标值(要调整一下,避免移动到窗口外面),另外在OnLButtonDown里记录下起点坐标m_ptStart,在OnMouseMove里将m_ptStart符值给m_ptOld,用来进行擦除操作
      

  7.   

    哦,说错了,不是m_ptStart赋给m_ptOld,是将鼠标位置直接赋给m_ptOld,记录当前画线的位置.
      

  8.   

    在OnMouseMove里面这样调用错在哪里呢?
    if(m_bDrag){
      pDoc->m_ptOld=point;
      DoDrawDragFocus(point.x,point.y,FALSE,TRUE);
    }
    我这样调用画出来的矩形也有很多黑色的竖条纹。
      

  9.   

    另外我把您的DrawRect(dc, rcFocuse);
    改成了
    dc.Rectangle(rcFocuse);
    您那句在我这里没编译过去
      

  10.   

    在OnLBUttonDown要初始化:m_ptStart.x = x;m_ptStart.y = y; m_ptOld = m_ptStart;
    在OnMouseMove里要这样调DoDrawDragFocus(point.x,point.y,TRUE,TRUE);
    意思是擦掉上次旧的,在新位置画出新的.在调用完后,要记得写m_ptOld = CPoint(nX, nY);记录下这次画点位置.
    在OnLButtonUp里要这样调DoDrawDragFocus(nX, nY, XK_TRUE, XK_FALSE);
    意思是擦掉最后一次的框框
    在OnPaint里要这样调DoDrawDragFocus( 0, 0, XK_TRUE, XK_FALSE );
      

  11.   

    void CXKDrawUnit::DrawRect( CDC &hDC, CRect &rc )
    {
        hDC.DrawFocusRect( rc );
    }
    那个是我自己写的接口,主要是为了扩充,可以修改这里面的代码,或者派生类去修改,改变拖动时的效果...
      

  12.   

    问题马上解决了,thank you very much。看来要经常来这里向大家学习了,我为了实现这个小小的功能走了好多弯路。只有20分,聊表谢意!!