这是第二次发帖子额!
最近我做了个截图的程序,已经实现的功能是双击选择区域后自动保存。但是本人想改进为双击后截图显示在自动新建的文档上,然后保存。我的程序通过CopyScreenToBitmap(LPRECT lpRect)得到了截图的句柄HBITMAP hMap =  CopyScreenToBitmap(&rect)。(rect是截图的矩形区域)  新建文档还是很好实现的 ,问题关键是怎么把图显示在它上面。由于我这个程序中用的是别人现成的DIB的封装,view中的OnDraw函数如下:
void CMy51View::OnDraw(CDC* pDC)
{
//获取文档类指针
CMy51Doc* pDoc = GetDocument(); //返回m_dib的指针
ImgCenterDib *pDib=pDoc->GetPDib(); //获取DIB的尺寸
CSize sizeFileDib = pDib->GetDimensions(); //显示DIB
pDib->Draw(pDC, CPoint(0, 0), sizeFileDib);
}其中的pDC就是设备环境指针。我现在得到的只是个位图的句柄(HBITMAP hMap ),位图数据也只是在内存里而已,不是一个位图文件的,感觉这与显示一副现成的位图文件是不一样的。封装的DIB类中有DIB的显示函数Draw( )。我就想在取得pDC后,调用Draw(pDC, CPoint(0, 0), sizeFileDib)来显示的。前些天有高手指点,建议写个OnEraseBkgnd(CDC* pDC),如下:
CBitmap * m_pBitmap //背景位图的指针
BOOL CScreenDlg::OnEraseBkgnd(CDC* pDC) 
{
BITMAP bmp;
m_pBitmap->GetBitmap(&bmp); CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC); dcCompatible.SelectObject(m_pBitmap); CRect rect;
GetClientRect(&rect);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY); return TRUE;
}
 但本人不知如何用调用它。另外我的对话框类里还没有OnDraw和OnPaint函数,请问有必要建吗?请各位想想办法,最好有详细的代码,本人新手!麻烦大家了! 

解决方案 »

  1.   

    OnPaint
    ==>在消息中,添加WM_PAINT消息事件
    就可以了
      

  2.   

    在新产生的视图上动态创建一个picture控件,然后把图片加载进去。
      

  3.   

    你在视图窗口显示不就是画图么,当然在OnPaint里面了,不过就是已经画好了往里面贴图罢了
      

  4.   

    我补充下啊!我原来是通过以下代码直接将内存里的图像数据保存为文件了,但里面没显示的代码。我在想可否在其中添加些显示的代码就可以实现功能的!在红色字体的前面SaveBitmapToFile(HBITMAP hBitmap, LPSTR lpFileName)
    {
    HDC     hDC;         
        //设备描述表
     int     iBits;      
     //当前显示分辨率下每个像素所占字节数
     WORD    wBitCount;   
        //位图中每个像素所占字节数
     //定义调色板大小, 位图中像素字节大小 ,  位图文件大小 , 写入文件字节数
     DWORD           dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten;
     BITMAP          Bitmap;        
     //位图属性结构
     BITMAPFILEHEADER   bmfHdr;        
     //位图文件头结构
     BITMAPINFOHEADER   bi;            
     //位图信息头结构 
     LPBITMAPINFOHEADER lpbi;          
     //指向位图信息头结构指针
        HANDLE          fh, hDib, hPal;
     HPALETTE     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 if (iBits <= 24)
      wBitCount = 24;
    else
      wBitCount = 32;
     //计算调色板大小
     if (wBitCount <= 8)
      dwPaletteSize=(1<<wBitCount)*sizeof(RGBQUAD);
     
     //设置位图信息头结构
     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.biClrUsed         = 0;
     bi.biClrImportant      = 0;
     
     dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;
     //为位图内容分配内存/*xxxxxxxx计算位图大小分解一下(解释一下上面的语句)xxxxxxxxxxxxxxxxxxxx 
    //每个扫描行所占的字节数应该为4的整数倍,具体算法为:
     int biWidth = (Bitmap.bmWidth*wBitCount) / 32;
     if((Bitmap.bmWidth*wBitCount) % 32)
      biWidth++; //不是整数倍的加1
     biWidth *= 4;//到这里,计算得到的为每个扫描行的字节数。
     dwBmBitsSize = biWidth * Bitmap.bmHeight;//得到大小
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
     hDib  = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
     *lpbi = bi;
     // 处理调色板   
     hPal = GetStockObject(DEFAULT_PALETTE);
     if (hPal)
     {
      hDC = ::GetDC(NULL);
      hOldPal=SelectPalette(hDC,(HPALETTE)hPal,FALSE);
      RealizePalette(hDC);
     }
     // 获取该调色板下新的像素值
     GetDIBits(hDC,hBitmap,0,(UINT)Bitmap.bmHeight,(LPBYTE)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize, (BITMAPINFO *)lpbi,DIB_RGB_COLORS);
     //恢复调色板   
     if (hOldPal)
     {
      SelectPalette(hDC, hOldPal, TRUE);
      RealizePalette(hDC);
      ::ReleaseDC(NULL, hDC);
     }
     //创建位图文件    
     fh=CreateFile(lpFileName, 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, (LPBYTE)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
     // 写入位图文件其余内容
      WriteFile(fh, (LPBYTE)lpbi, sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize , &dwWritten, NULL); 
    //m_pImgData指向位图数据起始位置
    m_pImgData=(LPBYTE)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize; //清除   
     GlobalUnlock(hDib);
     GlobalFree(hDib);
     CloseHandle(fh);
     return TRUE;
    }
      

  5.   


    那应该在对话框的程序里添加Onpaint啦!可是总感觉不是画吧 因为图像数据就在内存里啊,怎么画啊?晕啦
      

  6.   

    仿造 OnEraseBkgnd的代码,在你的View 内OnDraw里引入:
    void CMy51View::OnDraw(CDC* pDC)
    {
       BITMAP bmp;
       m_pBitmap->GetBitmap(&bmp);   CDC dcCompatible;
       dcCompatible.CreateCompatibleDC(pDC);   dcCompatible.SelectObject(m_pBitmap);   CRect rect;
       GetClientRect(&rect);
       pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);}
      

  7.   

    另外,你的原来的程序不是在Dialog内处理的吗?
    为什么还要那么麻烦地放入文档视图内?
    那样 的话你必须把裁得的区域数据进行传递。在
    CMy51View内加入一个成员
    CBitmap * m_pBitmap //背景位图的指针比如你在原来的Dialog内响应双击后,得到了CMy51View的操作指针 pView
    pView->m_pBitmap = this->m_pBitmap [color=#008000]//把得到的位图数据放入View内的成员

    之后就是按9楼代码处理。[/color]统一用基于Dialog的MFC程序,新建一个DialogA,
    通过指针传递来操作DialogA内的OnPaint 进行代码移植。
      

  8.   

    http://hi.csdn.net/space-11703.html
    这个奸人 大家留言骂他
      

  9.   


    我的程序是在基于对话框的板块中啊!放在文档里是为了好保存成文件的,以后要处理这截取的图像。依你的意思看,从简单易实现的角度来看,我应该怎么做呢?你说在View里的OnDraw中添加那些代码是在原有的基础上(帖子上有,最上面)添加吗? 我来试试啊! 麻烦你回帖子啦!谢谢啦!我有不懂处再问你啊!
      

  10.   

    补充一下!我的程序是多文档的MFC,因为我编的是个图像处理软件,其中的一个功能就是图像截取。所以要显示在文档中的。
      

  11.   

    我试了试你说的方法,在CMy51View内加入一个成员
    CBitmap * m_pBitmap //背景位图的指针
     但是Dialog内响应双击后,得到了CMy51View的操作指针 pView
    pView->m_pBitmap = this->m_pBitmap 中m_pBitmap 就没定义了啊! 怎么办?
      

  12.   


    this->m_pBitmap 指的是你的MDI工程中,截图对话框模块的成员。
      

  13.   

    当你选择好区域rect双击后,
    可用
    m_pBitmap = CBitmap::FromHandle(CopyScreenToBitmap(&rect));保存入m_pBitmap内。

    为了防止出错,等建议不要关闭截图对话框,
    通过ShowWindow
    截图时显示
    其它时候隐藏
    在CMainFrame内进行控制。
      

  14.   

    m_pBitmap = CBitmap::FromHandle(CopyScreenToBitmap(&rect)); 这句我添加在双击响应OnLButtonDblClk(UINT nFlags, CPoint point) 里面 ,随后我新建个文档,获得新建视图指针pView,按照pView->m_pBitmap ,编译报错啊!CBitmap * m_pBitmap 在View里定义的话,那么对话框里面的
    m_pBitmap = CBitmap::FromHandle(CopyScreenToBitmap(&rect)); 就会报错,m_pBitmap没有定义。
    我不知指针传递怎么的,请详细指点下! 我现在的目的很简单,就是显示出来就可以了。
      

  15.   



    指针传递的问题你要自己看书学习
    你的截图Dialog内定义
    CBitmap * m_pBitmapRect。View内 定义CBitmap * m_pBitmapView。
    截图Dialog内响应双击后,得到了CMy51View的操作指针 pView
    pView->m_pBitmapView = m_pBitmapRect;//如此传递

    如果还报错,请把具体内容帖出来。
      

  16.   


    我已按照你说的去添加了代码,但是对于以下代码的添加之处有点不清楚
    void CMy51View::OnDraw(CDC* pDC)
    {
       BITMAP bmp;
       m_pBitmap->GetBitmap(&bmp);   CDC dcCompatible;
       dcCompatible.CreateCompatibleDC(pDC);   dcCompatible.SelectObject(m_pBitmap);   CRect rect;
       GetClientRect(&rect);
       pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);}
    添加OnDraw里会运行会出错的,原来OnDraw里的代码是不能删的,到底添加在哪儿合适呢?请指点下啊!
      

  17.   

    void CMy51View::OnDraw(CDC* pDC)
    {
    CClockDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // TODO: add draw code for native data here
    // 加在这里,另外,请注意BitBlt的用法。
    }
      

  18.   


    我现在的代码OnDraw里面已经是如下了: 这是别人修改过的,因为我用了别人封装好的DIB了。所以再把那代码加上去,就直接运行报错了。OnDraw就是显示嘛,我感觉把要显示的数据传递到这儿应该就可以显示了呀!是不是应该另外建个函数的?
    void CMy51View::OnDraw(CDC* pDC)
    {
    //获取文档类指针
    CMy51Doc* pDoc = GetDocument();//返回m_dib的指针
    ImgCenterDib *pDib=pDoc->GetPDib();//获取DIB的尺寸
    CSize sizeFileDib = pDib->GetDimensions();//显示DIB
    pDib->Draw(pDC, CPoint(0, 0), sizeFileDib);
    }
      

  19.   

    别人封装好的DIB?
    对此我也不熟悉,
    你要自己看明白别人的类的
    每个函数、变量的含义。一个View内只能有一个
    OnDraw(CDC* pDC)
    除非你重载出另外一个。
    如果是我之前给你推荐的那个QQ 截图程序,按9楼的代码就没问题。
      

  20.   


    对!我用的是别人封装好的DIB,可以打开,读取bmp图像,因为后面用到的一些算法实现都是以此为基类派生的,所以OnDraw里面已经改动过了。如果删去的话,估计连打开图像就不可以了。你看现在怎么办啊? 
      

  21.   

     我的双击函数如下,为什么就只新建个文档,而没有显示呢?难道我就不能直接显示吗?非要传递指针?请指点下!
     
    void CScreenDlg::OnLButtonDblClk(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
       
        CRect rect;
        rect.left =(this->startPt.x<this->endPt.x)?this->startPt.x:this->endPt.x;
        rect.top = (this->startPt.y<this->endPt.y)?this->startPt.y:this->endPt.y;
        rect.right =(this->endPt.x>this->startPt.x)?this->endPt.x:this->startPt.x;
        rect.bottom =(this->endPt.y>this->startPt.y)?this->endPt.y:this->startPt.y;
      HBITMAP hMap =  CopyScreenToBitmap(&rect); 
      m_pBitmap=CBitmap::FromHandle(CopyScreenToBitmap(&rect));  CMainFrame* pFrame = (CMainFrame *)(AfxGetApp()->m_pMainWnd);
      //发送一个新建文件的消息,创建一个新的文档-视图
      pFrame->SendMessage(WM_COMMAND, ID_FILE_NEW);  //获取新建视图指针
      CMy51View* pView=(CMy51View*)pFrame->MDIGetActive()->GetActiveView();  //获取相关联的新的文档类指针
      CMy51Doc* pDocNew=pView->GetDocument();  //获取新文档中的ImgCenterDib类对象指针
      ImgCenterDib *dibNew=pDocNew->GetPDib();  pView->m_pBitmapView = m_pBitmap;    CDC* pDC;
       pDC = this->GetDC();
       CDC dcCompatible;
       dcCompatible.CreateCompatibleDC(pDC);   dcCompatible.SelectObject(m_pBitmap);   GetClientRect(&rect);
       pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);  //文档数据置脏,提示存盘信息
      pDocNew->SetModifiedFlag(TRUE);  //各视图刷新显示
      pDocNew->UpdateAllViews(pView);   dibNew->SaveBitmapToFile(hMap,"C:\\截屏.bmp");
       
          this->EndDialog(0); CDialog::OnLButtonDblClk(nFlags, point);
    }
      

  22.   


    一个主程序里的View类里只能有一个OnDraw,里面的内容是不能变的,因为涉及到很多子功能都要沿用这一个基类的。可不可以不改动OnDraw里,而实现显示呢?我认为应该可行啊!
    我现在编这个截图的程序是单独编的,没有和总程序挂上钩,以后还是要嵌入到其中,不知能不能成功的,到时候有问题的话,我再请教你啊!
      

  23.   


    那么你必须要有显示的容器才可能,
    也可以考虑截图后,New一个新的对话框,把截图得到的BMP内存数据复制过去,并显示。
    之后就可以CDialog::OnLButtonDblClk(nFlags, point);// 放在第一句…… // 相关内容this->EndDialog(0);//放在最后一句// 为什么是这个顺序,自己思考一下
    }
      

  24.   


    我的意思是在不改动我现有的OnDraw函数的前提下,能否依然显示在文档里面。OnDraw函数改动了,那么打开显示别的任意的图片就不得行了啊!你看还有没有别的方法?
      

  25.   

    void CMy51View::OnDraw(CDC* pDC)
    {
    //获取文档类指针
    CMy51Doc* pDoc = GetDocument();//返回m_dib的指针?
    //m_dib是什么类型?
    //ImgCenterDib是什么类型?ImgCenterDib *pDib=pDoc->GetPDib();//获取DIB的尺寸
    CSize sizeFileDib = pDib->GetDimensions();//显示DIB
    pDib->Draw(pDC, CPoint(0, 0), sizeFileDib);
    }以上是我的疑问,我认为你还是仔细理解人家的DIB类后再作决策。1. 关键在于明确ImgCenterDib *pDib 与 CBitmap* m_pBitmapView 
    之间的关系后,才可以移植组合入同一个View内进行显示。2. 不然,就让文档分工显示。
      

  26.   


    你所言极是,有些地方还是有点看不懂的。我把代码传到我的资源里去了,如果你有时间的话,可以看看的啊!ImgCenterDib是一个DIB类,m_dib是它的一个对象。ImgCenterDib *pDib=pDoc->GetPDib();这句话是获取DIB的指针。
      

  27.   


    http://download.csdn.net/source/2343300
      

  28.   


    我上传的图像截取的下载地址 http://download.csdn.net/source/2343300
      

  29.   

    用StretchDIBits啊
    SetStretchBltMode(pDC->m_hDC,BLACKONWHITE|WHITEONBLACK);
    StretchDIBits(pDC->m_hDC, 0, 0, w, h, 0, 0, Width, Height, 
    pDoc->pDataL[nLayer], pDoc->pBitmapInfoL[nLayer], DIB_RGB_COLORS, SRCCOPY);
    pData为数据区首指针
    pBitmapInfo为信息头指针
    既然你获得了图片句柄,这个是很容易获得的。在对话框中显示,要重载OnPaint。
    可以添加一个CStatic,得到CWnd类指针后,GetDC(),然后绘图
      

  30.   


    我不是想在对话框里显示,是在新建文档里显示的。你看看我的程序吧!http://download.csdn.net/source/2343300 
      

  31.   

    主要是我用的是别人封装好的DIB类,你说的StretchDIBits ,那个类里的显示函数里都有的,现在关键是怎么样联系起来
      

  32.   

    To sunshineJ313:已发,你查收
    To YANDONGLIANG:不好意思,这代码不是我的,我无权赠予,而且这个也和矢量图无关,有兴趣的话你可以向楼主索要
      

  33.   


    http://download.csdn.net/source/2343300  你去下载嘛 
      

  34.   


    CDIB 直接用Draw函数啊。不用别人的类用API也是一样。
    另外请问楼主是不是做遥感的啊?
      

  35.   


    我看到了的,你加了个OnPaint消息处理函数,设置为私有的。但是为什么加上这个函数后,就不能打开bmp图像了呢?请指点下啊!
      

  36.   

    补充一下,好像你改动后的Veiw里面的MFC Classwizard也没有了,我在原来的程序里按添加消息响应的方法加上你的OnPaint函数,编译时没有问题,运行就报错。请问这与你的哪些改动有关啊?有点迷惑,呵呵!
      

  37.   

    呵呵!突然发现是m_pBitmapView没有初始化造成出错的,能运行了。但是还是打不开bmp图片的!!!!!!!!!!!就是无法显示的。这怎么解决啊?