News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Bitmap on Static Control

Started by y-code, April 24, 2006, 01:38:55 PM

Previous topic - Next topic

y-code

Havin no luck with resizing a bitmap, despite combining code/advice from both Donkey and Iczelion.

Have a static image control on a DialogBoxParam main window, a bitmap in the resource. If I set the bitmap as the source for the image control in the dialog, the app loads it fine. BUT of course the image control gets resized for different peoples' window resolution, so while it looks OK on my system, the bitmap is too big for the control on others.

So I need to resize it when the dialog box inits. If I was only coding for XP there's a flag to force that automatically when the bitmap loads from resource, but that doesn't work otherwise. Here's the code I have, a mix as said of me/Donkey/Iczelion:

.data
        LogoIMGhWnd DWORD ?  ; globals to save pointers
        hLogo DWORD ?
...

InitControls    proc
    LOCAL IMGbitmap:BITMAP, IMGrect:RECT, memDC1:DWORD, hBitmapNew:DWORD
...
; EBX set to dialog hWnd
        invoke  GetDlgItem, ebx, LogoIMG  ; LogoIMG = resource ID for image control
        lea     ecx, IMGrect
        mov     LogoIMGhWnd, eax
        invoke  GetWindowRect, eax, ecx  ; save size of control
...
        invoke  LoadBitmap, hInstance, Logo  ; Logo = resource ID for bitmap
        lea     ecx, IMGbitmap
        mov     edi, LogoIMGhWnd
        mov     hLogo, eax
        invoke  GetObject, eax, (SIZEOF BITMAP), ecx ; get original bitmap params

        invoke  GetDC, edi                      ; should get valid DC for logo box
        mov     esi, eax                        ; ESI = DC for logo image box
        invoke  CreateCompatibleDC, esi
        mov     memDC1, eax                     ; save temp DC for original bitmap
        invoke  SelectObject, eax, hLogo        ; old bitmap in temp DC
        invoke  CreateCompatibleDC, esi
        mov     ebx, eax                        ; temp DC for resized bitmap
        invoke  ReleaseDC, edi, esi   ; don't need original DC now
        invoke  SetStretchBltMode, ebx, COLORONCOLOR ; need color information!

        invoke  GetSystemMetrics, SM_CXEDGE
        mov     edi, IMGrect.right
        mov     esi, IMGrect.bottom
        add     eax, eax                        ; width of borders
        sub     edi, IMGrect.left               ; EDI = width of IMG control
        sub     esi, IMGrect.top                ; ESI = height of IMG control
        sub     edi, eax
        sub     esi, eax
        invoke  CreateCompatibleBitmap, ebx, edi, esi ; make correct-sized bitmap
        mov     hBitmapNew, eax                 ; save handle for later
        invoke  SelectObject, ebx, eax          ; new bitmap in temp DC

        mov     ecx, IMGbitmap.bmWidth          ; ECX = width of old bitmap
        mov     edx, IMGbitmap.bmHeight         ; EDX = height of old bitmap
        mov     eax, memDC1
        invoke  StretchBlt, ebx, 0, 0, edi, esi, eax, 0, 0, ecx, edx, SRCCOPY
        ; should create copy in new bitmap, stretched to fit, with all color information
        mov     esi, hBitmapNew                 ; get new bitmap handle
        mov     edi, memDC1
        invoke  SendMessage, LogoIMGhWnd, STM_SETIMAGE, IMAGE_BITMAP, esi
        invoke  DeleteDC, edi                   ; don't need the old bitmap any more
        invoke  DeleteDC, ebx
        invoke  DeleteObject, hLogo
        mov     hLogo, esi                      ; replace handle with new


Problem is this doesn't quite work. In the image box I now get a resized bitmap, so it's almost working, but it's like a mask - where there was a white background in the original logo it now shows through the grey of the dialog box surface, and where there was any colour I get a black pixel. I thought using SRCCOPY was supposed to copy the original without any alteration? I am stumped, and the SDK is leading me round and round in circles with no solution. Any ideas?

y-code

#1
Just to add, I tried changing the COLORONCOLOR parameter fr the SetStretchBltMode call to HALFTONE, which I know won't work non-NT, and that gave an OK bitmap but totally monochrome, no white background just see-through to the dialog surface, and a grey logo where there should have been colour. So why is the colour info getting stripped out?

y-code

OK, found the answer finally in the SDK. It's the CreateCompatibleBitmap function that was screwing it.

QuoteNote: When a memory device context is created, it initially has a 1-by-1 monochrome bitmap selected into it. If this memory device context is used in CreateCompatibleBitmap, the bitmap that is created is a monochrome bitmap. To create a color bitmap, use the hDC that was used to create the memory device context, as shown in the following code:

    HDC memDC = CreateCompatibleDC ( hDC );
    HBITMAP memBM = CreateCompatibleBitmap ( hDC, nWidth, nHeight );
    SelectObject ( memDC, memBM );

So my code works perfectly with the following alterations - note you need to release the original winDC AFTER selecting the correct sized bitmap into the new temp DC:

InitMainControls    proc
    LOCAL IMGbitmap:BITMAP, IMGrect:RECT, winDC:DWORD, memDC1:DWORD, hBitmapNew:DWORD
; need extra local here to store original winDC

...

        invoke  GetDC, NULL
        mov     esi, eax                        ; ESI = DC for screen
        invoke  CreateCompatibleDC, esi
        mov     memDC1, eax
        invoke  SelectObject, eax, hLogo        ; old bitmap in temp DC
        invoke  CreateCompatibleDC, esi
        mov     ebx, eax
        invoke  SetStretchBltMode, ebx, COLORONCOLOR

        invoke  GetSystemMetrics, SM_CXEDGE
        mov     winDC, esi                      ; save through 2 API calls
        mov     edi, IMGrect.right
        mov     esi, IMGrect.bottom
        add     eax, eax                        ; width of borders
        sub     edi, IMGrect.left               ; EDI = width of IMG control
        sub     esi, IMGrect.top                ; ESI = height of IMG control
        sub     edi, eax
        sub     esi, eax
        invoke  CreateCompatibleBitmap, winDC, edi, esi ; use original window DC here
        mov     hBitmapNew, eax
        invoke  SelectObject, ebx, eax          ; new bitmap in logo box DC
        invoke  ReleaseDC, NULL, winDC          ; can release original DC now
...