Re: get mouse position in win32
- Posted by "Cuny, David" <David.Cuny at DSS.CA.GOV> Nov 13, 1998
- 1501 views
[Sorry about the length of this post, but it the answer requires a bit of detail. As a bonus, you also get a silly scribble program!] Jamie Murphy wrote: > Using win32lib, Does anyone know a function > that would keep track of the mouse position > in a win32 program, Like an onMouseOver routine? Nothing like that exists in the library (yet). I'll add it eventually. In the mean time, you should be able to hook into it with onEvent (see below). > Also, can anyone explain how to use the > onEvent[] routine? I can't seem to do it > without errors. The onEvent routine is used to hook into Win32 events that Win32Lib doesn't trap. If a window or control has an onEvent() handler, it is called *before* any other handling. The parameters that are passed are: onEvent( aMsg, wParam, lParam ) Please note that my documentation says that the first parameter is iMsg, but it really should be defined as an atom! the aMsg parameter is the event that Win32 is reporting. For example, here are some of the events Win32Lib traps, and the names of the wrappers: WM_CREATE onLoad WM_SIZE onResize WM_SETFOCUS onGetFocus WM_KILLFOCUS onLoseFocus WM_KEYDOWN onKeyPress WM_LBUTTONDOWN onClick WM_RBUTTONDOWN onRightClick WM_LBUTTONDBLCLK onLeftClick WM_PAINT onPaint WM_HSCROLL onScroll WM_VSCROLL onScroll WM_TIMER onTimer WM_CLOSE onUnload The parameters wParam and lParam hold the parameters of the event. In the case of WM_KEYDOWN, for example, the key number is passed in wParam. Another example of this is the mouse events, where the X value is in the low word of lParam, and Y is in the high value of lParam . Some events are even more complex. For example, there are several tests for WM_COMMAND in Win32Lib's event loop. Here's one of them: elsif ( iMsg = WM_COMMAND and lParam = NULL) then -- menu or accelerator? if hi_word( wParam ) = 1 then -- from accelerator; -- this should not happen else -- get the menu id id = lo_word( wParam ) -- get the pointer pointer = onMenu[ id ] -- action? if pointer != -1 then call_proc( pointer, {} ) end if end if In this case, If: 1. the event is WM_COMMAND, and 2. lParam is NULL, and 3. the high word in wParam is 0, Then: the low word in wParam contains the id of a menu command. > Where can I find some info on win32 low level programming? You might want to look at: http://listserv.muohio.edu/archives/euphoria.html and search on windows programming. There is a Win32 help file in the Euphoria Archives which is quite helpful. I also have a copy of the Win32 API file that came with Visual Basic, which is very helpful for getting the definitions of constants (such as WM_MOUSEMOVE, for example). These constants are explained, but not defined, in the Win32 help file. Ok, now to answer your question about tracking the mouse. Here is some example code from the Win32 help file: -- EXAMPLE BEGIN -- In the following example, the window procedure prepares for drawing when the user presses and holds the left mouse button (sending the WM_LBUTTONDOWN message). As the user moves the cursor within the window, the window procedure receives a series of WM_MOUSEMOVE messages. For each message, the window procedure draws a line connecting the previous position and the current position. To draw the line, the procedure uses GetDC to retrieve a display DC; then, as soon as drawing is complete and before returning from the message, the procedure uses the ReleaseDC function to release the display DC. As soon as the user releases the mouse button, the window procedure clears the flag, and the drawing stops (which sends the WM_LBUTTONUP message). BOOL fDraw = FALSE; POINT ptPrevious; . . . case WM_LBUTTONDOWN: fDraw = TRUE; ptPrevious.x = LOWORD(lParam); ptPrevious.y = HIWORD(lParam); return 0L; case WM_LBUTTONUP: if (fDraw) { hdc = GetDC(hwnd); MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL); LineTo(hdc, LOWORD(lParam), HIWORD(lParam)); ReleaseDC(hwnd, hdc); } fDraw = FALSE; return 0L; case WM_MOUSEMOVE: if (fDraw) { hdc = GetDC(hwnd); MoveToEx(hdc, ptPrevious.x, ptPrevious.y, NULL); LineTo(hdc, ptPrevious.x = LOWORD(lParam), ptPrevious.y = HIWORD(lParam)); ReleaseDC(hwnd, hdc); } return 0L; An application that enables drawing, as in this example, typically records either the points or lines so that the lines can be redrawn whenever the window is updated. Drawing applications often use a memory DC and an associated bitmap to store lines that were drawn by using a mouse. -- EXAMPLE END -- The Win32Lib routines automatically take care of the DC, so you only have to worry about trapping the events. I got the values from my VB API file: WM_MOUSEMOVE = #200 WM_LBUTTONDOWN = #201 WM_LBUTTONUP = #202 WM_LBUTTONDOWN is already defined in Win32Lib. Translating the code is trivial: -- CODE BEGIN -- include win32lib.ew constant Win = create( Window, "Draw Line Demo", 0, Default, Default, 200, 200, 0 ) -- mouse events constant WM_MOUSEMOVE = #200, -- WM_LBUTTONDOWN = #201, (already defined ) WM_LBUTTONUP = #202 integer fDraw, priorX, priorY fDraw = 0 -- initially false procedure Event( atom aMsg, atom wParam, atom lParam ) -- implement mouse drawing integer x, y if compare( aMsg, WM_MOUSEMOVE ) = 0 then -- in drawing mode? if fDraw then -- capture mouse position x = lo_word( lParam ) y = hi_word( lParam ) -- draw a line drawLine( Win, priorX, priorY, x, y ) -- save current point priorX = x priorY = y end if elsif compare( aMsg, WM_LBUTTONDOWN ) = 0 then -- flag drawing to begin fDraw = 1 -- capture mouse position priorX = lo_word( lParam ) priorY = hi_word( lParam ) elsif compare( aMsg, WM_LBUTTONUP ) = 0 then -- capture mouse position x = lo_word( lParam ) y = hi_word( lParam ) -- draw a line drawLine( Win, priorX, priorY, x, y ) -- end drawing mode fDraw = 0 end if end procedure -- tell Windows when to do the action onEvent[Win] = routine_id( "Event" ) -- hand control over to Windows WinMain( Win ) -- CODE END -- I could have used the onClick event instead of trapping WM_LBUTTONDOWN, but it seemed simpler to code it this way. Besides, it shows how you can pretty much ignore Win32Lib's wrappers if you want to. Hope this helps! -- David Cuny