最近在写画图程序,我用gdi画图函数在窗体中画线,然后把画线结果保存到一个位图文件中,当打开位图的时候,将他显示在窗体中需要和用gdi在窗体中画图的效果一模一样我是通过在OnMouseMove函数中通过扫描鼠标移动前后两个坐标构成的矩形,通过GetPixel函数获得获得每个坐标的rgb值,然后再设置bmp位图的数据区的相对应的坐标值,理论上这个方法是可以的,但是我的程序运行画图后保存的线条不连续,还有个特别奇怪的地方,就是从上到下的画能保存成连续线的位图,从下到上的画就是间断的点,鼠标移动越快,越不连续代码大致如下void CZuoyeView::OnMouseMove(UINT nFlags, CPoint point) 
{
       
                       CPen  pen;
                       pen.CreatePen(PS_SOLID,m_nPenWidth,m_crPenColor);//m_nPenWidth和m_crPenColor是view类 ////////的成员变量 dc->SelectObject(pen);
dc->MoveTo(m_ptMouseMoveTmp);//m_ptMouseMoveTmp是保存每次鼠标移动时的窗体坐标,以便下次用
dc->LineTo(point);

                        pDib->MapFromHdcToBmp(m_ptMouseMoveTmp,point,dc,m_nPenWidth);
                       //pDib是一个位图类,专门处理位图数据,这个函数作用是扫描dc在这两个点构成的矩形的像素,通过GetPixel函数实现,并保存到位图
    
            m_ptMouseMoveTmp=point;
}各位有没有其它更好的方法,这个方法估计是每次用gdi画图后,dc上面的像素值还没改变,我就去用GetPixel去获取rgb,最后还是得到的原来的dc上面的rgb值,这部分的值就是断的,所以会出现间断

解决方案 »

  1.   


    #include "WINDOWSX.H" CClientDC SHDC(this);//取得客户区内存DC
     CPaintDC   dc(this);
     CDC memDC;
     CRect rect;
     GetClientRect(rect); memDC.CreateCompatibleDC(&SHDC);
     CBitmap bm;
     int Width = rect.Width();//
     int Height = rect.Height();//
     bm.CreateCompatibleBitmap(&SHDC, Width, Height);
     CBitmap*  pOld = memDC.SelectObject(&bm);
     memDC.BitBlt(0, 0, Width, Height, &SHDC, 0, 0, SRCCOPY);
     memDC.SelectObject(pOld);
     BITMAP  btm;
     bm.GetBitmap(&btm);
     DWORD  size = btm.bmWidthBytes * btm.bmHeight;
     LPSTR lpData =(LPSTR)GlobalAllocPtr(GPTR, size);
     BITMAPFILEHEADER   bfh;
    /////////////////////////////////////////////
     BITMAPINFOHEADER  bih;
     bih.biBitCount = btm.bmBitsPixel;
     bih.biClrImportant = 0;
     bih.biClrUsed = 0;
     bih.biCompression = 0;
     bih.biHeight = btm.bmHeight;
     bih.biPlanes = 1;
     bih.biSize = sizeof(BITMAPINFOHEADER);
     bih.biSizeImage = size;
     bih.biWidth = btm.bmWidth;
     bih.biXPelsPerMeter = 0;
     bih.biYPelsPerMeter = 0;
     GetDIBits(dc,bm,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);
     bfh.bfReserved1 = bfh.bfReserved2 = 0;
     bfh.bfType = ((WORD)('M'<< 8)|'B');
     bfh.bfSize = 54 + size;
     bfh.bfOffBits = 54; CFileDialog dlg(false,_T("BMP"),_T("*.bmp"),OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,_T("*.bmp|*.bmp|*.*|*.*|"));
     if (dlg.DoModal()==IDOK)
     {
      CFile  bf;
      CString ss=dlg.GetPathName();
      if(bf.Open(ss, CFile::modeCreate | CFile::modeWrite))
      {
       bf.WriteHuge(&bfh, sizeof(BITMAPFILEHEADER));
       bf.WriteHuge(&bih, sizeof(BITMAPINFOHEADER));
       bf.WriteHuge(lpData, size);
       bf.Close();
      }
      GlobalFreePtr(lpData);
     }
      

  2.   

    this所指的窗口内容保存为图片
      

  3.   

    1.鼠标的点迹肯定是不连续的,这个不要再多想了。打CS的时候甩狙就是这么来的,呵呵。
    2.(如果用户操作完成后,有正确的界面显示)保存成位图,然后再打开是可以的,比较直接。

    参考:http://topic.csdn.net/u/20120301/16/35313613-78ac-49b9-b93b-8ec3a12f3edd.html
    3.采集鼠标点,保存成二进制或者文本文件,下次用户打开二进制或者文本文件,读取其中的窗体、画笔、背景及鼠标点迹等等信息使用GDI绘图方法重新绘图也可以,这样做,可以减少保存位图时的大存储量。
    4.楼主的方法理论上也是可行的,不过要考虑到,不连续的鼠标点之间应该采用直线、曲线等方式连接起来,这样需要楼主在DIB位图数据中进行计算。例如,两个相接但不连续的点(10,10)(12,12)。不但要将(10,10)及(12,12)两个点设置颜色,还需要将(11,11)也设定颜色。在DIB操作的时候如果这样做,直线时还方便一点,如果需要用曲线连接(例如贝塞尔),那就麻烦大了。
    微薄之建议,楼主参考