News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

character values?

Started by jannes braet, June 19, 2012, 01:49:13 AM

Previous topic - Next topic

jannes braet

hello everyone,
i have made a code but it doesn't quite work as expected. so the main intention of the program is to output  the x-coordinate if you click after pressing 1,to output the y-coordinate if you click after pressing 2 and both after pressing 3.
if none of these keys was pressed it should output press 1,2 or 3.
this is the code i have now:
i have chosen the values for 1,2 and 3 with an ascii table but i'm not sure if it is the same for asm. i believe it is since 20h in ascii is also space.


WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

.IF uMsg==WM_DESTROY
        invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CHAR
push wParam
pop char ;char starts with value of 20h (=space)
.ELSEIF uMsg==WM_LBUTTONDOWN
mov eax,lParam
and eax,0FFFFh
mov hitpoint.x,eax
mov eax,lParam
shr eax,16
mov hitpoint.y,eax
mov MouseClick,TRUE
invoke InvalidateRect,hWnd,NULL,TRUE
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint,hWnd,ADDR ps
mov hdc,eax
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
.IF char==31h ;1
invoke TextOut,hdc,hitpoint.x,hitpoint.y,hitpoint.x,SIZEOF hitpoint.x
.ELSEIF char==32h;2
invoke TextOut,hdc,hitpoint.x,hitpoint.y,hitpoint.y,SIZEOF hitpoint.y
.ELSEIF char==33h ;3
invoke lstrlen,ADDR hitpoint
invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR hitpoint,eax
.ELSE
invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR text,SIZEOF text ;press 1,2 or 3
.ENDIF
        invoke SelectObject,hdc,hfont
invoke EndPaint,hWnd,ADDR ps
.ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .ENDIF

the output i get is always press 1,2 or 3
so could someone tell me what i am doing wrong?

dedndave

you will probably want to reboot   :P

you create a new font every time your window gets a WM_PAINT message
better to create a font in WM_CREATE and save the handle in a var like hFont
then, use DeleteObject in WM_DESTROY to delete the hFont
these are GDI objects, and the system only has so much space allocated for them
the way your program is currently written, as you run it more times, the system will act screwier   :biggrin:

as for it not working...
i would construct a string in a buffer when mouse buttons are pressed
when the string changes, use InvalidateRect and UpdateWindow to force an update
then, in WM_PAINT, all you have to do is select hFont and display the string

jannes braet

#2
after following your tips i have something like this now but i'm not sure on how to work with a buffer. so can someone explain me that ? or how to store data in a buffer. and i'm also not sure on the way i display my data.

.data?
buffer db 512 dup(?)
...
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT
LOCAL hfont:HFONT

    .IF uMsg==WM_DESTROY
invoke DeleteObject,hfont
invoke EndPaint,hWnd,ADDR ps
        invoke PostQuitMessage,NULL
.ELSEIF uMsg=WM_CREATE
invoke BeginPaint,hWnd,ADDR ps
mov hdc,eax
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
    .ELSEIF uMsg==WM_COMMAND
        mov eax,wParam
        .IF ax==IDM_TEST
            invoke MessageBox,NULL,ADDR Test_string,OFFSET AppName,MB_OK
        .ELSEIF ax==IDM_HELLO
            invoke MessageBox, NULL,ADDR Hello_string, OFFSET AppName,MB_OK
        .ELSEIF ax==IDM_GOODBYE
            invoke MessageBox,NULL,ADDR Goodbye_string, OFFSET AppName, MB_OK
        .ELSE
            invoke DestroyWindow,hWnd
        .ENDIF
.ELSEIF uMsg==WM_CHAR
push wParam
pop char
.ELSEIF uMsg==WM_LBUTTONDOWN
mov eax,lParam
and eax,0FFFFh
mov hitpoint.x,eax
mov eax,lParam
shr eax,16
mov hitpoint.y,eax
mov MouseClick,TRUE
invoke InvalidateRect,hWnd,NULL,TRUE
.ELSEIF uMsg==WM_PAINT
.IF char==31h ;1
invoke lstrlen,ADDR buffer
invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR buffer,eax
.ELSEIF char==32h;2
invoke lstrlen,ADDR buffer
invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR buffer,eax
.ELSEIF char==33h ;3
invoke lstrlen,ADDR buffer
invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR buffer,eax
.ELSE
invoke lstrlen,ADDR buffer
invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR buffer,eax
.ENDIF
.ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .ENDIF
    xor    eax,eax
    ret
WndProc endp

dedndave

#3
ouch !

BeginPaint should not be in WM_CREATE
EndPaint should not be in WM_DESTROY
put them back in WM_PAINT

i assume you want to display the string at the same location each time
let's use the upper left corner of the client area - not the hitpoint   :P

to handle the buffer, you need to convert the binary values into ASCII strings and place them in the buffer

EDIT: code removed (syntax errors) - see attachment below

dedndave

ok - i played with it a little bit   :P

keys 0 to 3 work (0 turns both off)

jannes braet

thank you very much i will take a look at these codes and i hope i will learn alot from it ;p
but one thing i was wondering is how did you make your own icon and how did you add it to the program?

dedndave

there are a number of free icon editors out there
but, i use Axialis IconWorkshop, which is not free
http://speckyboy.com/2008/05/03/top-5-free-icon-editors-for-the-pro-designer/
http://filehippo.com/download_icofx/

to add the icon to the program, you add it to the resource file
in this case, it's named SmallWin.rc - a text file that can open with NotePad
#define  IDI_ICON               501

IDI_ICON  ICON  DISCARDABLE  "SmallWin.ico"

look at the batch files to see how the resource file is added to the program

then, in the SmallWin.inc file...
IDI_ICON    EQU 501
and in the program...
        INVOKE  LoadIcon,hInstance,IDI_ICON
LoadIcon returns a handle that may be used in the WNDCLASSEX.hIcon and hIconSm members
(when the window class is registered)
LoadImage can also be used
another way to set a window icon is to send it a WM_SETICON message
        INVOKE  SendMessage,hWnd,WM_SETICON,ICON_BIG,hIcon
        INVOKE  SendMessage,hWnd,WM_SETICON,ICON_SMALL,hIcon

ICON_BIG is used when icon view is used in explorer (and other places) (32x32)
ICON_SMALL is used in the window title bar (and other places) (16x16)
if you send the message in WM_CREATE of the same window, use PostMessage

i usually try to make them 16-color icons, but 256-color is ok, too
more colors than that is silly for such a small image - and it makes for larger files

jannes braet

uhm can you tell me what the intention of the copystring is and what is that ustr$(eax) ?

dedndave

well - it's just a little subroutine to fill the buffer with ASCII decimal numbers and/or spaces
it always sets 11 characters into the buffer
the buffer is 22 characters long (11 for X, 11 for Y)

ustr$ is a macro in the masm32 package for converting unsigned binary values to ASCII decimal
i probably should have used str$ - for signed values
but...
        mov     eax,str$(eax)
doesn't work
this would probably work
        push    str$(eax)
        pop     eax

the macros are described in \masm32\help\hlhelp.chm
and defined in \masm32\macros\macros.asm

jj2007

Quote from: dedndave on June 20, 2012, 08:35:06 PM
this would probably work
        push    str$(eax)
        pop     eax


Unfortunately not. You can replace the
      EXITM <ADDR rvstring>
in macros.asm with
      EXITM <OFFSET rvstring>

Otherwise, for geniuses who like it a bit more complicated, here is a workaround :biggrin:

include \masm32\include\masm32rt.inc

mov_eax MACRO arg
ifndef maDummy
   maDummy PROTO :DWORD
   .if 0
      maDummy proc maArg
      mov eax, maArg
      ret
      maDummy endp
   .endif
  endif
   invoke maDummy, arg
   exitm <>
endm


.code
start:   mov eax, 123
   mov_eax(str$(eax))
   MsgBox 0, eax, "Hi", MB_OK
   exit

end start

jannes braet

ok i think i get pretty much of the codes you have used now except the  movsx   eax,word ptr lParam and the   movsx  eax,word ptr lParam+2
i know movsx adds sign bits to the word but i don't see why we would have to use sign in this case.
and could you also explain what exactly is going on in the copystring. because i know it puts the numbers or spaces in the buffer but i don't see how that is accomplished :s. i'm sorry for asking so much but i'm just new to this.
and why do you use: or esi,esi in the copystring function. if you do that you still have the same number or not?

qWord

Mouse coordinates can also get negative - you can get wrong positions without the sign extension, if the window has the mouse capture.
The OR reg,reg modifies the flags, thus you can check whether the register is zero (also possible: sign and parity of the low byte).

BTW: the TEST instruction should be used instead of OR, because it discard the redundant result ...

EDIT: typo
MREAL macros - when you need floating point arithmetic while assembling!

dedndave

Quote from: qWord on June 21, 2012, 02:23:37 AM
The OR reg,reg modifies the registers, thus you can check whether the register is zero (also possible: sign and parity of the low byte).

mainly, i use OR on a register like that to set the sign and zero flags according to the value of the register
after that, you can use JZ/JNZ or JS/JNS
OR'ing a register on itself does not alter its' value

the CopyString11 routine is fairly simple

at the time i wrote it, i knew i was using unsigned numbers
unsigned binary dword's can have a decimal value from 0 to 4294967295 (10 digits max)
so - i made the buffer for each axis 11 characters in size
the X string will always be seperated from the Y string by at least 1 space

i know the mouse will never get to such coordinates - lol
but - i wanted it to work, even if incorrect values got plugged into it

so - we could simply put the numeric digits into the buffer and be done, right ?
not quite
as smaller values are displayed over larger values, the trailing digits would still be displayed
so - i back-fill the remainder of the 11 characters with spaces
this ensures that the old value will be overwritten and only the new value will show

another thing i did in this regard was to use a monospaced font
if you use a true-type font, remnants of previously displayed characters (artifacts) would need to be cleared out

back to the CopyString11 routine...
we pass a source string address (from ustr$ macro) to the copy routine
we simply copy characters until a 0 is encountered, which signifies the end of the string
after that, we pad with spaces until we have filled a total of 11 characters

if the source pointer is 0, we simply fill in 11 spaces

qWord

Quote from: dedndave on June 21, 2012, 02:50:55 AM
Quote from: qWord on June 21, 2012, 02:23:37 AM
The OR reg,reg modifies the registers, thus you can check whether the register is zero (also possible: sign and parity of the low byte).

mainly, i use OR on a register like that to set the sign and zero flags according to the value of the register
after that, you can use JZ/JNZ or JS/JNS
that was a typo - I meant "[...] modifies the flags [...]"  :redface:
MREAL macros - when you need floating point arithmetic while assembling!

jannes braet

and what about the? movsx   eax,word ptr lParam