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?
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?
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
...