如下的代码是一个ATL项目里的代码,本意是想通过Bitmap实现双缓冲,可是没有显示出任何东西,直接使用原来的di.hdcDraw就可以显示出来。经调试确信代码是执行了的,为什么? HRESULT OnDrawAdvanced(ATL_DRAWINFO& di)
{
RECT& rc = *(RECT*)di.prcBounds;
HDC memDc;
HBITMAP bitmap;
memDc=CreateCompatibleDC(di.hdcDraw);
if (memDc!=NULL)
{
bitmap=CreateCompatibleBitmap(di.hdcDraw,rc.right-rc.left,rc.bottom-rc.top);
SelectObject(memDc, &bitmap);
Ellipse(memDc, rc.left, rc.top, rc.right, rc.bottom);
SetTextAlign(memDc, TA_CENTER|TA_BASELINE);
LPCTSTR pszText = _T("测试");
#ifndef _WIN32_WCE
TextOut(memDc,
(rc.left + rc.right) / 2,
(rc.top + rc.bottom) / 2,
pszText,
lstrlen(pszText));
#else
ExtTextOut(memDc,
(rc.left + rc.right) / 2,
(rc.top + rc.bottom) / 2,
ETO_OPAQUE,
NULL,
pszText,
ATL::lstrlen(pszText),
NULL);
#endif
//__debugbreak();
//SelectStockFont(&memDc);
BOOL b=BitBlt(di.hdcDraw,  rc.left, rc.top, rc.right, rc.bottom,memDc,0,0,SRCCOPY);
DeleteObject(bitmap);
DeleteDC(memDc);
}
return S_OK;
}

解决方案 »

  1.   

    这里的宽度和高度似乎不对
    BitBlt(di.hdcDraw,  rc.left, rc.top, rc.right, rc.bottom,memDc,0,0,SRCCOPY);
    --》
    BitBlt(di.hdcDraw,  rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, memDc, 0, 0, SRCCOPY);
      

  2.   

    什么都不显示应该不至于吧
    是不是黑屏?
    Ellipse(memDc, rc.left, rc.top, rc.right, rc.bottom);之前填充一个底色试试
      

  3.   

    什么也不显示的意思是说使用双缓冲这一段代码就像没有执行一样,什么也没有显示,屏是白色的,不是黑的。如果是黑的可能倒好说了。我把memDc换成di.hdcDraw就显示出来了。按VisualEleven说的,也不行。
      

  4.   

    你在memDC的绘图都有问题,比如:Ellipse(memDc, rc.left, rc.top, rc.right, rc.bottom);
    这里应该用Ellipse(memDc, 0, 0, rc.right-rc.left, rc.bottom-rc.top);
    同样,TextOut(memDc,
                    (rc.left + rc.right) / 2,
                    (rc.top + rc.bottom) / 2,
                    pszText,
                    lstrlen(pszText));
    等都有问题。
    你要注意一个问题,rc.left和rc.top是相对di.hdcDraw而言的位置;与之对应,在memDc中,它的坐标应该是(0,0)
      

  5.   

    TextOut(memDc,
                    (rc.left + rc.right) / 2,
                    (rc.top + rc.bottom) / 2,
                    pszText,
                    lstrlen(pszText));
    应该是
    TextOut(memDc,
                    (rc.right-rc.left) / 2,
                    (rc.bottom-rc.top) / 2,
                    pszText,
                    lstrlen(pszText));
      

  6.   

     bitmap=CreateCompatibleBitmap(di.hdcDraw,rc.right-rc.left,rc.bottom-rc.top);
     SelectObject(memDc, &bitmap);
     Ellipse(memDc, rc.left, rc.top, rc.right, rc.bottom);改成
     Ellipse(memDc, 0, 0, rc.Width(), rc.Height());看看极端的例子,假设rc.left = 100, rc.top = 100,然而rc的宽度为50,高度为50,
    那么Ellipse(memDc, rc.left, rc.top, rc.right, rc.bottom);将画在了图片外面
    而Ellipse(memDc, 0, 0, rc.Width(), rc.Height());从0,0开始算起,应该就能画上去了
      

  7.   

    我确信不是坐标的问题,因为我无论把坐标怎样改,结果还是一样的,没有显示出来我建立的项目是ATL的Activex,里面的有绘图的代码,所以我想用双缓冲,以前的项目是用MFC写的,可以正常运行,现在换成ATL,怎么也出不来。好奇怪。
      

  8.   

    TO:lfs09
    是个好主意,不过好像Bitmap不太好保存成文件
      

  9.   

    HRESULT OnDrawAdvanced(ATL_DRAWINFO& di)
    {
    RECT& rc = *(RECT*)di.prcBounds;
    HDC memDc;
    HBITMAP bitmap;
    memDc=CreateCompatibleDC(di.hdcDraw);
    if (memDc!=NULL)
    {
    int nWidth = rc.right - rc.left();
    int nHeight = rc.bottom - rc.top;
    bitmap=CreateCompatibleBitmap(di.hdcDraw, nWidth, nHeight);
    HBITMAP hOldbmp = (HBITMAP)SelectObject(memDc, &bitmap);
    Ellipse(memDc, 0, 0, rc.right, rc.bottom); LPCTSTR pszText = _T("²âÊÔ"); DrawText(memDc, pszText, _tcslen(pszText), &rc, DT_CENTER|DT_VCENTER); BitBlt(di.hdcDraw,  0, 0, nWidth, nHeight, memDc, 0, 0, SRCCOPY);
    SelectObject(memDc, &hOldbmp);
    DeleteObject(bitmap);
    DeleteDC(memDc);
    }
    return S_OK;
     }
      

  10.   

    这样试一下,你的Ellipse显示的出来吗???
      

  11.   

    我本来是用VS2010来测试的,以为可能VS2010有问题。结果我在Vs2005上同样也建立了一个Atl项目,结果一样的不显示,你们可以测试一下: HRESULT OnDraw(ATL_DRAWINFO& di)
    {
    RECT& rc = *(RECT*)di.prcBounds;
    HDC memDc=CreateCompatibleDC(di.hdcDraw);
    if (memDc!=NULL)
    {
    HBITMAP bitmap=CreateCompatibleBitmap(memDc,rc.right-rc.left,rc.bottom-rc.top);
    SelectObject(memDc, &bitmap);
    Ellipse(memDc, 0, 0, rc.right-rc.left,rc.bottom-rc.top);
    SetTextAlign(memDc, TA_CENTER|TA_BASELINE);
    LPCTSTR pszText = _T("测试");
    ExtTextOut(memDc,
    (rc.right-rc.left) / 2,
    (rc.bottom-rc.top) / 2,
    ETO_OPAQUE,
    NULL,
    pszText,
    lstrlen(pszText),
    NULL);
    BOOL b=BitBlt(di.hdcDraw,  rc.left, rc.top, rc.right, rc.bottom,memDc,0,0,SRCCOPY);
    DeleteObject(bitmap);
    DeleteDC(memDc);
    }
    return S_OK;
    }
      

  12.   

    感觉这些函数有些乱,有的Rect是绝对坐标,好比(left, top, right, bottom),有的时候贴图是(left, top, width, height);绕着绕着就......
      

  13.   

    TO:happyparrot
     
    我现在的代码是这样的,还是不行,郁闷
    HRESULT OnDraw(ATL_DRAWINFO& di)
    {
    RECT& rc = *(RECT*)di.prcBounds;
    HDC memDc=CreateCompatibleDC(di.hdcDraw);
    if (memDc!=NULL)
    {
    HBITMAP bitmap=CreateCompatibleBitmap(memDc,rc.right-rc.left,rc.bottom-rc.top);
    SelectObject(memDc, &bitmap);
    Ellipse(memDc, 0, 0, rc.right-rc.left,rc.bottom-rc.top);
    SetTextAlign(memDc, TA_CENTER|TA_BASELINE);
    LPCTSTR pszText = _T("测试");
    TextOut(memDc,
    (rc.right-rc.left) / 2,
    (rc.bottom-rc.top) / 2,
    pszText,
    lstrlen(pszText));
    BOOL b=BitBlt(di.hdcDraw,  rc.left, rc.top, rc.right, rc.bottom,memDc,0,0,SRCCOPY);
    DeleteObject(bitmap);
    DeleteDC(memDc);
    }
    return S_OK;
    }补充:我用的是Window7,不会是这个问题吧。
      

  14.   

    1楼的提示你没有注意啊?BitBlt中你的宽和高的参数不正确。
      

  15.   

    这样应该合适了吧,一样不行:HRESULT OnDraw(ATL_DRAWINFO& di)
    {
    RECT& rc = *(RECT*)di.prcBounds;
    HDC memDc=CreateCompatibleDC(di.hdcDraw);
    if (memDc!=NULL)
    {
    HBITMAP bitmap=CreateCompatibleBitmap(memDc,rc.right-rc.left,rc.bottom-rc.top);
    SelectObject(memDc, &bitmap);
    Ellipse(memDc, 0, 0, rc.right-rc.left,rc.bottom-rc.top);
    SetTextAlign(memDc, TA_CENTER|TA_BASELINE);
    LPCTSTR pszText = _T("测试");
    TextOut(memDc,
    (rc.right-rc.left) / 2,
    (rc.bottom-rc.top) / 2,
    pszText,
    lstrlen(pszText));
    BOOL b=BitBlt(di.hdcDraw, rc.left, rc.top, rc.right-rc.left,rc.bottom-rc.top,memDc,0,0,SRCCOPY);
    DeleteObject(bitmap);
    DeleteDC(memDc);
    }
    return S_OK;
    }
    我觉得不是坐标的问题。
      

  16.   


    你的坐标很成问题,Maybe就是坐标的问题
      

  17.   

    说我坐标有问题的,
    我希望你们通过Atl项目测试通过后再给我说我哪里错了。
    对于坐标我试了几种写法了,都是不对的,我倒真希望是我的坐标不合适造成的,但结果都是不对的。不要再只靠自己想像回复了。
      

  18.   

    HRESULT OnDrawAdvanced(ATL_DRAWINFO& di)
    {
        RECT& rc = *(RECT*)di.prcBounds;
        HDC memDc;
        HBITMAP bitmap;
        memDc=CreateCompatibleDC(di.hdcDraw);
        if (memDc!=NULL)
        {
            int nWidth = rc.right - rc.left();
            int nHeight = rc.bottom - rc.top;
            bitmap=CreateCompatibleBitmap(memDc, nWidth, nHeight);
            ASSERT(bitmap);
            HBITMAP hOldbmp = (HBITMAP)SelectObject(memDc, &bitmap);
            Ellipse(memDc, 0, 0, rc.right, rc.bottom);        LPCTSTR pszText = _T("²âÊÔ");        DrawText(memDc, pszText, _tcslen(pszText), &rc, DT_CENTER|DT_VCENTER);        BitBlt(di.hdcDraw,  0, 0, nWidth, nHeight, memDc, 0, 0, SRCCOPY);
            SelectObject(memDc, &hOldbmp);
            DeleteObject(bitmap);
            DeleteDC(memDc);
        }
        return S_OK;
     }
    Sorry,这个地方写错了,你调试一下,看看的Rect,memDC,bitmap是否正确有效??Debug下看看值是不是正确的
      

  19.   

    bitmap=CreateCompatibleBitmap(di.hdcDraw,rc.right-rc.left,rc.bottom-rc.top);
     SelectObject(memDc, &bitmap);
    Ellipse(memDc, rc.left, rc.top, rc.right, rc.bottom);改成
     Ellipse(memDc, 0, 0, rc.Width(), rc.Height());看看极端的例子,假设rc.left = 100, rc.top = 100,然而rc的宽度为50,高度为50,
    那么Ellipse(memDc, rc.left, rc.top, rc.right, rc.bottom);将画在了图片外面
    而Ellipse(memDc, 0, 0, rc.Width(), rc.Height());从0,0开始算起,应该就能画上去了
      

  20.   

    调用就是 SaveBmpToFile(hBitmap,_T("c:\\1.bmp");
    //参数说明: hbmp :需保存的图象的句柄         path :保存路径
    void XXXX::SaveBmpTofile(HBITMAP hbmp, CString path)
    {
    //参数说明: hbmp :需保存的图象的句柄         path :保存路径//定义文件头结构 BITMAPFILEHEADER fileHead;                                              
    int fileHeadLen = sizeof( BITMAPFILEHEADER );//定义图象信息结构BITMAPINFOHEADER bmpHead;
    int bmpHeadLen =sizeof( BITMAPINFOHEADER );
    BITMAP bmpObj;
    GetObject( hbmp, sizeof(BITMAP), &bmpObj );DWORD fileSizeInByte;                //文件总的字节大小//获取系统颜色深度,即每个象素用多少位表还示
    DWORD PixelSizeInBit;               
    CDC srcDC;                        //系统屏幕设备描述表
      
    srcDC.CreateDC(_T("DISPLAY"), NULL, NULL, NULL);PixelSizeInBit=srcDC.GetDeviceCaps( BITSPIXEL ) * srcDC.GetDeviceCaps( PLANES );fileSizeInByte = fileHeadLen + bmpHeadLen + bmpObj.bmWidth*bmpObj.bmHeight*PixelSizeInBit/8;//初始化文件头结构
        fileHead.bfOffBits = fileHeadLen + bmpHeadLen;
    fileHead.bfReserved1=0;
    fileHead.bfReserved2=0;
    fileHead.bfSize = fileSizeInByte;
    fileHead.bfType = 0x4D42;///初始图像信息结构
    bmpHead.biBitCount = PixelSizeInBit;
    bmpHead.biCompression = BI_RGB;
    bmpHead.biPlanes = 1;
    bmpHead.biHeight = bmpObj.bmHeight;
    bmpHead.biWidth = bmpObj.bmWidth;
    bmpHead.biSize = bmpHeadLen;//为文件分配空间
    PBYTE pFile=new byte[ fileSizeInByte ];
    memset( pFile, 0, fileSizeInByte );//填充文件头部
    memcpy( pFile, (PBYTE)&fileHead, fileHeadLen);    //填充文件信息头部结构
    memcpy( pFile+fileHeadLen, (PBYTE)&bmpHead, bmpHeadLen);    //填充象素部分
    GetDIBits( srcDC.m_hDC, hbmp, 0, bmpObj.bmHeight, pFile+fileHeadLen+bmpHeadLen, (LPBITMAPINFO)(pFile+fileHeadLen), DIB_RGB_COLORS);
    //打开文件并写入数据
    HANDLE hFile;hFile=CreateFile( path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);if( hFile==INVALID_HANDLE_VALUE )
    {
            MessageBox(_T("创建文件失败"));
       return;
    }    DWORD nByteTransfered;WriteFile( hFile, pFile, fileSizeInByte, &nByteTransfered, NULL);CloseHandle( hFile );    //清理
    delete pFile;
    srcDC.DeleteDC();}
      

  21.   


    lz 给分吧,我应该给你找到原因了HBITMAP bitmap=CreateCompatibleBitmap(memDc,rc.right-rc.left,rc.bottom-rc.top);
     这句话,我也遇到过 你的bitmap创建的时候,使用的不是物理的dc,而是用的内存DC,这样画出来的只有黑白。我也遇到过这样的问题
    把你的memDc 换成你的物理DC,这里不能使用内存DC
      

  22.   

    真是不解,我把原来的MFC里的双缓冲代码改了下也就不可以了。原来是CBitmap,现在用的是HBITMAP,看来原因在这里了。不能直接使用HBITMAP?因为使用了Atl,不想再使用CBitmap这个类了,这个类应该是MFC的,那么应该怎么实现这个双缓冲呢?
      

  23.   

    HBitmap 也可以使用双缓冲啊???
    不用mfc的类库,用hdc,hbitmap 都可以噻,
      

  24.   

    IPicture 类 纯GDI的,你试试 可读 jpg png bmp
      

  25.   

    天啊,我错了,错的可怜。我竟然多写了一个&符号,改成这样就行了://SelectObject(memDc, &bitmap);
    SelectObject(memDc, bitmap);都是代码复制过来不细心造成的!不好意思,连这里的大侠们都惊动了!
    散分了!