以前没做过关于图片处理的,由于最近项目的需要,做一个波形图保存的东西!
已知:波形图生成的数据集合,波形图生存的方法ap_MakeTanpaku(pDC);
需求:将显示在对话框上的波形图,保存BMP格式的图片
在网上找了一些例子,以下是测试程序
void TanpakuDlg::Onpaint(){
  cpaintDc dc(this);
  CRect rect;
  GetClientRect(rect);
  dc.FillSolidRect(rect,RGB(255,255,255));
  CDC pDC = this->GetDC();
  //在对话框上描画波形图
  ap_MakeTanpaku(pDC);
  //这里的saveBmp和GetSrcBit都是网上提供的,没经过修改!GetSrcBit中的400,300,是我随意写的
  saveBmp(GetSrcBit(pDC->m_hbc,400,300),m_FileName);
}
问题1:结果是保存了一张空白图片,DEBUG发现,pDC->m_hbc是空的,是什么原因导致保存的图片为空呢?
不是很了解图片的处理机制,十分的纠结~哪位大虾帮帮忙!!!不胜感激!!!

解决方案 »

  1.   

    你都说了  pDC->m_hbc是空的
      

  2.   

    用dc画,不要在Onpaint里用CDC,本站上有人已说了不能在这个函数里用CDC
      

  3.   

     CDC pDC = &dc;
      

  4.   

    两个函数,具体不解释了,通过名字和参数类型应该知道是做什么用的,楼主的函数可能和这个一样:
    HBITMAP CopyDCToBitmap(HDC hScrDC, LPRECT lpRect)
    {
    HDC hMemDC; 
    // 屏幕和内存设备描述表 
    HBITMAP hBitmap,hOldBitmap; 
    // 位图句柄 
    int nX, nY, nX2, nY2; 
    // 选定区域坐标 
    int nWidth, nHeight; 
    // 位图宽度和高度 

    // 确保选定区域不为空矩形 
    if ( IsRectEmpty( lpRect ) ) return NULL; 

    // 获得选定区域坐标 
    nX=   lpRect->left; 
    nY=   lpRect->top; 
    nX2 = lpRect->right; 
    nY2 = lpRect->bottom; 
    nWidth  = nX2 - nX; 
    nHeight = nY2 - nY; 
    //为屏幕设备描述表创建兼容的内存设备描述表 
    hMemDC= CreateCompatibleDC( hScrDC ); 
    // 创建一个与屏幕设备描述表兼容的位图 
    hBitmap = CreateCompatibleBitmap( hScrDC, nWidth, nHeight ); 
    // 把新位图选到内存设备描述表中 
    hOldBitmap = ( HBITMAP )SelectObject( hMemDC, hBitmap ); 
    // 把屏幕设备描述表拷贝到内存设备描述表中 
    StretchBlt( hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, nWidth, nHeight, SRCCOPY );
    //得到屏幕位图的句柄 
    hBitmap = ( HBITMAP )SelectObject( hMemDC, hOldBitmap ); 
    //清除
    DeleteDC( hMemDC ); 
    DeleteObject( hOldBitmap ); 
    //返回位图句柄 
    return hBitmap;
    }BOOL SaveBmp(HBITMAP hBitmap, CString FileName)
    {
    HDC hDC; 
    //当前分辨率下每象素所占字节数 
    int iBits; 
    //位图中每象素所占字节数 
    WORD wBitCount; 
    //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数 
    DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0; 
    //位图属性结构 
    BITMAP Bitmap; 
    //位图文件头结构 
    BITMAPFILEHEADER bmfHdr; 
    //位图信息头结构 
    BITMAPINFOHEADER bi; 
    //指向位图信息头结构 
    LPBITMAPINFOHEADER lpbi; 
    //定义文件,分配内存句柄,调色板句柄 
    HANDLE fh, hDib, hPal,hOldPal=NULL; 

    //计算位图文件每个像素所占字节数 
    hDC = CreateDC("DISPLAY", NULL, NULL, NULL); 
    iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); 
    DeleteDC(hDC); 
    if (iBits <= 1) wBitCount = 1; 
    else if (iBits <= 4) wBitCount = 4; 
    else if (iBits <= 8) wBitCount = 8; 
    else wBitCount = 24; 

    GetObject( hBitmap, sizeof( Bitmap ), ( LPSTR )&Bitmap ); 
    bi.biSize = sizeof( BITMAPINFOHEADER ); 
    bi.biWidth = Bitmap.bmWidth; 
    bi.biHeight = Bitmap.bmHeight; 
    bi.biPlanes = 1; 
    bi.biBitCount = wBitCount; 
    bi.biCompression = BI_RGB; 
    bi.biSizeImage = 0; 
    bi.biXPelsPerMeter = 0; 
    bi.biYPelsPerMeter = 0; 
    bi.biClrImportant = 0; 
    bi.biClrUsed = 0; 

    dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight; 

    //为位图内容分配内存 
    hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER)); 
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
    *lpbi = bi; 

    // 处理调色板 
    hPal = GetStockObject(DEFAULT_PALETTE); 
    if (hPal) 

    hDC = ::GetDC(NULL); 
    //hDC = m_pDc->GetSafeHdc(); 
    hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE); 
    RealizePalette(hDC); 

    // 获取该调色板下新的像素值 
    GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) 
    +dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS); 

    //恢复调色板 
    if (hOldPal) 

    ::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE); 
    RealizePalette(hDC); 
    ::ReleaseDC(NULL, hDC); 



    //创建位图文件 
    fh = CreateFile(FileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS, 
    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 

    if (fh == INVALID_HANDLE_VALUE) return FALSE; 

    // 设置位图文件头 
    bmfHdr.bfType = 0x4D42; // "BM" 
    dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; 
    bmfHdr.bfSize = dwDIBSize; 
    bmfHdr.bfReserved1 = 0; 
    bmfHdr.bfReserved2 = 0; 
    bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize; 
    // 写入位图文件头 
    WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 
    // 写入位图文件其余内容 
    WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL); 
    //清除 
    GlobalUnlock(hDib); 
    GlobalFree(hDib); 
    CloseHandle(fh); 

    return TRUE; 
    }
    使用方法: CDC *pdc=GetDC();
    CDC MenDC; 
    CBitmap bm;
    MenDC.CreateCompatibleDC( pdc ); 
    bm.CreateCompatibleBitmap( pdc, int( txWD+2 ), int( txHT+2 ) ); 
    //txWD和TxHT为客户区大小,根据你的窗口来设定
    MenDC.SelectObject( &bm );

    //MenDC.TextOut( 1, 1, “写一行文字”);
            //此处用MenDC绘制你所要的波形
    //----------------------------------------------------
    // 设定你要从CBitmap bm;上截取哪一部分。
    //----------------------------------------------------
    RECT rt;
    rt.left = 0; rt.right  = int( 512 );
    rt.top  = 0; rt.bottom = int( 512 );

    //----------------------------------------------------

    HBITMAP hBmp = Kp.CopyDCToBitmap( MenDC.GetSafeHdc(), &rt ); 
    Kp.SaveBmp( hBmp, "MyDC.bmp" );

    //----------------------------------------------------

    bm.DeleteObject();
    MenDC.DeleteDC();
    ReleaseDC(pdc);
    最后一个函数如果有某些地方编译不过,楼主改一改
      

  5.   

    感谢楼上几位~
    ap_MakeTanpaku(&MenDC);
    结果波形图画不出来了~~
    是不是保存BMP不应该在Onpaint里做?
      

  6.   

    保存不分在哪,楼主先用视图试试,在视图里调试通过后再改成对话框
    ap_MakeTanpaku(&amp;MenDC);这句好象不对,是不是这样:ap_MakeTanpaku(&amp,MenDC);
      

  7.   

    好的,回去试试
    开始我怀疑是画图出了问题,结果我把画图不分去掉,直接
    CDC *pdc=GetDC();
        CDC MenDC; 
        CBitmap bm;    
        MenDC.CreateCompatibleDC( pdc ); 
        bm.CreateCompatibleBitmap( pdc, int( txWD+2 ), int( txHT+2 ) ); 
        //txWD和TxHT为客户区大小,根据你的窗口来设定
        MenDC.SelectObject( &bm );
    直接用MenDC去画一条线~~,结果在对话框上直线都没画出来~~纠结了.....我在说一下程序流程吧,可能是有些地方我真不懂~在对话框操作有些内部处理,不明了导致到现在保存不了BMP文件!
    1:由Timer事件触发,监视文件strFilePath
    2:读取strFilePath下的CSV文件,构建波形图数据
    3:对话框的类TanpakuDlg Dlg = new TanpankuDlg(this)
       .......
       显示对话框
    4:在TanpakuDlg类中的Onpaint方法中绘制波形图~~
    5:也是在Onpaint中,想保存这个波形图!!
    是不是在Timer事件重新定义了TanpakuDlg Dlg = new TanpankuDlg(this)导致的阿~~
    真心求解~~