首先是一个对话框程序,没有view类ondraw
有onpaint主对话框上一个picture控件,ID名为picture1主对话框上有一个按钮,叫打开图片,ID为IDB_OPEN,单击事件是打开图片到....加载图片,最后InvalidateRect(&ClearRect,TRUE);onpaint事件里面是这么写的                  CPaintDC dc(this); 
CPaintDC pdc(GetDlgItem(IDC_Picture1));//定义容器
ShowRect.left=0-HS_Value;//水平
ShowRect.top=0-VS_Value;//垂直
ShowRect.right=w-HS_Value;//水平
ShowRect.bottom =h-VS_Value;//垂直一定要全部,否则缩放
image->Draw(pdc,ShowRect,&ClipRect);//Cximage *image;
ReleaseDC(&pdc);主对话框上还有一个按钮,叫手动画线,IDB_handDarw提问:程序要求在open图像后,picture1容器中存在一幅位图时,单击[手动画线]按钮后,
鼠标移动到picture1中的图片上,在位图上单击鼠标用鼠标拖拉一根直线,“不闪烁”?这样的操作我其实会写,在movedown mousemove onpaint 事件分别写代码,记录point,不停paint,但是画线很闪烁
我的思路被放弃我查了网上的资料,有一个技术叫双缓冲,还是改进的三缓冲但是线画到picture1控件下面去了,也就是在对话框上,怎么画到picture1容器中贴代码//.h
CBitmap memBakBMP; //新缓冲区内存DC
 CDC memBakDC;        //新缓冲区用的位图
 BOOL bClicked;          //判断是否应当作图
 CPoint ptBegin;          //记录图象开始的位置
 CBitmap memBMP;    //新缓冲区用的位图
 CDC memDC;           //旧缓冲区内存DC//创建时
int CBSYDDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;

// TODO: Add your specialized creation code here
memDC.CreateCompatibleDC(NULL);
 memBMP.CreateCompatibleBitmap(&memDC,1024,768);
 memDC.SelectObject(&memBMP);
 memDC.FillSolidRect(0,0,1024,768,GetDC()->GetBkColor());
 memBakDC.CreateCompatibleDC(NULL);
 memBakBMP.CreateCompatibleBitmap(&memBakDC,1024,768);
 memBakDC.SelectObject(&memBakBMP);
  return 0;
}void CBSYDDlg::handDarw() 
{
m_measure=1;//标志为1,代表手动画线
}void CBSYDDlg::OnMouseMove(UINT nFlags, CPoint point) 
{if(m_measure==1);//标志为1,代表手动画线{
CRect rect;
           GetClientRect(&rect);
memBakDC.BitBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);
memDC.BitBlt(0,0,rect.Width(),rect.Height(),&memBakDC,0,0,SRCCOPY);
memDC.MoveTo(100,100);//假设起点在100,100位置处,现在是测试,不考虑第一个点
memDC.LineTo(point);
Invalidate(false);

}
void CBSYDDlg::OnPaint() 
{
CPaintDC dc(this); 

if(m_measure==1)//;//标志为1,代表手动画线
{
         CDC* pdc1 = GetDC();
CRect rect;
GetClientRect(&rect);
pdc1->BitBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);
ReleaseDC(pdc1);
} if(m_measure!=1)//不是画线
{
CPaintDC pdc(GetDlgItem(IDC_Picture1));//定义容器
ShowRect.left=0-HS_Value;//水平
ShowRect.top=0-VS_Value;//垂直
ShowRect.right=w-HS_Value;//水平
ShowRect.bottom =h-VS_Value;//垂直一定要全部,否则缩放
image->Draw(pdc,ShowRect,&ClipRect);
ReleaseDC(&pdc);
}
}现在这个代码是一团糟,打开图片后正常,一但点击"手动测量"按钮
开始画线了,原来的图片框不见了,移动鼠标直接在窗体画很多线,原来的线也不擦除,彻底无语:-(我想达到的功能是,点击"手动测量"按钮
在picture1中的图片上实时画一条直线条,不擦除背景,用鼠标移动动态画一条直线
就好比windows画图一样,你在打开的图片上画一条直线奉献所有可用分求解!!不胜感谢

解决方案 »

  1.   

    你的CPaintDC dc(this)获得的是窗口的DC,当然在窗口里面画了。
    你得获得picture1控件的DC画线,也就是this要改成this->picture1控件。
    图片要画在OnPaint里面,而不是在初始化画一下就完了。擦除原来的线你得用InvalidateRect,并且记录线的轨迹,按着轨迹擦这样不会闪。
      

  2.   

    TO飞狐大侠vc基础不牢靠,对dc,this指针不是很精通,this->picture1写不起来,onpaint()中第一句改成CPaintDC dc(GetDlgItem(IDC_Picture1)); 运行后窗体都看不到了,请详解另双缓中有一段,这个代码返回真,我的窗体除了按钮,图片框,其他地方变成透明的了,什么个情况?
    BOOL CBSYDDlg::OnEraseBkgnd(CDC* pDC) 
    {
    // TODO: Add your message handler code here and/or call default
    return TRUE;
    //return CDialog::OnEraseBkgnd(pDC);
    }
      

  3.   


    我这没说清楚。原来的CPaintDC dc(this)不要动。另外在Picture控件的OnPaint声明一个DC,比如CPaintDC dcPic(GetDlgItem(IDC_Picture1)),用这个dcPic去绘图画线。没有Picture的继承类就继承一个。
    OnEraseBkgnd返回TRUE的时候,一定要给pDC填充东西,不然背景就乱了。你这里的OnEraseBkgnd就返回FALSE,因为你这里又不需要擦除背景。
      

  4.   

    楼主,这样:
    1.
    BOOL CBSYDDlg::OnEraseBkgnd(CDC* pDC)  
    {
    // TODO: Add your message handler code here and/or call default
    return FALSE;
    //return CDialog::OnEraseBkgnd(pDC);
    }你如果用双缓冲绘制全界面的画,就不需要return true..这是你闪烁的一个原因.2.
    双缓冲是概念上的,就是你看到的闪烁是因为你屏幕的pDC操作很多次造成的.因此好方法就是全部在内存里画好,屏幕画一次就看不到闪烁了.
      

  5.   

    谢谢大家TO飞狐大侠:
    如果在onpaint()中
    CPaintDC dcPic(GetDlgItem(IDC_Picture1)),
    然后用这个dcPic去绘图画线那这样好像不算是用内存dc去画线了?那在onpaint中多次画线,那就算线搞出来不还是闪烁吗
      

  6.   


    汗,你自己搞一个内存DC啊,这个dcPic只是用来最后贴到屏幕上用的
      

  7.   

    谢谢大家,画线已经不闪烁了,最后一个问题,为何得不到图像背景,只是白屏黑色线条,原来的图像到哪去了??????????????????????????????????????????????????????帮看看下面的代码哪句错了void CBSYDDlg::OnPaint() 
    {
    CPaintDC dc(this); 
    if(m_measure==1)
    { CWnd* pPictureWnd = GetDlgItem(IDC_Picture1);
    CDC* pdc = pPictureWnd->GetDC();
    CDC dcMem; //用于缓冲作图的内存DC  
    CDC* pMem=&dcMem;
    CBitmap bmp; //内存中承载临时图象的位图 
    CRect myrect;
    GetClientRect(&myrect); 
    dcMem.CreateCompatibleDC(pdc); //依附窗口DC创建兼容内存DC 
    bmp.CreateCompatibleBitmap(pdc,w,h);//创建兼容位图 
    dcMem.SelectObject(&bmp); //将位图选择进内存DC 
    //按原来背景填充客户区,不然会是黑色 
    dcMem.FillSolidRect(myrect,pdc->GetBkColor()); 
    /////////防闪烁程序段1结束/////////////////////////////////
    dcMem.MoveTo(100,100);
    dcMem.LineTo(x,y);
    CPaintDC pDC1(GetDlgItem(IDC_Picture1));//定义容器
    /////////防闪烁程序段2开始/////////////////////////////////
    pDC1.BitBlt(0,0,w,h, &dcMem,0,0,SRCCOPY);//将内存DC上的图象拷贝到前台 
    dcMem.DeleteDC(); //删除DC 
    bmp.DeleteObject(); //删除位图 
    }
    }
      

  8.   


    你这个if(m_measure==1)是干什么的,去掉试试
      

  9.   

    m_measure==1 是标志
    去不去掉是一样的因为onpaint 还有其它调用,为了和其它功能区分开来
      

  10.   

    继承一个picture控件,在picture::OnEraseBkgnd(CDC* pDC)里面用pDC->Bitblt贴图,并返回TRUE
      

  11.   

    重载CStatic类,自己处理WM_LBUTTONDOWN,WM_LBUTTONUP消息,OnPaint中画线
      

  12.   


    继承CStatic也可以,新建一个类,继承CStatic。在新类::OnEraseBkgnd(CDC* pDC)里面用pDC->Bitblt贴图,就是你上面的代码,并返回TRUE