Why is it, that I have to write "-1", at the end of TextOut, to make the text NOT display the trailing zero ::)
and
Do I "restore" the original font in the right manner everytime I create a new font :eek
.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
RGB macro red,green,blue
xor eax,eax
mov ah,blue
shl eax,8
mov ah,green
mov al,red
endm
.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
TestString db "This is written with the OEM_CHARSET",0
NormalWriting_1 db "I'm writing in the original font ;-)",0
NormalWriting_2 db "I'm now writing in the original font again ;-)",0
RussianString db "This is written with the Russian Font !",0
RussianWriting db "I'm STILL writing with the last Selected Font !",0
VietnamString db "This is written with the Vietnamese Font !",0
FontName db "script",0
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
INVOKE ShowWindow, hwnd,SW_SHOWNORMAL
INVOKE UpdateWindow, hwnd
.WHILE TRUE
INVOKE GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT
LOCAL hfont:HFONT
LOCAL hVietnameseFont:HFONT
LOCAL hRussianFont:HFONT
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
invoke TextOut,hdc,380,270,ADDR NormalWriting_1,SIZEOF NormalWriting_1 -1 ; Why "-1" here ?
invoke CreateFont,24,16,0,0,400,0,0,0,OEM_CHARSET,\
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\
DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\
ADDR FontName
invoke SelectObject, hdc, eax
mov hfont,eax
RGB 255,0,0
invoke SetTextColor,hdc,eax
RGB 0,0,0
invoke SetBkColor,hdc,eax
invoke TextOut,hdc,380,300,ADDR TestString,SIZEOF TestString
invoke SelectObject,hdc, hfont
invoke CreateFont,0,0,0,0,400,0,0,0,VIETNAMESE_CHARSET,\
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\
DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\
ADDR FontName
invoke SelectObject, hdc, eax
mov hVietnameseFont,eax
RGB 255,0,0
invoke SetTextColor,hdc,eax
RGB 0,0,0
invoke SetBkColor,hdc,eax
invoke TextOut,hdc,380,330,ADDR VietnamString,SIZEOF VietnamString -1 ; Why "-1" here ?
invoke SelectObject,hdc, hfont
invoke CreateFont,0,0,0,0,400,0,0,0,RUSSIAN_CHARSET,\
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\
DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\
ADDR FontName
invoke SelectObject, hdc, eax
mov hRussianFont,eax
RGB 255,0,0
invoke SetTextColor,hdc,eax
RGB 0,0,0
invoke SetBkColor,hdc,eax
invoke TextOut,hdc,380,360,ADDR RussianString,SIZEOF RussianString -1 ; Why "-1" here ?
invoke TextOut,hdc,380,390,ADDR RussianWriting,SIZEOF RussianWriting -1 ; Why "-1" here ?
invoke SelectObject,hdc, hfont
RGB 0,0,0
invoke SetTextColor,hdc,eax
RGB 255,255,255
invoke SetBkColor,hdc,eax
invoke TextOut,hdc,380,420,ADDR NormalWriting_2,SIZEOF NormalWriting_2 -1 ; Why "-1" here ?
invoke EndPaint,hWnd, ADDR ps
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start
regards,
The SharK
Because TextOut requires you to tell it HOW MANY characters to print; it doesn't know/care whether your string is null-terminated or not. So when you do "SIZEOF yourstring" you're getting the length of the string including its terminating zero, so you have to subtract 1 to get the length without the zero. In other words, the terminating null isn't required for such strings (unless you plan to use them elsewhere, where it is required.)
When you do a "SelectObject" it returns the object you just replaced. So, you don't actually need to select yours in, then put the old one back, then put another of yours in, then put the old one back... You can simply select yours in and save the previous one, then select another of yours in, and another, ..., and then finally restore the original when you've finished.
Also, remember to delete the fonts you've created when you no longer need them. In your case, it might be a better idea to create all of the fonts you need (in WM_CREATE) and save all of their handles for the lifetime of the program, then delete them all again on close (in WM_DESTROY)
Hi Tedd
Great advice :thumbu
I have adjusted the code according to your advice:
But now the SelectObject doesn't select anything - they all returns ZERO :dazzled:
regards,
The SharK
.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
RGB macro red,green,blue
xor eax,eax
mov ah,blue
shl eax,8
mov ah,green
mov al,red
endm
.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
OEMString db "This is written with the OEM_CHARSET",0
NormalString_1 db "I'm writing in the original font ;-)",0
NormalString_2 db "I'm now writing in the original font again ;-)",0
RussianString_1 db "This is written with the Russian Font !",0
RussianString_2 db "I'm STILL writing with the last Selected Font !",0
VietnamString db "This is written with the Vietnamese Font !",0
FontName db "script",0
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
INVOKE ShowWindow, hwnd,SW_SHOWNORMAL
INVOKE UpdateWindow, hwnd
.WHILE TRUE
INVOKE GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc :HDC
LOCAL ps :PAINTSTRUCT
LOCAL hfont :HFONT
LOCAL hOEM :HFONT
LOCAL hViet :HFONT
LOCAL hRuss :HFONT
.IF uMsg==WM_DESTROY
invoke DeleteObject, hOEM ; Deletes the OEM_CHARSET font object.
invoke DeleteObject, hViet ; Deletes the VIETNAMESE_CHARSET font object.
invoke DeleteObject, hRuss ; Deletes the RUSSIAN_CHARSET font object.
invoke PostQuitMessage,NULL ; The PostQuitMessage function indicates to the system that
; a thread has made a request to terminate (quit).
; It is typically used in response to a WM_DESTROY message.
.ELSEIF uMsg==WM_CREATE
invoke CreateFont, 24, 16, 0, 0, 400, 0, 0, 0, OEM_CHARSET,\
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,\
DEFAULT_QUALITY, DEFAULT_PITCH or FF_SCRIPT,\
ADDR FontName
mov hOEM, eax
invoke CreateFont, 0, 0, 0, 0, 400, 0, 0, 0, VIETNAMESE_CHARSET,\
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,\
DEFAULT_QUALITY, DEFAULT_PITCH or FF_SCRIPT,\
ADDR FontName
mov hViet, eax
invoke CreateFont, 0, 0, 0, 0, 400, 0, 0, 0, RUSSIAN_CHARSET,\
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,\
DEFAULT_QUALITY, DEFAULT_PITCH or FF_SCRIPT,\
ADDR FontName
mov hRuss, eax
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint, hWnd, ADDR ps
mov hdc, eax
invoke TextOut, hdc, 380, 270, ADDR NormalString_1, SIZEOF NormalString_1 -1
invoke SelectObject, hdc, hOEM
mov hfont, eax ; IMPORTANT! - Save the handle of the old font !!!
RGB 255, 0, 0
invoke SetTextColor, hdc, eax
RGB 0, 0, 0
invoke SetBkColor, hdc, eax
invoke TextOut, hdc, 380, 300, ADDR OEMString, SIZEOF OEMString -1
invoke SelectObject, hdc, hViet
RGB 255, 0, 0
invoke SetTextColor, hdc, eax
RGB 0, 0, 0
invoke SetBkColor, hdc, eax
invoke TextOut, hdc, 380, 330, ADDR VietnamString, SIZEOF VietnamString -1
invoke SelectObject, hdc, hRuss
RGB 255, 0, 0
invoke SetTextColor, hdc, eax
RGB 0, 0, 0
invoke SetBkColor, hdc, eax
invoke TextOut, hdc, 380, 360, ADDR RussianString_1, SIZEOF RussianString_1 -1
invoke TextOut, hdc, 380, 390, ADDR RussianString_2, SIZEOF RussianString_2 -1
RGB 0, 0, 0
invoke SetTextColor,hdc, eax
RGB 255, 255, 255
invoke SetBkColor,hdc, eax
invoke TextOut, hdc, 380, 420, ADDR NormalString_2, SIZEOF NormalString_2 -1
invoke SelectObject,hdc, hfont
invoke EndPaint,hWnd, ADDR ps
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax, eax
ret
WndProc endp
end start
hmmm
I think the answer is:
make the handles GLOBAL in the .data section !
.data
hfont dd HFONT
hOEM dd HFONT
hViet dd HFONT
hRuss dd HFONT
this worked though !
is this the correct solution ?
regards,
The SharK
Quote from: The SharK on January 28, 2008, 04:03:46 PM
make the handles GLOBAL in the .data section !
...
is this the correct solution ?
Yes indeed. WndProc is a callback procedure, which means that every time it gets called, there will be a completely virgin set of local variables. Note also that local variables are NOT zero-initialised.
Hi jj2007
should I make:
LOCAL hdc : HDC
LOCAL ps : PAINTSTRUCT
GLOBAL ? they seem to work both LOCAL or GLOBAL ::)
Quote from: The SharK on January 28, 2008, 04:27:40 PM
Hi jj2007
should I make:
LOCAL hdc : HDC
LOCAL ps : PAINTSTRUCT
GLOBAL ? they seem to work both LOCAL or GLOBAL ::)
They work local if they are assigned within the same CASE; e.g. if you process WM_PAINT:
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint, hWnd, ADDR ps
mov hdc, eax
...
invoke EndPaint,hWnd, ADDR ps
That's fine: you assign hdc at the beginning, and use the same ps from BeginPaint to EndPaint
ok,
so when you use LOCAL in the beginning of WndProc, you can't "mix" these
variables within every WM_ message.
I.E. if I create a font within WM_CREATE, I can't delete the object in WM_DESTROY, if the
handle to the font are LOCAL !
But if the handle to the font are GLOBAL, then I can use WM_CREATE to create the font,
and use WM_DESTROY to destroy it afterwards.
Conclusion:
So within every WM_ message, the code is LOCAL to the exact WM_ message right ?
and to make use of the variable in every WM_ message, you have to make it GLOBAL.
does this make any sense, or have I blurred it all :bg
regards,
The SharK
Quote from: The SharK on January 28, 2008, 06:37:36 PM
So within every WM_ message, the code is LOCAL to the exact WM_ message right ?
and to make use of the variable in every WM_ message, you have to make it GLOBAL.
Absolutely clear and correct :green
Thanks :U :dance: