TransparentBlt example: Another example that others might find useful.
Source code fully commented. :tongue:
include \masm32\include\masm32rt.inc
include \masm32\include\msimg32.inc ; needed for TransparentBlt
includelib \masm32\lib\msimg32.lib ; needed for TransparentBlt
DlgProc proto :dword, :dword, :dword, :dword
cwidth equ 240 ; desired client area width
cheight equ 140 ; desired client area height
.data?
hBmp_red dd ? ; handle of bitmap loaded from resource
.code
start proc
local hInstance:dword
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke DialogBoxParam, hInstance, 100, 0, addr DlgProc, 0 ;; create dialog box, from resource dilalog
invoke ExitProcess, eax
start endp
DlgProc proc hWin:dword, uMsg:dword, wParam:dword, lParam:dword
local hDC:dword, ps:PAINTSTRUCT, rct:RECT, hBrush:dword, hBrush_old:dword
local mDC:dword, hBmp:dword, hBmp_old:dword, hPen:dword, hPen_old:dword
local x:dword, y:dword, wwid:dword, whgt:dword, cwid:dword, chgt:dword
.if uMsg == WM_INITDIALOG
;; resizing Client Area to exact dimensions, specified by cwidth and cheight
invoke GetWindowRect, hWin, addr rct ;; get window current dimensions.
mov eax, rct.right ;; obtain current window width by subtracting left boundary
sub eax, rct.left ;; from the right boundary
mov wwid, eax ;; store current window width
mov eax, rct.bottom ;; obtain current window height by subtracting top boundary
sub eax, rct.top ;; from the bottom boundary
mov whgt, eax ;; store current window height
invoke GetClientRect, hWin, addr rct ;; get client area current dimensions.
mov eax, rct.right ;; obtain current client width by subtracting left boundary
sub eax, rct.left ;; from the right boundary
mov cwid, eax ;; store current client area width
mov eax, rct.bottom ;; obtain current client height by subtracting top boundary
sub eax, rct.top ;; from the bottom boundary
mov chgt, eax ;; store client area height
;; calculate the difference between desired client area width and current client area width
mov eax, cwidth
sub eax, cwid
;; adjust the window width according to the difference calculated above
add wwid, eax
;; calculate the difference between desired client area height and current client area height
mov eax, cheight
sub eax, chgt
;; adjust the window height according to the difference calculated height
add whgt, eax
;; center the main window
;; obtain client area of the desktop, not including the task bar
invoke SystemParametersInfoA, SPI_GETWORKAREA, 0, addr rct, 0
;; center window width
mov eax, rct.right
sub eax, wwid
sar eax, 1
mov x, eax
;; center window height
mov eax, rct.bottom
sub eax, whgt
sar eax, 1
mov y, eax
;; implement the centering of the resized main window
invoke MoveWindow, hWin, x, y, wwid, whgt, TRUE
invoke GetModuleHandle, 0
invoke LoadBitmap, eax, 100 ; load bitmap from resource
mov hBmp_red, eax
.elseif uMsg == WM_PAINT
invoke BeginPaint, hWin, addr ps
mov hDC, eax ; window client area DC
;; get client area rectangle
invoke GetClientRect, hWin, addr rct ; client rectangle of dialog box
invoke CreateCompatibleDC, hDC
mov mDC, eax ; memory DC
invoke CreateCompatibleBitmap, hDC, rct.right, rct.bottom
mov hBmp, eax ; compatible bitmap handle
invoke SelectObject, mDC, hBmp
mov hBmp_old, eax
;; ###########################################################
;; Here I change the background color of the main window
invoke CreateSolidBrush, 0000FFFFh ; color yellow
mov hBrush, eax ;; save the brush handle
;; fill the client area rectangle with chosen color
invoke FillRect, mDC, addr rct, hBrush ; fill rectangle in memory DC
;; delete the brush, as it is no longer needed
invoke DeleteObject, hBrush
invoke SelectObject, mDC, hBmp ; select memory bitmap object
mov hBmp_old, eax
invoke BitBlt, hDC, 0, 0, rct.right, rct.bottom, mDC, 0, 0, SRCCOPY
;; ###########################################################
invoke SelectObject, mDC, hBmp_red ; select resource bitmap object
; transparent blit, exclude color 0000FF00h
invoke TransparentBlt, hDC, 0, 0, 120, 120, mDC, 0, 0, 120, 120, 0000FF00h
; mormal blit resource bitmap
invoke BitBlt, hDC, 120, 0, 120, 120, mDC, 0, 0, SRCCOPY
;; ###########################################################
invoke SelectObject, mDC, hBmp_old
invoke DeleteObject, hBmp ; delete DC bitmap object
invoke DeleteDC, mDC ; delete memory DC
invoke EndPaint, hWin, addr ps
.elseif uMsg == WM_CLOSE
invoke DeleteObject, hBmp_red ; delete resource bitmap object
invoke EndDialog, hWin, 0 ; clode dialog box
.endif
xor eax, eax
ret
DlgProc endp
end
The image on the left uses TranparentBlt to draw the bitmap. Color for transparent parts (color to not copy) is 0000FF00h.
The image on the right used BitBlt to draw the bitmap, and represents what the actual bitmap looks like.
(https://i.postimg.cc/MGgWFCFM/untitled.png)
:smiley:
Slight change to the source code, also in the attachment.
Yes, TransparentBlt() is an excellent tool to have in one's toolbox.
The one limitation I found with it is that (if I remember correctly) you can't resize the image between the source and destination DCs as you can with BitBlt(); the destination has to be the same size as the source. (Maybe someone can confirm or deny this.)
Hey, Zedd, maybe next you might want to try StretchBlt() to round out your GDI methods.
Quote from: NoCforMe on March 09, 2025, 07:28:03 AM(if I remember correctly) you can't resize the image between the source and destination DCs as you can with BitBlt()
Like this: :biggrin:
(https://i.postimg.cc/0jBwQk5k/untitled.png)
TransparentBlt with stretching!! :cool:
; transparent blit, exclude color 0000FF00h
invoke TransparentBlt, hDC, 0, 0, 240, 240, mDC, 0, 0, 120, 120, 0000FF00h
I had seen your comment about not able to stretch while using TransparentBlt, btw. I almost posted there today, while checking if an example was already posted somewhere on the forum for how to use TransparentBlt - before posting mine.
Found it. Again:
Quote from: NoCforMe on December 09, 2023, 07:44:47 AMAnd stretching does not work. Don't believe me? Try it.
That might have had something to do with your custom pallete?.
Quote from: NoCforMe on March 09, 2025, 07:28:03 AMHey, Zedd, maybe next you might want to try StretchBlt() to round out your GDI methods.
I generally don't like the appearance of stretched images. It is bad enough that some have to look blocky because of reducing the # of colors used. Stretching amplifies the blockiness. If I could "stretch B.L.T." that would be alright. :biggrin:
If you want to get a particular client size try using AdjustWindowRect (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-adjustwindowrect).
Quote from: sinsi on March 09, 2025, 07:56:24 AMIf you want to get a particular client size try using AdjustWindowRect (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-adjustwindowrect).
No, thats too easy. :biggrin: Actually I did not know about that api (or if I did, I don't remember it), thanks sinsi. Maybe next time, my solution also works perfectly, and is a lot better than my old one.
Quote from: zedd151 on March 09, 2025, 07:33:03 AMQuote from: NoCforMe on March 09, 2025, 07:28:03 AM(if I remember correctly) you can't resize the image between the source and destination DCs as you can with BitBlt()
Like this: :biggrin:
(https://i.postimg.cc/0jBwQk5k/untitled.png)
TransparentBlt with stretching!! :cool:
; transparent blit, exclude color 0000FF00h
invoke TransparentBlt, hDC, 0, 0, 240, 240, mDC, 0, 0, 120, 120, 0000FF00h
I had seen your comment about not able to stretch while using TransparentBlt, btw. I almost posted there today, while checking if an example was already posted somewhere on the forum for how to use TransparentBlt - before posting mine.
Found it. Again:
Quote from: NoCforMe on December 09, 2023, 07:44:47 AMAnd stretching does not work. Don't believe me? Try it.
That might have had something to do with your custom pallete?.
So apparently you were able to resize the image using
TransparentBlt(), yes?
Happy to be proven wrong here. But it'd be nice to know why I couldn't get it to work. (Believe me, I tried.)
I don't think it would have been on account of my custom palette: Windows doesn't really care what's in that data. However, it could have been because I was using a paletted image in the first place, instead of a non-paletted image (like anything higher than 8BPP).
What is the bit depth of your images? Are they 24-bit images? That might explain it.
4 bit, Indexed 16 colors... converted with GIMP.
Attach here a bitmap that you could not stretch using TransparentBlt, even if you have to screenshot it from your program or otherwise render it. Is it A custom made bitmap, using your routines?
Side note: when saving indexed .bmp's with GIMP, I have to check "do not save color space information" for it to be compatible with gdi api's. (At least I had not found a way for them to work without doing so).
I would like to open your bitmap with GIMP, to try a few tricks. Maybe I could find a solution for your particular issue. If I recall correctly, GIMP lets you rearrange the color table (or colormap?).
Not sure though, if it affects the color placement in the bitmap itself. Experimentation would prolly be necessary.
OK, give me a little time to resurrect that project ...
Yes, custom-made bitmap created by code.
Quote from: NoCforMe on March 09, 2025, 07:28:03 AMThe one limitation I found with it is that (if I remember correctly) you can't resize the image between the source and destination DCs as you can with BitBlt(); the destination has to be the same size as the source. (Maybe someone can confirm or deny this.)
Denied!
From the Microsoft page TransparentBlt (https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-transparentblt)
QuoteIf the source and destination rectangles are not the same size, the source bitmap is stretched to match the destination rectangle.
Quote from: zedd151 on March 09, 2025, 08:36:25 AMIf I recall correctly, GIMP lets you rearrange the color table (or colormap?).
Not sure though, if it affects the color placement in the bitmap itself. Experimentation would prolly be necessary.
(https://i.postimg.cc/Dzf4qjj4/colormap.png)
Rearranging the colormap with GIMP does
not alter the appearance of the bitmap in any way. :biggrin:
I just checked and verified. It changes the colormap as you request, and adjusts the values in the bitmap data according to the changes to the colormap indexing. :thup:
The GIMP is a great tool, you should try it.
Quote from: NoCforMe on March 09, 2025, 07:28:03 AM(Maybe someone can confirm or deny this.)
Quote from: sinsi on March 09, 2025, 09:15:33 AMDenied!
Ouch! Yes he knows what Microsoft 'says', but he was having trouble with a certain bitmap, which I *think* I can help with.
quote from the thread where NoCforMe was having issues stretching a bitmap while using TransparentBlt...
Quote from: NoCforMe on December 09, 2023, 07:44:47 AMThe point is that TransparentBlt() only works if the transparent color is the first one in the palette. This is not mentioned at all in the Micro$oft documentation.
I think this is not true at all. YOU specify the exact color for the transparent parts, as one of TransparentBlt's arguments. Something else is amiss with your home grown bitmap. I propose opening your rendered bitmap with GIMP, saving it in whatever bit depth you need, then you can compare the bitmap data to see how much it might differ from yours...
Better still, if you wanted 4 bit color depth, examine this one
(attached), created with GIMP - with "do not write color space information" checked under "Compatibilty Options" upon exporting (saving) ...
According to someone on Stack Overflow, black is not supported as a transparent colour.
Maybe that's the problem?
Quote from: sinsi on March 09, 2025, 09:39:45 AMAccording to someone on Stack Overflow, black is not supported as a transparent colour.
Maybe that's the problem?
Yes, I had seen that also during my research. Hey, NoC??? were you using black as transparent??
My money says yes. Don't ask me why I say this... :rofl: Then again, it
is a homebrew bitmap made in code not from a .bmp file, so we have to wait and see...
But yes passing colorref for black 00000000h as the transparent colour, would be passing a NULL. Makes sense, actually. Most likely it needs a non-zero value there.
Whoa, whoa; before we get totally corn-fused here:
I had no problems at all with transparency with TransparentBlt(); I was able to use any color, including black, as the transparent color.
What I had problems with was being able to resize the bitmap using that function (despite what Micro$oft claimed in their documentation). Which may or may not be a consequence of the bitmap I was generating programmatically.
I'll try to extract a .bmp from my code that you can experiment with.
Quote from: NoCforMe on March 09, 2025, 10:59:47 AMWhoa, whoa; before we get totally corn-fused here:
I had no problems at all with transparency with TransparentBlt(); I was able to use any color, including black, as the transparent color.
:biggrin: okay.
QuoteWhat I had problems with was being able to resize the bitmap using that function (despite what Micro$oft claimed in their documentation). Which may or may not be a consequence of the bitmap I was generating programmatically.
I'll try to extract a .bmp from my code that you can experiment with.
okay... :biggrin:
Once you have a *.bmp file, try it yourself first. Maybe it will work after loading it with LoadBitmap... it's worth a try.
But I'm here if you still need me to try something else.
QuoteThe GIMP is a great tool, you should try it.
Agreed :smiley: :thumbsup:
Ackshooly, I prefer my old, old copy of Paint Shop Pro (v 7.00). Does everything one would want done to bitmap images easily. Resizing, changing # of colors, adjusting colors, etc.
Quote from: NoCforMe on March 09, 2025, 11:46:06 AMAckshooly, I prefer my old, old copy of Paint Shop Pro (v 7.00). Does everything one would want done to bitmap images easily. Resizing, changing # of colors, adjusting colors, etc.
Sure,... but it isn't Free, GIMP IS, so is realistically, pretty Damn excellent value, to say the least :wink2:
Quote from: stoo23 on March 09, 2025, 12:44:56 PMSure,... but it isn't Free, GIMP IS, so is realistically, pretty Damn excellent value, to say the least :wink2:
It is rather heavy though, the installer weighs in at 330 MB. The Gimp2 folder in Program Files. Weighs in at 1.16 GB. :dazzled: But yes, I really like some of its features.
I also have and use Photoshop CS2 (Which has some features too that I really like, that GIMP does not.) Which, when purchased was very very expen$ive, but I had a goood paying job when I bought it back in 2006. And it too, is no lightweight. installer weighs 340 MB, with the folder in Pgram Files (x86) weighing in just over that at 356 MB. Not bad compared with gimp.
[rant]
Now, adobe and other major software vendors, is all about 'cloud computing'. I don't even know if they still use real software that actually and fully resides on a users computer. And the cost for photoshop these days??? Forget it, prolly through the roof.[/rant]
But yes, I like GIMP for some of its features that I don't think Photoshop has, or at least I haven't found em.
And usage of either of those compared to the other, Is like Chinese versus Hungarian. No offense intended to either of those populations or countries.
:biggrin: :biggrin: :badgrin: :cool:
Quote from: NoCforMe on March 09, 2025, 10:59:47 AMI'll try to extract a .bmp from my code that you can experiment with.
Any progress with that?
The continuing discussion of using AdjustWindowRect with a dialog box can be found Here (https://masm32.com/board/index.php?msg=137112)