News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Drawing mouse coordinates

Started by Moskacz, February 03, 2013, 10:54:25 AM

Previous topic - Next topic

Moskacz

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?

dedndave

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

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

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

jj2007

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:

Gunther

Hi Moskacz,

welcome to the forum.

Gunther
You have to know the facts before you can distort them.

Moskacz

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!

dedndave

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

Moskacz


Farabi

Quote from: Moskacz on February 03, 2013, 11:51:06 PM
How to create statusbar?

Use CreateWindowEx. I think it had a statusbar component.
http://farabidatacenter.url.ph/MySoftware/
My 3D Game Engine Demo.

Contact me at Whatsapp: 6283818314165

dedndave

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

dedndave

here is a simple example of a status bar with mouse position
i used CreateStatusWindow, because it is simpler for beginners

Moskacz

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?

dedndave

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

Moskacz

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? :/

dedndave

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

Moskacz

Thanks!

Stupid mistake, now everything is working!  :t