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.
Okay. Here you go... :azn:
StretchBlt example: Another example that others might find useful...
Source code fully commented. :tongue:
include \masm32\include\masm32rt.inc
DlgProc proto :dword, :dword, :dword, :dword
cwidth equ 390 ; desired client area width
cheight equ 260 ; 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, 00DFDFDFh ; color = off white
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
; stretch blit resource bitmap
invoke StretchBlt, hDC, 10, 10, 240, 240, mDC, 0, 0, 120, 120, SRCCOPY
; normal bit blit resource bitmap
invoke BitBlt, hDC, 260, 10, 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 has been stretched using StretchBlt.
The image on the right is normal size using BitBlt.
(https://i.postimg.cc/G21H5Kdd/untitled.png)
:cool:
Slight change to the source code, also in the attachment.
Stretching a bitmap can also be done while using TransparentBlt. :smiley:
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 390 ; desired client area width
cheight equ 260 ; 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, 00FFBF7Fh ;; a nice light blue colr
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 00FFFFFFh
invoke TransparentBlt, hDC, 10, 10, 240, 240, mDC, 0, 0, 120, 120, 00FFFFFFh
; mormal blit resource bitmap
invoke BitBlt, hDC, 260, 10, 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 has been stretched using TransparentBlt, while also making the white part of the bitmap transparent.
The image on the right is normal size using BitBlt, and represents exactly what the bitmap actually looks like.
The bitmap used here, is slightly different than the one used in the first example in that this bitmap has no borders drawn on the actual bitmap, as the one posted above does.
(https://i.postimg.cc/90FS1P7f/untitled.png)
Slight change to the source code, also in the attachment.