The MASM Forum

General => The Campus => Topic started by: Moskacz on February 03, 2013, 10:54:25 AM

Title: Drawing mouse coordinates
Post by: Moskacz on February 03, 2013, 10:54:25 AM
Hi,

Im new to MASM. I want to build small program that will be showing mouse position. I know there is GetCursorPosition API function. But i have problem in drawing coordinates on screen. I have a frame and I want two strings in that frame  - "X cord: " and "Y cord: ". Which function i should use to draw double (point.x and point.y) on a screen?
Title: Re: Drawing mouse coordinates
Post by: dedndave on February 03, 2013, 11:00:36 AM
you don't have to "get" the cursor position
the top window that has the cursor under it will recieve WM_MOUSEMOVE messages (when in client area)
lParam then holds X and Y mouse position

http://msdn.microsoft.com/en-us/library/windows/desktop/ms645616%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms645616%28v=vs.85%29.aspx)

for setting a pixel, you can use SetPixel
not the fastest way, but it will get you started

http://msdn.microsoft.com/en-us/library/windows/desktop/dd145078%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/dd145078%28v=vs.85%29.aspx)

you may also want to use GetDC to get the window DC

http://msdn.microsoft.com/en-us/library/windows/desktop/dd144871%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/dd144871%28v=vs.85%29.aspx)
Title: Re: Drawing mouse coordinates
Post by: jj2007 on February 03, 2013, 06:26:24 PM
Quote from: Moskacz on February 03, 2013, 10:54:25 AMWhich function i should use to draw double (point.x and point.y) on a screen?

WM_MOUSEMOVE handler plus a borderless static control should do the job. Post your current code, and we'll help you.

Welcome to the forum :icon14:
Title: Re: Drawing mouse coordinates
Post by: Gunther on February 03, 2013, 09:48:37 PM
Hi Moskacz,

welcome to the forum.

Gunther
Title: Re: Drawing mouse coordinates
Post by: Moskacz on February 03, 2013, 11:25:44 PM
Hi again :)

My code:


.386

.MODEL FLAT, STDCALL

OPTION CASEMAP:NONE

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

WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD

;zainicjowane dane

.DATA

ClassName DB "SimpleWinClass",0       ;nazwa naszej klasy okna
AppName   DB "Program pokazujacy obsluge myszki w MASM",0  ;tytuł naszego okna
OurText1 DB "Wspolrzedna X:", 0
OurText2 DB "Wspolrzedna Y:", 0
Position POINT<>
Position2 POINT<>
MouseClick1 db 0
MouseClick2 db 0
LeftButtonText DB "Left_Button", 0
RightButtonText DB "Right_Buton",0

;niezainicjowane dane

.DATA?

hInstance   HINSTANCE ?               ;uchwyt egzemplarza naszego programu
CommandLine LPSTR ?                   ;wskazanie wiersza poleceń

;tutaj rozpoczyna się nasz kod

.CODE

start:
    INVOKE GetModuleHandle, NULL     ;pobieramy uchwyt programu
    mov    hInstance, eax            ;pod Win32 hmodule==hinstance
    INVOKE GetCommandLine            ;pobierz wiersz polecenia. Nie musisz wywoływać
    mov    CommandLine, eax          ;tej funkcji, jeśli twój program nie przetwarza
                                     ;wiersza polecenia
    INVOKE WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT ;główna funkcja
    INVOKE ExitProcess, eax          ;kończymy program. Kod wyjścia jest zwracany
                                     ;w eax z WinMain.

WinMain PROC hInst:     HINSTANCE,\
             hPrevInst: HINSTANCE,\
             CmdLine:   LPSTR,\
             CmdShow:   DWORD

LOCAL wc:   WNDCLASSEX               ;na stosie tworzymy zmienne lokalne
LOCAL msg:  MSG
LOCAL hwnd: HWND
                                     ;wypełniamy pola struktury wc
    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   hInstance
    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   ;rejestrujemy naszą klasę okna
    INVOKE CreateWindowEx, NULL,\
                           ADDR ClassName,\
                           ADDR AppName,\
                           WS_OVERLAPPEDWINDOW,\
                           CW_USEDEFAULT,\
                           CW_USEDEFAULT,\
                           600,\
                           600,\
                           NULL,\
                           NULL,\
                           hInst,\
                           NULL
    mov    hwnd, eax
    INVOKE ShowWindow, hwnd, CmdShow  ;wyświetlamy nasze okno na pulpicie
    INVOKE UpdateWindow, hwnd         ;odświeżamy obszar roboczy

    .WHILE TRUE                       ;wchodzimy w pętle wiadomości
        INVOKE GetMessage, ADDR msg, NULL, 0, 0
        .BREAK .IF (!eax)
        INVOKE TranslateMessage, ADDR msg             
        INVOKE DispatchMessage, ADDR msg
    .ENDW

    mov eax, msg.wParam              ;kod powrotu zwracamy w eax
    ret

WinMain ENDP

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

LOCAL hdc: HDC
LOCAL ps: PAINTSTRUCT
LOCAL rect: RECT

    .IF uMsg==WM_DESTROY
        INVOKE PostQuitMessage, NULL
    .ELSEIF uMsg==WM_LBUTTONDOWN
        mov    eax, lParam
        and    eax, 0ffffh
        mov    Position.x, eax
        mov    eax, lParam
        shr    eax, 16
        mov    Position.y, eax
        mov    MouseClick1, TRUE
        mov    MouseClick2, FALSE
        INVOKE InvalidateRect, hWnd, NULL, TRUE
       
    .ELSEIF uMsg==WM_RBUTTONDOWN
        mov    eax, lParam
        and    eax, 0ffffh
        mov    Position2.x, eax
        mov    eax, lParam
        shr    eax, 16
        mov    Position2.y, eax
        mov    MouseClick2, TRUE
        mov    MouseClick1, FALSE
        INVOKE InvalidateRect, hWnd, NULL, TRUE

    .ELSEIF uMsg==WM_PAINT
        INVOKE BeginPaint, hWnd, ADDR ps
        mov    hdc, eax
       
        .IF MouseClick1
            INVOKE lstrlen, ADDR AppName
            INVOKE TextOut, hdc, Position.x, Position.y,\
                            ADDR LeftButtonText, eax
                           
        .ENDIF
       
        .IF MouseClick2
            INVOKE lstrlen, ADDR AppName
            INVOKE TextOut, hdc, Position2.x, Position2.y,\
                            ADDR RightButtonText, eax
           
        .ENDIF
       
        INVOKE EndPaint, hWnd, ADDR ps
    .ELSE
        INVOKE DefWindowProc, hWnd, uMsg, wParam, lParam
        ret
    .ENDIF


    xor eax, eax
    ret

WndProc ENDP


END start


Now, if i click left or right button my program will draw text that starts in clicked position. But I still want to draw coordinates of mouse cursor on a screen, and i don't know how. I know how to get x and y cord , but how draw this on a screen?

PS. I know my code may be stupid or something, but I started learning this yesterday.

Greetings!
Title: Re: Drawing mouse coordinates
Post by: dedndave on February 03, 2013, 11:30:07 PM
first, you have to convert the binary values into ascii decimal strings
the masm32 package has functions and macros for that
(see str$ macro in masm32\help\hlhelp.chm)

but, to display the text, use TextOut, ExtTextOut, DrawText, or DrawTextEx

personally, i would find it easier to create a status bar and display the position, there
you create the status bar
convert the value to ascii decimal
then use SendMessage to tell the status bar what string to display
Title: Re: Drawing mouse coordinates
Post by: Moskacz on February 03, 2013, 11:51:06 PM
How to create statusbar?
Title: Re: Drawing mouse coordinates
Post by: Farabi on February 03, 2013, 11:56:04 PM
Quote from: Moskacz on February 03, 2013, 11:51:06 PM
How to create statusbar?

Use CreateWindowEx. I think it had a statusbar component.
Title: Re: Drawing mouse coordinates
Post by: dedndave on February 04, 2013, 12:15:16 AM
yes - i prefer CreateWindowEx - there is also CreateStatusWindow

but, to use CreateWindowEx, use the pre-defined class string
szStatusClass db 'msctls_statusbar32',0

http://msdn.microsoft.com/en-us/library/windows/desktop/bb760726%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/bb760726%28v=vs.85%29.aspx)
Title: Re: Drawing mouse coordinates
Post by: dedndave on February 04, 2013, 12:22:03 AM
here is a simple example of a status bar with mouse position
i used CreateStatusWindow, because it is simpler for beginners
Title: Re: Drawing mouse coordinates
Post by: Moskacz on February 04, 2013, 01:25:14 AM
OK, i know how to create status bar but I still don't understand how did you convert long to dword.

I have position: POINT<>, so position.x and position.y hold my coords and i must convert these numbers to dword.

You told me to use str$ macro.
Here is code of this macro:

sstr$ MACRO number
        LOCAL buffer
        .data?
          buffer TCHAR 40 dup (?)
          align 4
        .code
        IFNDEF __UNICODE__
          invoke crt__ltoa,number,ADDR buffer,10
        ELSE
          invoke crt__ltow,number,ADDR buffer,10
        ENDIF
        EXITM <eax>
      ENDM

But if I have local variable tmp: DWORD i can't use this macro in this way - mov tmp, sstr$(position.x) [invalid symbol type in expression sstr$()].
What is the correct way to use this macro?
Title: Re: Drawing mouse coordinates
Post by: dedndave on February 04, 2013, 01:32:57 AM
yes - sorry about that
in my little example program i wrote my own routine to do the conversion
the drawback of that is - i don't think my little routine will handle negative numbers
the client coordinates should never be negative, but you never know   :P

but - for you, it may be easier to use one of the masm32 functions or macros
in the case of signed values, Hutch uses crt__ltoa from the MSVCRT library
you can do the same

invoke crt__ltoa,number,ADDR buffer,10
number is the value to be converted (could be in a register like ECX or EDX)
addr buffer is the address of the string buffer
10 is the radix or base

the macro creates the string and returns the address
that may not be convenient, in this case
Title: Re: Drawing mouse coordinates
Post by: Moskacz on February 04, 2013, 02:05:13 AM
Now I want to convert coordinates of point when I click somewhere in client area:


.ELSEIF uMsg==WM_RBUTTONDOWN
        mov    eax, lParam
        and    eax, 0ffffh
        mov    Position2.x, eax
        mov    eax, lParam
        shr    eax, 16
        mov    Position2.y, eax
        mov    MouseClick2, TRUE
        mov    MouseClick1, FALSE
        INVOKE InvalidateRect, hWnd, NULL, TRUE
        invoke crt__ltoa,Position2.x,tmpX,10


tmpX is a local variable :
LOCAL tmpX: DWORD

But it's not working, with line
invoke crt__ltoa,Position2.x,tmpX,10
i got window with message 'program.exe has stopped working' (when i click right button)

What's wrong? :/
Title: Re: Drawing mouse coordinates
Post by: dedndave on February 04, 2013, 02:15:52 AM
yes - it crashed because it wants the address of a string buffer
unless "tmpX" contains an address, you may get an access violation

for signed values, the buffer should be at least 12 bytes long
do not pass the contents - pass the address
Title: Re: Drawing mouse coordinates
Post by: Moskacz on February 04, 2013, 02:39:42 AM
Thanks!

Stupid mistake, now everything is working!  :t
Title: Re: Drawing mouse coordinates
Post by: MichaelW on February 04, 2013, 07:44:34 AM
If you capture the mouse, typically to track its position outside your window, then the client coordinates as reported by the various mouse messages, are negative when the mouse cursor is to the left of and/or above the window.
Title: Re: Drawing mouse coordinates
Post by: dedndave on February 04, 2013, 08:12:40 AM
that's true
however, if you design the code so that it doesn't report positions outside the window...
i.e., you ReleaseCapture when such a position is detected, and do not display it
Title: Re: Drawing mouse coordinates
Post by: hfheatherfox07 on February 04, 2013, 08:24:58 AM
Quote from: Moskacz on February 04, 2013, 02:39:42 AM
Thanks!

Stupid mistake, now everything is working!  :t

I get an error even before converting the co-ordinates with "invoke crt__ltoa"  when you left click you get:

Left_Button  Right_Buton , co-ordinates

even after converting with "invoke crt__ltoa" still get the last co-ordinate of right click when left clicking ?
Title: Re: Drawing mouse coordinates
Post by: dedndave on February 04, 2013, 09:08:00 AM
hard to trouble shoot it without seeing the code   :P
Title: Re: Drawing mouse coordinates
Post by: hfheatherfox07 on February 04, 2013, 10:54:41 AM
Quote from: dedndave on February 04, 2013, 09:08:00 AM
hard to trouble shoot it without seeing the code   :P

I agree , just nice to post the finished code ....more people will see it in the future and learn from it .... At least I do , when people help me I post the finished code for others to refer to  :biggrin:
It is a modified version of Iczelion's tut 7...

I was referring to the original code Moskacz posted ....
Compile it and you see when you left click...
I am under the impression that all that was added was the co ordinaries printing on the screen