Re: get mouse position in win32
- Posted by "Cuny, David" <David.Cuny at DSS.CA.GOV> Nov 13, 1998
- 1308 views
Ad Reinks wrote: > Can you do [the scribble program] this easy in DOS? I couldn't resist, and ended up doing two versions of the code. The first looked like this: -- BEGIN CODE -- include graphics.e include mouse.e integer fDraw, x, y, priorX, priorY fDraw = 0 -- initially false object mouse, result -- set up screen if graphics_mode( 14 ) then puts( 1, "Unable to set graphics mode." ) abort(0) end if procedure drawLine( integer x1, integer y1, integer x2, integer y2 ) -- hide the mouse mouse_pointer(0) -- draw a line draw_line( BLACK, {{x1, y1}, {x2, y2}} ) -- show the mouse mouse_pointer(1) end procedure -- clear the screen result = video_config() x = result[VC_XPIXELS] y = result[VC_YPIXELS] polygon( WHITE, 1, {{0,0}, {x,0}, {x,y}, {0,y}} ) -- loop until exit key is pressed while compare( get_key(), 27 ) do -- get a mouse event mouse = get_mouse() if not sequence( mouse ) then mouse = {0,0,0} end if if and_bits( mouse[1], LEFT_DOWN ) then -- flag drawing to begin fDraw = 1 -- capture mouse position priorX = mouse[2] priorY = mouse[3] elsif and_bits( mouse[1], LEFT_UP ) then -- capture mouse position x = mouse[2] y = mouse[3] -- draw a line drawLine( priorX, priorY, x, y ) -- end drawing mode fDraw = 0 elsif and_bits( mouse[1], MOVE ) then -- in drawing mode? if fDraw then -- capture mouse position x = mouse[2] y = mouse[3] -- draw a line drawLine( priorX, priorY, x, y ) -- save current point priorX = x priorY = y end if end if end while result = graphics_mode( -1 ) -- END CODE -- It *looks* about the same. But there was a lot more work involved in the port than I thought. Some of the pitfalls I encountered were classics: 1. If you clear the screen by writing: bk_color( WHITE ) clear_screen() you end up redefining the color black. The pen color is then *invisible*. To clear the screen, you need to draw a screen-sized polygon instead. 2. Mouse events are combined in DOS - so a "move" and "left click" can appear in a single event. This means that you have to test with and_bits to get the correct mouse event. Otherwise, you don't see the mouse events. 3. The test sequence has to be reordered. As it was, a mouse event of MOVE+MOUSE_DOWN would hit the MOVE event first, so the MOUSE_DOWN event was never seen. Either that, or the tests would have to be made into seperate IF statements. 4. Before drawing a line, the mouse pointer had to be hidden, or it would overwrite what had just been written to the screen. Since Ad said "using whichever graphics library you want", I put together a small library: - display a window - splitting mouse events into seperate events It's about as simple as a basic GUI library can get, but still captures the flavor of an event-oriented GUI. It wouldn't take a lot of work to extend WinLib to handle keystrokes, text and other goodies, but I've already done that with Dos32Lib. -- START WINLIB.E -- include graphics.e include mouse.e global procedure drawLine( integer x1, integer y1, integer x2, integer y2 ) -- draw a line between two points -- hide the mouse mouse_pointer(0) -- draw a line draw_line( BLACK, {{x1, y1}, {x2, y2}} ) -- show the mouse mouse_pointer(1) end procedure procedure box( integer color, integer fill, integer x1, integer y1, integer x2, integer y2 ) -- draws an optionally filled box polygon( color, fill, {{x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}} ) end procedure -- holds the callback id integer callback procedure postEvent( integer event, integer parm1, integer parm2 ) -- send an event to the event handler callback call_proc( callback, {event, parm1, parm2 } ) end procedure global procedure eventLoop( integer callbackID ) -- simulates windows event loop integer x1, y1, x2, y2 object mouse, result -- set the callback callback = callbackID -- set graphics mode if graphics_mode( 18 ) then puts( 1, "Unable to set graphics mode." ) abort(0) end if -- clear the screen result = video_config() x2 = result[VC_XPIXELS] y2 = result[VC_YPIXELS] box( CYAN, 1, 0, 0, x2, y2 ) -- calculate the size of a window x1 = 100 y1 = 100 x2 = x2 - 100 y2 = y2 - 100 -- draw a window with shadows box( BLACK, 0, x1+1, y1+1, x2+1, y2+1 ) box( WHITE, 1, x1, y1, x2, y2 ) box( BLACK, 0, x1, y1, x2, y2 ) while 1 do -- exit on escape key if compare( get_key(), 27 ) = 0 then exit end if mouse = get_mouse() if sequence( mouse ) then -- in bounds? if mouse[2] < x1 or mouse[2] > x2 or mouse[3] < y1 or mouse[3] > y2 then -- zap the event mouse[1] = 0 end if -- click? if and_bits( mouse[1], LEFT_DOWN ) then postEvent( LEFT_DOWN, mouse[2], mouse[3] ) end if -- mouse release? if and_bits( mouse[1], LEFT_UP ) then postEvent( LEFT_UP, mouse[2], mouse[3] ) end if -- mouse move? if and_bits( mouse[1], MOVE ) then postEvent( MOVE, mouse[2], mouse[3] ) end if end if end while result = graphics_mode( -1 ) end procedure -- END WINLIB.E -- Here is the resulting event-oriented DOS Scribble program: -- BEGIN SCRIBBLE.EX -- integer fDraw, x, y, priorX, priorY fDraw = 0 -- initially false procedure process( integer event, integer parm1, integer parm2 ) if compare( event, MOVE ) = 0 then -- in drawing mode? if fDraw then -- capture mouse position x = parm1 y = parm2 -- draw a line drawLine( priorX, priorY, x, y ) -- save current point priorX = x priorY = y end if elsif compare( event, LEFT_DOWN ) = 0 then -- flag drawing to begin fDraw = 1 -- capture mouse position priorX = parm1 priorY = parm2 elsif compare( event, LEFT_UP ) = 0 then -- capture mouse position x = parm1 y = parm2 -- draw a line drawLine( priorX, priorY, x, y ) -- end drawing mode fDraw = 0 end if end procedure -- call the event loop eventLoop( routine_id( "process" ) ) -- END SCRIBBLE.EX -- -- David Cuny