我打算在一个视图中粘贴很多个位图,也就是鼠标左键点击一下就粘贴一个位图,现在遇到的问题就是,当我第一次点击的时候能够正确粘贴位图,但是点击第二次的时候,第一次的位图消失了,而第二次的位图能够正确粘贴,请哪位高手能指教一下小弟,万分感谢。能不能给出原代码,谢谢救命之恩了

解决方案 »

  1.   

    必须在OnDraw()中也有实现。不然窗口重画时就没有了。
      

  2.   

    粘贴位图的操作要在View类的OnDraw函数中完成,否则粘贴第二个位图或者窗口刷新的时候位图就会被刷新掉!
      

  3.   

    onDraw了,我粘贴一下我的源代码BOOL CConfigView::Draw (CDC* pDC,CPoint pt,UINT bitmapid)
    {//»­½Úµã

    CConfigureDoc* pDoc=GetDocument();
    CBitmap bitmap;
    bitmap.LoadBitmap (bitmapid);
    BITMAP bmpInfo;
    bitmap.GetBitmap (&bmpInfo);
    CDC dcMemory;
    dcMemory.CreateCompatibleDC (pDC);
    CBitmap* pOldBitmap=dcMemory.SelectObject (&bitmap); CSize size;
    size=bitmap.GetBitmapDimension ();
    m_cNodeSize=size; CPoint bpt;//·ÅÖù¦ÄÜ¿éµÄ×ø±ê
    bpt.x =pt.x -bmpInfo.bmWidth/2;
    bpt.y =pt.y -bmpInfo.bmHeight/2;

    CConfigNode* ds;
    ds=new CConfigNode(pDoc);
    // CMapIntToDataStruct ds=pDoc->m_pMap;
    // int ct;
    // int key;
    // ct=ds.GetCount();
    // if(ct==0)
    // key=1;
    // else
    // key=ct+1;
    // ds.SetAt(key,pNode); ds->LeftLinkPoint =CPoint(pt.x-size.cx/2,pt.y );
    ds->RightLinkPoint =CPoint(pt.x+size.cx /2,pt.y); pDC->BitBlt (bpt.x,bpt.y,bmpInfo.bmWidth ,bmpInfo.bmHeight ,&dcMemory,0,0,SRCCOPY);
    // dcMemory.SelectObject (pOldBitmap);

    //»­½ÚµãÓëÖ±ÏßµÄÁ¬½Ó×ø±êµã
    // pDC->Ellipse (ds->LeftLinkPoint.x-2,ds->LeftLinkPoint.y-2,ds->LeftLinkPoint.x+2,ds->LeftLinkPoint.y+2);
    // pDC->Ellipse (ds->RightLinkPoint.x-2,ds->RightLinkPoint.y-2,ds->RightLinkPoint.x+2,ds->RightLinkPoint.y+2); return TRUE;
    }
    void CConfigView::OnDraw (CDC* pDC)
    {//ÔÚÊÓͼÖл­Í¼
    // if (GetDocument()->DrawTree(pDC, m_ptStart, m_pSelectedNode) == -1)
    // TRACE0("´íÎó: CConfigureDoc::DrawTreeµ÷ÓÃʧ°Ü!!\n");
    CConfigureDoc* pDoc=GetDocument();
    ASSERT_VALID(pDoc);
    BOOL flag;
    flag=GetSelectionState();
    UINT bitmap;

    if(flag && pDoc!=NULL)
    {
    bitmap=GetDrawBitmapId();
    Draw(pDC,m_pMousePt,bitmap);
    pDoc->SetFunctionPoint (m_pMousePt);
    pDoc->IncreaceCounter ();
    pDoc->InsertNode (bitmap);
    }

    }
      

  4.   

    这么多乱七八糟的代码
    我就看了ondraw,没看draw
    我感觉ondraw里面没有循环能实现ondraw吗?
      

  5.   

    请问用循环干什么,我的程序是想,根据鼠标点击来粘贴位图,请afantict教我一下,谢谢了
      

  6.   

    我认为是这样的
    在你每次粘贴一个位图的同时
    把这个位图的信息保存到一个链表/数组里面
    ondraw的时候
    遍粒这个链表/数组,draw
      

  7.   

    思路是这样的
    文档类里面一个Clist,存放位置和位图信息
    视图类里面一个draw函数,根据位置来显示位图
    视图类里面的ondraw函数,遍离clist,调用draw
      

  8.   

    代码很糟糕。我想可以这么做。
    在视图中添加变量:CDC  m_memdc;
    在视图初始化的时候,
    CClientDC dc(this);
    CRect rect;
    GetClientRect(&rect);
    CBitmap bm;
    bm.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());//和视图一样大小的bm
    m_memdc.CreateCompatibleDC(&dc);在mouse_down事件处理中,只用在m_memdc中画图:
    CDC tmpdc;
    //加载位图,把位图选入tmpdc,我就不写了
    m_memdc.Bitblt(x,y,bm.Width(),bm.Height(),&tmpdc,0,0,SRCCOPY);
    //将tmpdc拷贝到m_memdc,位置可以选鼠标单击的位置
    CRect rect;
    GetClientRect(&rect);
    InvalidateRect(rect,false); //强制刷新,系统会调用ondraw在ondraw中:
    CRect rect;
    GetClientRect(&rect);
    pDC->bitblt(0,0,rect.Width(),rect.Height(),&m_memdc,0,0,SRCCOPY);//基本上这就可以实现你要的功能
    要注意的是:要在适当的时候和地方释放资源,比如位图,DC等。
      

  9.   

    afantict,你那种方法不行,你只是解决了doc的问题,不能解决视图显示的问题
      

  10.   

    是吗?
    你的draw函数怎么做的?
    ondraw的函数里面循环clist
    对每个位图都draw
    不可以吗?
      

  11.   

    enoloo老兄,怎么我用了后视图没有反应呢麻烦你再看一下我的源代码,再指导指导,还想问一下,两个CDC怎么互相拷贝呢?麻烦了,希望您能尽快的回答我,谢谢了,万分感谢。
    void CConfigView::OnLButtonDown (UINT nFlags,CPoint point)
    {
    BOOL flag;
    flag=GetSelectionState();
             UINT bitmapid;
    CBitmap bitmap;
    if(m_bSelectFlag&&flag)
    {
    CDC tmpdc;
    tmpdc.CreateCompatibleDC (&m_memDC);
    bitmapid=GetDrawBitmapId();
    bitmap.LoadBitmap (bitmapid);
    BITMAP bmpInfo;
    bitmap.GetBitmap (&bmpInfo);
    CBitmap* pOldBitmap=tmpdc.SelectObject (&bitmap);
    CSize size;
    size=bitmap.GetBitmapDimension ();
    m_cNodeSize=size;
             m_memDC.BitBltpoint.x,point.y,bmpInfo.bmWidth ,
                          bmpInfo.bmHeight ,&tmpdc,0,0,SRCCOPY);
    m_pMousePt=point; CRect rect;
    GetClientRect(&rect);
    InvalidateRect(rect,false); 
    }
    CView::OnLButtonDown (nFlags,point);
    }
    void CConfigView::OnDraw (CDC* pDC)
    {
    CRect rect;
    GetClientRect(&rect);
    pDC->BitBlt(0,0,rect.Width(),rect.Height
                (),&m_memDC,0,0,SRCCOPY);}
    void CConfigView::OnInitialUpdate ()
    {
    m_zoomNum = CSize(100, 100);
    m_zoomDenom = CSize(100, 100); CClientDC dc(this);
    CRect rect;
    GetClientRect(&rect);
    CBitmap bm;
    bm.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());
    m_memDC.CreateCompatibleDC(&dc);
    CScrollView::OnInitialUpdate();
    }
      

  12.   

    afantict,你的意思是我每粘贴一次都要把前面粘贴的图再粘贴一次,是吗?
      

  13.   

    我想你的把你每次单击时的位置及图片都得保存下来,比如说放入一个list里,然后在ondraw时再读出来重新绘制,不然重画时会将你原来的图像都擦除。
      

  14.   

    不是的
    你应该找本书看看
    只需要重绘现在clientrect里面的这几个
      

  15.   

    clist里面需要保存位置和位图信息
    ondraw的时候
    要比较位置和getclipbox这个rect的位置
    如果需要ondraw就draw,否则不draw
      

  16.   

    afantict,你看了我现在粘贴的这个源代码没有,如果用这种方法怎么实现
      

  17.   

    不用这么麻烦吧,
    CDC tmpdc;
    tmpdc.CreateCompatibleDC (&m_memDC);
    可以把这个tmpdc做成全局的,这样每次增加贴图先往这个内存中贴完后再把这个tmpdc贴到窗口中去,ok?
      

  18.   

    sinhighly,我还想问一下两个CDC对象怎样互相拷贝而且我上面的程序并没有实现我要的功能呀
      

  19.   

    你试试看吧:
    CDC* MemDC = new CDC;
    CBitmap *oldBitmap;MemDC->CreateCompatibleDC(pDC);
    oldBitmap = MemDC->SelectObject(&blank);//draw the elements
    MyCollection.Draw(MemDC);pDC->BitBlt(0,0,FrameWidth,FrameHeight,MemDC,0,0,SRCCOPY);
    MemDC->SelectObject(oldBitmap);delete MemDC;
      

  20.   

    拷贝实现在下面,你的代码我没看,偶懒:)
    CDC memdc;
    memdc.CreateCompatibleDC(&dc);
    memdc.SelectObject( &bitmap ); CDC pDC;
    // create a compatible memory dc 
    pDC.CreateCompatibleDC(&dc);
    // associate the back bitmap object to the compatible memory dc object
    pDC.SelectObject(&m_bitmapObj);
    //paint the compatible dc with back bitmap to the first compatible dc with window default paint
    memdc.BitBlt( 0, 
       0, 
       recttree.Width(), 
       recttree.Height(),
       &pDC,
       recttree.left,
       recttree.top,
       SRCAND);
      

  21.   

    我觉得是这样的
    1, draw(point, bitmap)
    {
    画图}
    2,onlbuttonup(point)
    {
    draw(point, bitmap);
    cdocument *pdoc = getdocument();
    pdoc->m_list.add(point, bitmap);   //point位置信息, bitmap位图信息
    InvalidateRect(rect);  //这个rect可以优化,getclipbox和你位图的位置比较找到最小的区域
    }
    3,ondraw()
    {
    for(pdoc->m_list)
    {
       if(   比较位置和rect)
       draw()
    }
    }大概是这样的,还有很多小东西需要修
      

  22.   

    sinhighly,请问你这段代码是在哪里实现的
      

  23.   

    sinhighly,enoloo说在OnLButtonDown里实现,但是好像没有用
      

  24.   

    OnDraw就行,或是OnPaint
    你试试吧
      

  25.   

    不能再OnLButtonDown里做,那样窗口一刷新就没了
      

  26.   

    哦,对不起,应该是说不能只在OnLButtonDown里做
    OnLButtonDown里做对CDC拷贝,蒋新增加的图拷贝到全局的DC对象中
    OnDraw 或 OnPaint 做
    pDC->BitBlt
    将全局DC对象画在窗口上
      

  27.   

    可以把CPoint和CBitmap放到一个类里面去,在将此类实例化后再放入Clist,这样操作会比较方便。另外在OnDraw以后一定要将MemDC占用的内存释放掉,要不然内存很快就会耗完的。
      

  28.   

    sinhighly,我没有看懂你的程序,你能不能详细讲一下呢
      

  29.   

    大概是这样的吧,你再调试一下CDC m_dcToPaint;
    CBitmap m_bitmap;
    m_bitmap.LoadBitmap (bitmapid);void CConfigView::OnLButtonDown (UINT nFlags,CPoint point)
    {//»­½Úµã if (!m_dcToPaint.m_hDC)
    {
    dcMemory.CreateCompatibleDC (pDC);
    }
    CDC dcMemory;
    dcMemory.CreateCompatibleDC (pDC);
    CBitmap* pOldBitmap=dcMemory.SelectObject (&m_bitmap); CSize size;
    size=m_bitmap.GetBitmapDimension ();
    m_cNodeSize=size; CPoint bpt;
    bpt.x =pt.x -bmpInfo.bmWidth/2;
    bpt.y =pt.y -bmpInfo.bmHeight/2;

    m_dcToPaint.BitBlt (bpt.x,bpt.y,bmpInfo.bmWidth ,bmpInfo.bmHeight ,&dcMemory,0,0,SRCAND);
    dcMemory.SelectObject (pOldBitmap);
    dcMemory.DeleteDC();
    }void CConfigView::OnDraw (CDC* pDC)
    {
    pDC->BitBlt (bpt.x,bpt.y,bmpInfo.bmWidth ,bmpInfo.bmHeight ,&m_dcToPaint,0,0,SRCCOPY);
    }z最后在程序退出前
    m_dcToPaint.DeleteDC();
    m_bitmap.DeleteObject();
      

  30.   

    错了,应该是
    void CConfigView::OnDraw (CDC* pDC)
    {
    pDC->BitBlt (0,0,(窗口宽),(窗口高),&m_dcToPaint,0,0,SRCCOPY);
    }
      

  31.   

    好,我再调试一下,多谢sinhighly的耐心指导
      

  32.   

    请问这段:
    if (!m_dcToPaint.m_hDC)
    {
    dcMemory.CreateCompatibleDC (pDC);
    }
    CDC dcMemory;
    不大对,你看呢?
      

  33.   

    m_dcToPaint.CreateCompatibleDC (pDC);
    嗬嗬,写错了
      

  34.   

    哦,那就用
    CPaintDC dc(this); // device context for painting
    dcToPaint.CreateCompatibleDC (&dc);dcMemory创建也这样
    dcMemory.CreateCompatibleDC (&dc);
      

  35.   

    不行呀,运行程序一点击以后就出现运行错误,然后调试就出现了
    BOOL CGdiObject::Attach(HGDIOBJ hObject)
    {
    ASSERT(m_hObject == NULL);      // only attach once, detach on destroy
    if (hObject == NULL)
    return FALSE;
    CHandleMap* pMap = afxMapHGDIOBJ(TRUE); // create map if not exist
    ASSERT(pMap != NULL);
    pMap->SetPermanent(m_hObject = hObject, this);
    return TRUE;
    }
    请问原因何在?
      

  36.   

    sinhighly能不能请你给我讲一下这样做的原理,我再仔细研究一下,谢谢了
      

  37.   

    我靠
    竟然还没有解决 sinhighly(非典型程序员) :
    void CConfigView::OnDraw (CDC* pDC)
    {
    pDC->BitBlt (bpt.x,bpt.y,bmpInfo.bmWidth ,bmpInfo.bmHeight ,&m_dcToPaint,0,0,SRCCOPY);
    }加入point1有一个位图
    现在在point2又画了一个位图,
    加入point1和point2都在重绘区域
    你point1的那个位图重绘了吗?
      

  38.   

    我想用sinhighly的双CDC缓冲,但是一直都有问题,afantict能看一下他给我写的代码吗
      

  39.   

    afantict(巴依老爷) :
    look look 上面的代码
    前面绘的图都画在m_dcToPaint全局变量里了,好像没有丢吧pscqll(飞翔) :
    算了,我还是自己调以下在给你吧
      

  40.   

    代码如下,已经试过了,不过宽度我随便填的,你自己想办法吧,还有OnLButtonDown最好不要用RedrawWindow刷新整个窗口,会闪,只刷新画得那块就行,自己改改吧void CTestpaintView::OnDraw(CDC* pDC)
    {
    CTestpaintDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    pDC->BitBlt (0,0,10000,10000,&m_dcToPaint,0,0,SRCCOPY);}void CTestpaintView::OnLButtonDown(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    CPaintDC dc(this); 
    CRect rectclient;
    //get rect of this tree control
    GetClientRect(&rectclient); if (!m_dcToPaint.m_hDC)
    {
    m_dcToPaint.CreateCompatibleDC (&dc);
    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap(&dc, rectclient.Width(), rectclient.Height());
    m_dcToPaint.SelectObject( &bitmap );
    CBrush brush;
    brush.CreateSysColorBrush(COLOR_WINDOW);
    m_dcToPaint.FillRect(rectclient,&brush);
    }
    CDC dcMemory;
    dcMemory.CreateCompatibleDC (&dc);
    CBitmap* pOldBitmap=dcMemory.SelectObject (&m_bitmap); CSize size;
    size=m_bitmap.GetBitmapDimension ();
    size.cx = 32;
    size.cy = 32; CPoint bpt;
    bpt.x =point.x -size.cx/2; //bmpInfo.bmWidth/2;
    bpt.y =point.y -size.cy/2;//bmpInfo.bmHeight/2;

    m_dcToPaint.BitBlt (bpt.x,bpt.y,size.cx ,size.cy ,&dcMemory,0,0,SRCCOPY);
    dcMemory.SelectObject (pOldBitmap);
    dcMemory.DeleteDC();
    RedrawWindow();
    CView::OnLButtonDown(nFlags, point);
    }
      

  41.   

    把你的位图编号,定义结构{int x,y ,index;};分别存X、Y坐标,和索引,在OnDraw里循环画每一个位图,画之前先判断是否可见,以提高效率;在OnLButtonDown中只画位图覆盖的地方,不用重画整个窗口。如觉得屏不清了,再重画窗口。
      

  42.   

    谢谢sinhighly了,这两天麻烦大家了,现在结题