简体   繁体   English

从分层窗口获取HBITMAP-错误的数据

[英]Getting HBITMAP from layered window - incorrect data

I created a layered window (with WS_EX_LAYERED), size of about 400X300 px. 我创建了一个分层窗口(使用WS_EX_LAYERED),大小约为400X300像素。
When drawing the window (using UpdateLayeredWindow ) everything works great. 绘制窗口时(使用UpdateLayeredWindow ),一切正常。

The problem is that I'm unable to get the HBITMAP of the window after drawing it. 问题是我在绘制窗口后无法获得该窗口的HBITMAP。 When trying to get the HBITMAP through the window's HDC, I get an empty (black) bitmap, the size of my entire desktop (1920X1080 px insted of 400X300 px). 当试图通过窗口的HDC获取HBITMAP时,我得到了一个空的(黑色)位图,即整个桌面的大小(1920X1080像素插入了400X300像素)。

Does anybody know if it is even possible to get the HDC\\HBITMAP of a layered window? 有谁知道是否有可能获得分层窗口的HDC \\ HBITMAP?

Code samples 代码样本

Here's the code of how I draw the layered window (again, works great): 这是我如何绘制分层窗口的代码(再次,效果很好):

void MyLayeredWindow::DrawLayered() const
{
    RECT rcWindow;
    GetWindowRect(rcWindow);

    int nWidth = abs(rcWindow.right - rcWindow.left);
    int nHeight = abs(rcWindow.bottom - rcWindow.top);

    // Create 32Bit bitmap to apply transparency 
    // (have to set negative height because if not the (0,0) point would be the bottom left instead of top left)
    VOID *ppvBits = NULL;
    BITMAPINFO BitmapInfo = {0};
    BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    BitmapInfo.bmiHeader.biWidth = nWidth;
    BitmapInfo.bmiHeader.biHeight = -nHeight;
    BitmapInfo.bmiHeader.biPlanes = 1;
    BitmapInfo.bmiHeader.biBitCount = 32;
    BitmapInfo.bmiHeader.biCompression = BI_RGB;

    // Copy view buffer to a temp DC and bitmap
    HDC hDcTemp = ::CreateCompatibleDC(NULL);
    assert(hDcTemp);
    HBITMAP hBitmapTemp = ::CreateDIBSection(hDcTemp, &BitmapInfo, DIB_RGB_COLORS, &ppvBits, NULL, 0);
    assert(hBitmapTemp && hBitmapTemp!=(HBITMAP)ERROR_INVALID_PARAMETER)
    ::SelectObject(hDcTemp, hBitmapTemp);

    // Darwing the window's conent here
    // ....
    // ....

    // Call UpdateLayeredWindow
    BLENDFUNCTION blend = {0};
    blend.BlendOp = AC_SRC_OVER;
    blend.SourceConstantAlpha = 190;
    blend.AlphaFormat = AC_SRC_ALPHA;

    SIZE sizeWnd = {0};
    sizeWnd.cx = nWidth;
    sizeWnd.cy = nHeight;
    POINT ptPos = {0};
    ptPos.x = rcWindow.left;
    ptPos.y = rcWindow.top;
    POINT ptSrc = {0,0};

    ::UpdateLayeredWindow(m_hWnd, NULL, &ptPos, &sizeWnd, hDcTemp, &ptSrc, 0, &blend, ULW_ALPHA);

    if(hDcTemp)
        ::DeleteDC(hDcTemp);

    if(hBitmapTemp)
        ::DeleteObject(hBitmapTemp);
}

Here's the code of how I capture the window's bitmap and save it to a file: ( NOTICE: It works of "normal" windows, such as the Calculator) 这是我捕获窗口位图并将其保存到文件的代码:( 注意:它适用于“普通”窗口,例如计算器)

bool MyLayeredWindow::SaveBitmapFile(__in const HWND& hWnd, __in const wstring& sFileName)
{
    HDC hDC = ::GetDC(hWnd);

    // get bitmap of DC
    HBITMAP hBmp = (HBITMAP)::GetCurrentObject( hDC, OBJ_BITMAP );

    // get info of bitmap
    BITMAPINFO stBmpInfo; 
    stBmpInfo.bmiHeader.biSize = sizeof( stBmpInfo.bmiHeader );
    stBmpInfo.bmiHeader.biBitCount = 0;
    GetDIBits( hDC, hBmp, 0, 0, NULL, &stBmpInfo, DIB_RGB_COLORS );

    // init info size
    ULONG iBmpInfoSize; 
    switch( stBmpInfo.bmiHeader.biBitCount )
    { 
    case 24:
        iBmpInfoSize = sizeof(BITMAPINFOHEADER); 
        break;
    case 16: 
    case 32:
        iBmpInfoSize = sizeof(BITMAPINFOHEADER)+sizeof(DWORD)*3; 
        break;
    default:
        iBmpInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * ( 1 << stBmpInfo.bmiHeader.biBitCount ); 
        break;
    } 

    // copy header
    PBITMAPINFO pstBmpInfo = NULL;
    if( iBmpInfoSize != sizeof(BITMAPINFOHEADER) ) 
    { 
        pstBmpInfo = (PBITMAPINFO)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, iBmpInfoSize );
        PBYTE pbtBmpInfoDest = (PBYTE)pstBmpInfo; 
        PBYTE pbtBmpInfoSrc = (PBYTE)&stBmpInfo; 
        ULONG iSizeTmp = sizeof( BITMAPINFOHEADER );

        while( iSizeTmp-- ) 
            *( ( pbtBmpInfoDest )++ ) = *( ( pbtBmpInfoSrc )++ ); 
    } 

    // create file
    HANDLE hFile = CreateFile( sFileName.c_str(), GENERIC_WRITE, 0 , NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL );

    // init bmp file header
    BITMAPFILEHEADER stBmpFileHder = {0}; 
    stBmpFileHder.bfType = 0x4D42; // 'BM' 
    stBmpFileHder.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + iBmpInfoSize + pstBmpInfo->bmiHeader.biSizeImage; 
    stBmpFileHder.bfReserved1 = 0;
    stBmpFileHder.bfReserved2 = 0; 
    stBmpFileHder.bfOffBits = sizeof(BITMAPFILEHEADER) + iBmpInfoSize; 

    // write header to file
    DWORD dRet;
    WriteFile( hFile, (LPCVOID)&stBmpFileHder, sizeof(BITMAPFILEHEADER), &dRet, NULL );

    // allocate size for rest of bmp (body)
    PBYTE pBits = (PBYTE)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, stBmpInfo.bmiHeader.biSizeImage );

    // get bmp bits
    HBITMAP hBmpOld; 
    HBITMAP hTmpBmp = CreateCompatibleBitmap( hDC, pstBmpInfo->bmiHeader.biWidth, pstBmpInfo->bmiHeader.biHeight );
    hBmpOld = (HBITMAP)SelectObject( hDC, hTmpBmp ); 
    GetDIBits( hDC, hBmp, 0, pstBmpInfo->bmiHeader.biHeight, (LPSTR)pBits, pstBmpInfo, DIB_RGB_COLORS );

    // write bmp info
    WriteFile( hFile, (LPCVOID)pstBmpInfo, iBmpInfoSize, &dRet, NULL );

    // write bmp bits
    WriteFile( hFile, (LPCVOID)pBits, pstBmpInfo->bmiHeader.biSizeImage, &dRet, NULL );

    // release handles and free memory
    SelectObject( hDC, hBmpOld ); 
    DeleteObject( hTmpBmp ); 
    CloseHandle( hFile ); 
    GlobalFree( pstBmpInfo ); 
    GlobalFree( pBits ); 
    ReleaseDC( hWnd, hDC );

    return true;
}

Thanks! 谢谢!

Since I didn't get any better answer, I simply called a "Draw" function that paints my layered window, onto a temporary HDC. 由于我没有得到更好的答案,因此我简单地调用了一个“绘制”功能,将我的分层窗口绘制到一个临时HDC上。

Meaning I don't copy existing bitmap, but create an identical one, using the same drawing function. 意思是我不复制现有的位图,而是使用相同的绘图功能创建相同的位图。

I'd still love to get a better answer for this question. 我仍然很乐意为这个问题寻求更好的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM