C++ WIN32: Rescaling Bitmaps/Giving Bitmaps HDC's

3.5k views Asked by At

So i've been trying to rescale a bitmap without it printing the original and reprinting the rescaled image. I'm trying to use StretchBlt(), based on the MSDN Microsoft rescaling images function:

https://msdn.microsoft.com/en-us/library/windows/desktop/dd162950(v=vs.85).aspx

but that requires a secondary hdc tied to the Source, which stretching can't be done without printing the HBITMAP first. Is there a way to convert HBITMAP's into HDC's? I have been able to get HANDLE's out of HBITMAP's, which might provide a more direct route. The other thing i could do is create a resized bitmap in allocated memory (not saved) out of the standard bitmap and print that.

The standard way i print bitmaps is:

HBITMAP hBitmap;
static HANDLE hDIB = NULL;
CHAR szFileName[MAX_PATH] = "fileName.bmp";

hDIB = OpenDIB((LPSTR)szFileName);

hBitmap = BitmapFromDIB(hDIB, NULL);

DrawBitmap(hdc, x, y, hBitmap, SRCCOPY);

Another option i could try is to look into another means of displaying the bmp. I'm pretty new to win32, so I don't know any other means of accomplishing this task. Any insight into how i can rescale the BITMAP without printing it in the first place.

1

There are 1 answers

1
IInspectable On BEST ANSWER

The link you posted (Scaling an Image) already contains code, that renders a bitmap. All you need to do is replace the call to BitBlt with StretchBlt:

BOOL DrawBitmap (HDC hDC, INT x, INT y, INT width, INT height, HBITMAP hBitmap, DWORD dwROP)
{
    HDC       hDCBits;
    BITMAP    Bitmap;
    BOOL      bResult;

    if (!hDC || !hBitmap)
        return FALSE;

    hDCBits = CreateCompatibleDC(hDC);
    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
    SelectObject(hDCBits, hBitmap);
    // Replace with StretchBlt call
    //bResult = BitBlt(hDC, x, y, Bitmap.bmWidth, Bitmap.bmHeight, hDCBits, 0, 0, dwROP);
    bResult = StretchBlt(hDC, x, y, width, height,
                         hDCBits, 0, 0, Bitmap.bmWidth, Bitmap.bmHeight, dwROP);
    DeleteDC(hDCBits);

    return bResult;
}

You can call this from your WM_PAINT message handler, for example:

case WM_PAINT:
{
    PAINTSTRUCT ps = { 0 };
    HDC hDC = ::BeginPaint( hWnd, &ps );
    RECT rc = { 0 };
    ::GetClientRect( hWnd, &rc );
    DrawBitmap( hDC, 0, 0, rc.right, rc.bottom, hBitmap, SRCCOPY );
    ::EndPaint( hWnd, &ps );
}
break;