Re: get mouse position in win32

new topic     » goto parent     » topic index » view thread      » older message » newer message

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. smile

-- 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

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu