Re: Another Win32Lib question: captureMouse()

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

Ben Logan wrote:

> I'm pretty sure that's not happenning, because
> it retrieves the pixel values correctly as long
> as I click inside my program's window. It only doesn't
> work when I click outside the window.

The captureMouse routine works oddly, and not the way I would have expected
it to. Basically, it only works as long as the mouse button is held down.
For example:

  include win32lib.ew

  constant
  W = create( Window, "", 0, Default, Default, 100, 100, 0 )

  procedure press()
    captureMouse( W )
  end procedure
  onClick[W] = routine_id("press")

  procedure mouse( integer event, integer x, integer y, integer shift )
    repaintWindow( W )
    setPosition( W, 1, 1 )
    wPrintf( W, "%d, %d      ", {x,y} )
  end procedure
  onMouse[W] = routine_id("mouse")

  WinMain( W, Normal )

If you click in the window and keep the mouse held down, the mouse will
continue to track. As soon as you release the mouse button, tracking stops.
This approach is problematic at best.

The Win32 documentation states:

"Only the foreground window can capture the mouse. When a background window
attempts to do so, the window receives messages only for mouse events that
occur when the cursor hot spot is within the visible portion of the window.
Also, even if the foreground window has captured the mouse, the user can
still click another window, bringing it to the foreground.
When the window no longer requires all mouse input, the thread that created
the window should call the ReleaseCapture function to release the mouse.

This function cannot be used to capture mouse input meant for another
process."

Perhaps a better approach would be to set up a timer and track the mouse
that way. I don't know how to dynamically read the state of the mouse
buttons, but you can instead read the state of the keyboard. For example,
the following code tracks the mouse and the state of the space bar.

  include win32lib.ew

  constant
  Key = VK_SPACE,
  W = create( Window, "Button Example", 0, Default, Default, 200, 100, 0 )

  procedure timer( integer t )

    integer state
    sequence point, down, toggled

    -- get the mouse position
    point = getMousePos()

    -- get state of key
    state = c_func( xGetKeyState, { Key } )

    -- down?
    if and_bits( #8000, state ) then
        down = "yes"
    else
        down = "no"
    end if

    -- toggled?
    if and_bits( #1, state ) then
        toggled = "yes"
    else
        toggled = "no"
    end if

    -- erase the window
    repaintWindow( W )

    -- mouse status
    setPosition( W, 1, 1 )
    wPrintf( W, "mouse: %d, %d  key state: %x", point & state )

    -- keyboard status
    setPosition( W, 1, 32 )
    wPrintf( W, "state: %x  down: %s toggled: %s ", {state, down, toggled} )

  end procedure
  onTimer[W] = routine_id("timer")

  -- set timer running
  setTimer( W, 1, 100 )

  WinMain( W, Normal )

With this approach, you can set up the timer routine to look for a special
key combination. When the user presses the key(s), use getMousePos to
determine where the mouse was pressed.

You can track the state of the shift keys with the following constants:

   VK_SHIFT
   VK_SHIFT
   VK_CONTROL
   VK_LSHIFT
   VK_RSHIFT
   VK_LCONTROL
   VK_RCONTROL
   VK_LMENU
   VK_RMENU

So, for example, the code to watch for a CTRL+SHIFT+C key would be:

   if and_bits( c_func( xGetKeyState( { VK_CONTROL } ), #8000 )
   and and_bits( c_func( xGetKeyState( { VK_SHIFT } ), #8000 )
   and and_bits( c_func( xGetKeyState( { 'c' ), #8000 ) then
      -- your code here

   end if

I 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