when i use gdi32 api function,such as StretchBlt 、BitBlt
invoke StretchBlt,wParam,0,0,rect.right,rect.bottom,hdcSrc,0,0,sbmp.bmWidth,sbmp.bmHeight,SRCCOPY
then the debugger date
0012FA2C 2501084F |hDestDC = 2501084F
0012FA30 00000000 |XDest = 0x0
0012FA34 00000000 |YDest = 0x0
0012FA38 00000123 |WidthDest = 123 (291.)
0012FA3C 000000AC |HeightDest = AC (172.)
0012FA40 000405DE |hSrcDC = 000405DE (window)
0012FA44 00000000 |XSrc = 0x0
0012FA48 00000000 |YSrc = 0x0
0012FA4C 2501084F |WidthSrc = 2501084F (620824655.)
0012FA50 0012FABC |HeightSrc = 12FABC (1243836.)
0012FA54 00CC0020 \ROP = SRCCOPY
;and the type of sbmp is BITMAP
0012FC68 0000011C ->sbmp.bmWidth
0012FC6C 00000115 ->sbmp.bmHeight
0012FC70 00000470
0012FC74 00200001
0012FC78 00000000
i'm not sure i understand the question, but....
0012FA4C 2501084F |WidthSrc = 2501084F (620824655.)
0012FA50 0012FABC |HeightSrc = 12FABC (1243836.)
those are unrealistic dimensions
we can't see the rest of the code, so it's hard to say why :P
thx ,this is just a simple project,print the bmp to the client rect
this is the code
test.asm
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
include test.inc
.code
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke InitCommonControls
invoke DialogBoxParam,hInstance,IDD_MAIN,NULL,addr DlgProc,NULL
invoke ExitProcess,0
;########################################################################
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL hdc:HDC
LOCAL hdcSrc:HDC
LOCAL PicH:DWORD
LOCAL PicW:DWORD
LOCAL rect:RECT
LOCAL hRgn:HRGN
LOCAL hbitmap:HBITMAP
LOCAL sbmp:BITMAP
LOCAL hpaint:PAINTSTRUCT
mov eax,uMsg
.if eax==WM_INITDIALOG
invoke GetWindowLong,hWin, GWL_STYLE
or eax,WS_SIZEBOX
invoke SetWindowLong,hWin,GWL_STYLE,eax
invoke LoadBitmap,hInstance,logo
mov hbitmap,eax
invoke GetDC,hWin
mov hdc,eax
invoke CreateCompatibleDC,hdc
mov hdcSrc,eax
invoke SelectObject,hdcSrc, hbitmap
invoke ReleaseDC,hWin,hdc
invoke RtlZeroMemory,addr sbmp,sizeof sbmp
invoke GetObject,hbitmap,sizeof sbmp,addr sbmp
;initialization here
.elseif eax==WM_CTLCOLORDLG
invoke RtlZeroMemory,addr rect,sizeof rect
invoke GetClientRect,hWin,addr rect
invoke SetStretchBltMode,wParam,COLORONCOLOR
invoke StretchBlt,wParam,0,0,rect.right,rect.bottom,hdcSrc,0,0,sbmp.bmWidth,sbmp.bmHeight,SRCCOPY
invoke GetStockObject,NULL_BRUSH
.elseif eax==WM_SIZE
invoke InvalidateRect,hWin,NULL,TRUE
.elseif eax==WM_COMMAND
mov edx,wParam
movzx eax,dx
shr edx,16
.if edx==BN_CLICKED
.if eax==IDOK
.elseif eax==IDCANCEL
invoke SendMessage,hWin,WM_CLOSE,NULL,NULL
.endif
.endif
.elseif eax==WM_CLOSE
invoke DeleteDC,hdcSrc
invoke EndDialog,hWin,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
end start
test.ini
include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
include gdi32.inc
includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib
includelib gdi32.lib
DlgProc PROTO :HWND,:UINT,:WPARAM,:LPARAM
.const
IDD_MAIN equ 101
logo equ 100
;#########################################################################
.data?
hInstance dd ?
;#########################################################################
the rest file just Resources
after you have loaded the bitmap resource, you will have an HBITMAP object handle
you can pass that handle to GetObject to get the bitmap dimensions
i use this function for that
;***********************************************************************************************
GetBitmapSize PROC hbmpBitmap:HBITMAP,lpSize:LPVOID
;returns X and Y dimensions of a bitmap in EAX and ECX
;will optionally fill a SIZE structure with the same values
;if the lpSize pointer is NULL, no structure is filled
;------------------------------
LOCAL bms :BITMAP
;------------------------------
xor eax,eax
mov bms.bmWidth,eax
mov bms.bmHeight,eax
INVOKE GetObject,hbmpBitmap,sizeof BITMAP,addr bms
mov edx,lpSize
mov ecx,bms.bmWidth
mov eax,bms.bmHeight
.if edx
mov [edx]._SIZE.x,ecx
mov [edx]._SIZE.y,eax
.endif
ret
GetBitmapSize ENDP
;***********************************************************************************************
to use it, you would place a PROTOtype near the beginning of the program (usually, just after the INCLUDE's)
GetBitmapSize PROTO :HBITMAP,:LPVOID
then, to use the routine.....
INVOKE GetBitmapSize,hBmp,NULL
;EAX = Y dimension
;ECX = X dimension
as a side note:
opening a ".const" section is not required for EQUates
optionally, if you want to use a global _SIZE structure...
.DATA?
BmpSize _SIZE <>
.CODE
INVOKE GetBitmapSize,hBmp,offset BmpSize
;EAX = BmpSize.y = Y dimension
;ECX = BmpSize.x = X dimension
thx your help,my poor english,now i really know why my code do not work normal
Just because a local variable
LOCAL sbmp:BITMAP
if define this variable as a global variable
.data?
sbmp BITMAP<>
my code will work well,but the real problem appeared,Why won't show my bitmap in the client area and if I use C language to write the same code can display bitmap
well, in the WM_INITDIALOG code, i see where you select the bitmap into a compatible DC
however, i don't see the code for WM_PAINT - i don't see where it is ever copied into the dialog hDC
also - i don't see the resource file
it might help if you would ZIP and attach the complete project
that having been said, i rarely use a dialog window when painting or drawing
i might use a dialog if it just has controls (buttons, edit boxes, icons, text, etc)
but, when i want to draw/paint, i generally use a regular window with WndProc and a message loop
so - i have little experience with painting in a dialog
i guess it could work, though - lol
ohhh - now i see the code in WM_CTLCOLORDLG :biggrin:
never saw that before - lol
that message is generally used for a solid color
i don't think painting it will work
If an application processes this message, it must return a handle to a brush.
The system uses the brush to paint the background of the dialog box.
what you can imply from that is that after the WM_CTLCOLORDLG message returns to the system,
the HBRUSH returned in EAX is used to paint the dialog background
so, whatever you painted gets covered up
maybe that's not how it works
you said you have a working C version :redface:
ok - you use a NULL brush - hmmm interesting approach
tomorrow, i'll make a RC file and play with it a bit
i see a couple little things....
you should save and restore the orginal HBITMAP selection in the memory DC
(when SelectObject returns, save EAX - then, in WM_CLOSE, select that back into the DC before deleting it)
no need to zero the RECT structure before GetClientRect
ok - got my curiosity up, so i had to play with it tonight :lol:
i made the following changes:
1) created RC file
2) global hdcSrc variable and sbmp structure
3) include file path's and masm32rt.inc
i don't use KetilO's RadAsm, so we need paths to make things work
also - i used \masm32\include\masm32rt.inc to handle the preface (.386, model, option, inc's and lib's)
you can have a look inside that file to see what it does
4) DlgProc return values
i modified the way DlgProc handles return values
generally, a dialog proc should return 0 - there are a few exceptions
one exception to this rule is WM_CTLCOLORxxx
it must return an HBRUSH
you can look at the code and see what i added and commented out
5) added hbrNull global variable
got the stock NULL_BRUSH in WM_INITDIALOG and stored it
then, return the global in EAX for WM_CTLCOLORDLG
6) added code to save and restore the original memory DC HBITMAP, as previously mentioned
you only need to download Test.zip
test.png.zip is the picture you see...
EDIT: attachment updated (Test2.zip)
corrected DialogProc return values
added manifest
Thank you very much,I'm just start learning assembly,from your answer I understand the difference between global and local variables,and how to return a value in the assembly
Thank you again for give directions
I don't have enough permissions to upload attachments,Today I also modified successfully, will no longer show oneself up
In fact,it's my stupid bug
thx man
well - i never saw your RC file
but, DialogBoxParam creates a modal dialog
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645465%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms645465%28v=vs.85%29.aspx)
that page links you to DialogProc...
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645469%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms645469%28v=vs.85%29.aspx)
as you can see, i got the return value incorrect :lol:
so - you want to read that page and modify your program accorfdingly
i am not used to using dialog boxes :P
i almost always use CreateWindowEx
the important thing is to allow each message type to return values seperately :t
thx again,in fact rc file is not so important,
today i read your code again found that our code is similar, just the function GetStockObject's position is different,
Through your answer and I learned a lot of things,thank you very much
i modified the attachment, above
corrected DialogProc return values
added manifest
What is the use for add manifest ,it looks no difference ,now I still have a problem .elseif eax==WM_CTLCOLORDLG
invoke GetClientRect,hWin,addr rect
invoke SetStretchBltMode,wParam,COLORONCOLOR
invoke StretchBlt,wParam,0,0,rect.right,rect.bottom,hdcSrc,0,0,sbmp.bmWidth,sbmp.bmHeight,SRCCOPY
mov eax,hBitmapBrush
ret ;if not add ret,the picture does not show
and radasm progect thx bro
the manifest file is primarily for common controls
under XP, you can add a manifest and call InitCommonControlsEx to get later version buttons, etc
but - adding a manifest and a version control block also help prevent AV false positives :P
i generally add them to all my projects
the value returned in EAX is critical
your code design should allow for different messages to return different values
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645469%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms645469%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645417%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms645417%28v=vs.85%29.aspx)
what happens is - if you return some value other than a null brush handle, windows thinks it's a brush (or an indication to use the default brush) and draws a background on top of the image you just painted :biggrin:
mov eax,uMsg
.if eax==WM_INITDIALOG
.elseif eax==WM_CTLCOLORDLG
.elseif eax==WM_SIZE
.elseif eax==WM_COMMAND
.elseif eax==WM_CLOSE
.else
mov eax,FALSE
ret ;bad design to use multiple RET's
.endif
mov eax,TRUE ;oops - overwrites any value in EAX
ret
i prefer this method, although not all forum members agree with me - lol
mov eax,uMsg
.if eax==WM_INITDIALOG
;init dialog code
mov eax,TRUE ;return TRUE - see WM_INITDIALOG documentation
.elseif eax==WM_CTLCOLORDLG
;paint background code
mov eax,hbrNull ;null brush handle - see WM_CTLCOLORDLG documentation
.elseif eax==WM_SIZE
;size code
mov eax,TRUE ;standard for most handled messages - see DialogProc documentation
.elseif eax==WM_COMMAND
;command code
mov eax,TRUE ;standard for most handled messages - see DialogProc documentation
.elseif eax==WM_CLOSE
;close code
mov eax,TRUE ;standard for most handled messages - see DialogProc documentation
.else
mov eax,FALSE ;standard for un-handled messages - see DialogProc documentation
.endif
ret
I checked every line of code, and finally found the reason
At the end of the Dialog function
.else
xor eax,eax ;return FALSE
ret
.endif
; mov eax,TRUE ;I should comment the trip, but this is Radasm template code,so not notice before
ret
DlgProc endp
end start
maybe we should suggest KetilO modify the template code
I read the template code again, most Msg should return TRUE ,so add mov eax,TRUE
in the end before the last ret
,we will not need to add the same code in each message,when requires special return values add a ret
well ok.and this can reduce the number of code volume and reducing program volume
re-read my last 2 posts :P