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?
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)
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:
Hi Moskacz,
welcome to the forum.
Gunther
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!
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
How to create statusbar?
Quote from: Moskacz on February 03, 2013, 11:51:06 PM
How to create statusbar?
Use CreateWindowEx. I think it had a statusbar component.
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)
here is a simple example of a status bar with mouse position
i used CreateStatusWindow, because it is simpler for beginners
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?
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
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? :/
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
Thanks!
Stupid mistake, now everything is working! :t
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.
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
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 ?
hard to trouble shoot it without seeing the code :P
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