Re: get mouse position in win32

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

[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

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

Search



Quick Links

User menu

Not signed in.

Misc Menu