Natan
Natan

Reputation: 3

Can't draw a bitmap on a desktop using GDI

I wanted to make program that just draw a picture on a desktop using GDI, but it doesn't show anything. I checked if there's any error and it shown me error code 2. This is my code

BITMAP bitMap;
HBITMAP hBitmap = reinterpret_cast<HBITMAP>(LoadImageA(0, Globals::bmpPath.c_str(), IMAGE_BITMAP, 1536,864, LR_LOADFROMFILE));

HDC whdc = GetDC(NULL);
HDC hdcMem = CreateCompatibleDC(whdc);

SelectObject(hdcMem,hBitmap);
GetObject(reinterpret_cast<HGDIOBJ>(hBitmap), sizeof(bitMap), &bitMap);

BitBlt(whdc, 0, 0, 1536,864, hdcMem, 0, 0, SRCCOPY);
std::this_thread::sleep_for(std::chrono::milliseconds(200));

It's in while(true) btw.

Upvotes: 0

Views: 212

Answers (1)

armagedescu
armagedescu

Reputation: 2155

In your code BitBlt is supposed to transfer bits to hwdc, which is in fact a GetDC(NULL). You need there a real DC from a real window like myTargetDC=GetDC(hWnd). But better use WM_PAINT handler and use the de from BeginPaint instead of drawing it each 200 milliseconds, let the operation system to decide when to draw it.

Use following function to load an image and use where you want it:

HBITMAP loadImageFromFileW(wchar_t* fileName)
{
    char* buf = 0;
    HBITMAP btRet = 0;

    HANDLE hFile = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    DWORD dwFileSizeHigh;
    DWORD fileSize = GetFileSize( hFile, &dwFileSizeHigh );
    buf = (char*)HeapAlloc(GetProcessHeap(), 0, fileSize);
    DWORD read;
    ReadFile(hFile, buf, fileSize, &read, 0);
    
    CloseHandle(hFile);

    BITMAPFILEHEADER* bmpfh = (BITMAPFILEHEADER *)buf;
    BITMAPINFO* pbmInfo = (BITMAPINFO*)(buf + sizeof(BITMAPFILEHEADER));

    if(pbmInfo->bmiHeader.biCompression == BI_RGB)
    {
        HDC hdcSrc = CreateDCW(L"DISPLAY", 0, 0, 0);
        btRet = CreateDIBitmap(hdcSrc, &pbmInfo->bmiHeader, CBM_INIT, buf + bmpfh->bfOffBits, pbmInfo, DIB_RGB_COLORS);
        DeleteDC(hdcSrc);
    }

    HeapFree(GetProcessHeap(), 0, buf);

    return btRet;
}

Use it at once somewhere on initializing the progam:

    hBitmapBmpFile = loadImageFromFileW(L"yourbmp.bmp");

And use hBitmapBmpFile

    case WM_PAINT:
            PAINTSTRUCT ps;
            HDC hDC= BeginPaint(hWnd, &ps);

            {
                HDC hdcMem = CreateCompatibleDC(0);
                HGDIOBJ hbmOld = SelectObject(hdcMem, hBitmapBmpFile);
                BITMAP bm;
                GetObject(hBitmapBmpFile, sizeof(bm), &bm);
                BitBlt(hDC, 10, 190, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
                DeleteDC(hdcMem);
            }
            EndPaint(hWnd, &ps);
            break;

Upvotes: 1

Related Questions