各位,我需要画一幅图片,在后面的操作中需要作为背景,所以在画图后需要保存下来。
draw_background(memDC); int bytes;
DWORD lasterr;

bytes=GetBitmapBits(hBmp, bmp_width*bmp_height*4, (LPVOID)&uv_bkground);
if(!bytes)
{
lasterr=GetLastError();
} BitBlt(hDC, 0, 0, bmp_width, bmp_height, memDC, 0, 0, SRCCOPY);
     
     位图的宽度是240像素,高度是212,每个像素是32bit。上面代码执行后,可以看到输出图像,但是uv_bkground中的数据都是205,这个是怎么回事?跟踪发现bytes等于0,lasterr也是0,这个真是奇怪。

解决方案 »

  1.   

    GetBitmapBits(hBmp, bmp_width*bmp_height*4, (LPVOID)&uv_bkground);
    看看这3个参数是否有问题,比如hBmp、传入字节的大小、还有具体的buff都是否有问题!
    你确信要拷贝的字节的大小是:bmp_width*bmp_height*4?
      

  2.   

    你看看GetBitmapBits后的GetLastError值是什么,初步怀疑是你给了个无效的Bitmap句柄?
      

  3.   

        谢谢各位。
         现在感觉很困惑。因为我在另外的一个基于MFC的程序里用这个函数做过同样的事情,结果是正确的。
        现在用API的方式,结果却不行了。
        有人讲,GetBitmapBits是为了兼容16位windows的,所以用GetDIBits来代替它更好,但是,这个函数是设备无关的,不太适合我的要求:我只是想把初始画好的背景图保存下来,然后在以后的每一帧中作为它们的背景来显示。如果用设备无关,那么就还需要转换回去。    我看了那个GetLastError()返回值,是0;
        hBmp我感觉似乎没有问题,因为后面的背景图可以正常显示:
    SelectObject(memDC, hBmp);
    //在draw_background()完成背景内存分配
    draw_background(memDC); int bytes;
    DWORD lasterr;
    long lbytes;
    lbytes=GetBitmapBits(hBmp, 0, NULL);

    bytes=GetBitmapBits(hBmp, lbytes, (LPVOID)&uv_bkground);
    if(!bytes)
    {
    lasterr=GetLastError();
    }                //这里可以正常显示画出的背景图
    BitBlt(hDC, 0, 0, bmp_width, bmp_height, memDC, 0, 0, SRCCOPY);      
         
      

  4.   

    lbytes=GetBitmapBits(hBmp, 0, NULL);是不是就有问题了?
    导致bytes=GetBitmapBits(hBmp, lbytes, (LPVOID)&uv_bkground);这里lbytes=0,所以没有LastError?
      

  5.   

        这lbytes=GetBitmapBits(hBmp, 0, NULL);是从网上看到的,人家说是获取hBmp这个位图的缓存大小,但是获取的值是250000,非常奇怪。因为我现在屏幕的设置是32比特的。图像bmp_width=240, bmp_height=212;
        然后后面的bytes仍然是0,就是说还是没有复制过来?!
         这真是奇怪。
      

  6.   

    你要用GetObject来取Bitmap的信息然后计算数组大小,然后把它给GetBitmapBits
      

  7.   

        现在发现位图的大小有问题,和我期望的不一样。
        创建一个包含标题栏的窗口,width=height=250; 获取客户区的宽度(取4的倍数)和高度:bmp_width=240, bmp_height=212;希望用这个大小来创建位图。
        CreateCompatibleBitmap(hDC, bmp_width, bmp_height);
        但奇怪的是,用GetObject获取的位图的宽度是250,高度是250;不是期望中的bmp_width*bmp_height=240*212;
        
        这个是为什么?
        
      

  8.   

       这个hDC是这样获取的:hDC=GetDC(hwnd);
       hwnd是我创建的窗口。    
      

  9.   

    hDC=GetDC(hwnd)所以是窗口的大小width=height=250?
      

  10.   

        我也想用GetClientDC测试一下,但是我不能用mfc,必须用API,但是API里貌似没有GetClientDC
    这个函数?     刚才创建一个popup窗口,没有边框和标题,width=248, height=250;这样位图的宽度和高度取值bmp_width=248, bmp_height=250, 但是即使这样GetBitmapBits复制的字节数量仍然是0,GetLastError返回的也是0,和上面的结果还是一样。
       
         真是没招了。
       
      

  11.   

       然后我想GetObject里面不是获取了一个BITMAP结构对象,里面不是有个bmBits指针么?这个指针不知道是否指向位图像素数组? //直接内存复制好了
    memcpy((BYTE *)uv_bkground, (BYTE *)bm.bmBits, bmp_width*bmp_height*4);
       让人郁闷的是,这个语句编译通过,执行错误。
      
        真的让人奇怪,我画了一个位图,想把它保存下来,然后做为新一帧图的背景,这个在API下就不能实现了么(在mfc下的确可以实现)?
      

  12.   

    MFC能实现,那么你可以参考MFC的源码啊(VS安装的时候可以选择安装MFC源码),里面也是用API实现的。另外你说的GetClientDC函数,貌似MFC里也没有啊,是哪个类的方法?
      

  13.   

       mfc实现,用的是同样的函数,不过就是一个bmp类而已,代码如下:
    void my_pic::OnPaint()
    {
    CPaintDC dc(this); if(memDC.GetSafeHdc()==NULL && bmp.GetSafeHandle()==NULL)
    {
    memDC.CreateCompatibleDC(&dc);
    bmp.CreateCompatibleBitmap(&dc, bmp_width, bmp_height);
    memDC.SelectObject(&bmp);
    //backgroundPen=CPen(PS_SOLID, 1, RGB(255, 69, 0));
    backgroundPen.CreatePen(PS_SOLID, 1, RGB(255, 69, 0));
    pOldBackgroundPen=memDC.SelectObject(&backgroundPen);
    //绘制背景
    draw_background();
    //
    memDC.SelectObject(pOldBackgroundPen);
    //贴图
    dc.BitBlt(0, 0, bmp_width, bmp_height, &memDC, 0, 0, SRCCOPY);
    bmp.GetBitmapBits(bmp_width*bmp_height*4, background);
    ReleaseDC(&dc);
    CStatic::OnPaint();
    return;
    } //贴图
    dc.BitBlt(0, 0, bmp_width, bmp_height, &memDC, 0, 0, SRCCOPY);
    //设置读取完毕事件
    ReleaseDC(&dc);
    CStatic::OnPaint();
    }
         其中mypic是CStatic的派生类;
         
          另外貌似GetClientDC是miniGUI的函数,这个也没用过,好像mfc也没有,见笑了。
          谢谢回复。
         
      

  14.   

    CPaintDC dc(this);取的是BeginPaint返回的DC。基本上你可以用 BeginPaint 来代替你的GetDC
      

  15.   

        我现在使用GetDIBits和SetDIBits,已经解决问题。
        谢谢各位回复。尤其感谢wangk。