2012-11-26 2 views
2

크기가 약 400X300 픽셀 인 계층화 된 창 (WS_EX_LAYERED 포함)을 만들었습니다.
UpdateLayeredWindow을 사용하여 창을 그릴 때 모든 것이 효과적입니다.계층화 된 창에서 HBITMAP 가져 오기 - 잘못된 데이터

문제는 드로잉 후 창 HBITMAP을 가져올 수 없다는 것입니다. 창 HDC를 통해 HBITMAP을 가져 오려고하면 전체 바탕 화면 크기 (1920X1080 px insted of 400X300 px) 인 빈 (검은 색) 비트 맵이 나타납니다.

계층화 된 창의 HDC \ HBITMAP을 가져 오는 것이 가능한지 아무도 알지 못합니까?

코드 샘플

여기에 내가 계층화 된 창을 그리는 방법에 대한 코드입니다 (다시는, 잘 작동) : 여기

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); 
} 

내가 윈도우의 비트 맵을 캡처에 저장하는 방법의 코드입니다 파일 : ( 주의 사항 :이 같은 계산기와 같은 "정상"창, 작품)

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; 
} 

감사합니다.

+0

접근 방법은 일반적으로 잘못되어 우연히 만 작동 할 수 있습니다. 윈도우에 비트 맵이 없으면 BitBlt 또는 PrintWindow를 사용해야합니다. 계층화 된 창에 CAPTURE_BLT 옵션을 사용하십시오. http://msdn.microsoft.com/en-us/library/windows/desktop/dd183402%28v=vs.85%29.aspx –

+0

BitBlt 및 PrintWindow가 내 계층화 된 창에 적용되지 않는 것 같습니다. 빈 (검은 색/투명) DC를 반환합니다. –

답변

0

나는 더 좋은 대답을 얻지 못했기 때문에 임시로 HDC에 레이어 된 창을 그릴 수있는 "그리기"기능을 호출했습니다.

의미 기존의 비트 맵을 복사하지 않지만 동일한 드로잉 기능을 사용하여 동일한 비트 맵을 만듭니다.

나는이 질문에 대해 더 나은 대답을 얻고 싶습니다.

관련 문제