Sign in to follow this  

DirectInput mouse grab/release

This topic is 4746 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm having a major headache with DirectInput 8 mouse capture. What i'm trying to do is move about a 3d world in the same way UnrealEd does. Hold down the right mouse button to grab the mouse cursor, and move the mouse about to change the camera view. In my program it works fine. Right mouse button down captures the mouse, and right mouse button release releases it, and I can interact with other programs without problems while mine is running. The insanity here is that the problem occurs on every other mouse button apart from the left ( DIMOFS_BUTTON0 ) Here's the problem: I hold down the right mouse ( or anything other than the left ) button for more than a few seconds ( 3 ) then release, then do anything, or nothing, then quit the program. I then bring up any window from the taskbar, and it comes into focus fine, then if I click on the menubar of the focused window, it loses focus. If I click on a non-focused menubar of a window, it doesn't gain focus. If I ALT+TAB to any window, the focus problems disappear until I next run my program. The problem doesn't occur until I close my program. I haven't been able to reliably trigger it, but sometimes, I can't even click the taskbar to bring up a window. ( it doesn't react ) The ALT+TAB always corrects the problem. -- The kicker is that the problem doesn't occur when I change the line mouseData[i].dwOfs == DIMOFS_BUTTON1 to mouseData[i].dwOfs == DIMOFS_BUTTON0 the error doesn't occur. It's only when BUTTON > 0 that the problem comes up. I can only guess that the problem is within the grabMouseCursor call, but I can't figure out why the problem comes up only when button > 0 Can anybody help here? Matthew. --
When reading buffered data:
    MOUSE_BUFFER_SIZE = 32


    assert(g_Mouse);
    DIDEVICEOBJECTDATA mouseData[MOUSE_BUFFER_SIZE];
    elements = MOUSE_BUFFER_SIZE;
    hr = g_Mouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
                                 mouseData, &elements, 0 );
    
    if ( hr != DI_OK ) {
        hr = g_Mouse->Acquire();
        while ( hr == DIERR_INPUTLOST )
            hr = g_Mouse->Acquire();
        
        return;
    }


    if ( mouseData[i].dwOfs == DIMOFS_BUTTON0 ) {
                static bool grab = true;
        
                common.sys->grabMouseCursor(grab);   
                grab = !grab; 
    }

--

void blSys::grabMouseCursor( bool grabIt ) {
    HRESULT hr = DI_OK;
    DWORD coopFlags;
      
    if ( grabIt )   coopFlags = DISCL_EXCLUSIVE | DISCL_FOREGROUND;
    else            coopFlags = DISCL_NONEXCLUSIVE | DISCL_FOREGROUND;
    
    assert(g_Mouse);
    g_Mouse->Unacquire();
    hr = g_Mouse->SetCooperativeLevel( _window.hwnd, coopFlags );
    assert( hr == DI_OK );
    g_Mouse->Acquire();
}

-- My setup code is:
    hr = g_DI->CreateDevice( GUID_SysMouse, &g_Mouse, NULL );
    assert( hr == DI_OK );
    
    // c_dfDIMouse2 allows support for more than 4 mouse buttons
    hr = g_Mouse->SetDataFormat( &c_dfDIMouse2 );
    assert( hr == DI_OK );
    
    dipdw.dwData           = MOUSE_BUFFER_SIZE;
    hr = g_Mouse->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph );
    assert( hr == DI_OK );
      
    grabMouseCursor(false);
       
    SetTimer(_window.hwnd, 0, 1000/60, NULL );

-- The timer event updates calls the reading buffered data method above -- And my shutdown code:
    if ( g_Mouse ) {
        g_Mouse->Unacquire();
        g_Mouse->Release();
        g_Mouse = 0;
    }

--

Share this post


Link to post
Share on other sites
Sheesh! Replying to my own post. A thread consisting of just me! Awww.

Well, it doesn't look like anybody is going to reply, but I've solved the problem, and my grab/release code works like a charm.

I'm not sure why it was a problem, but it seems the trouble was something to do with the SetCooperativeLevel. If someone could enlighten me, that would be great.

So, when initalising, I SetCooperativeLevel only once using the non-exclusive, and foreground flags. I then grabMouseCursor(false), and I then can grab, and relase in any situation without troubles.

There is also some trivial code in the WinProc function to Unacquire/reaquire the device when the window loses/gains focus respectively.

I modified my grabMouseCursor function, and here it is:

void blSys::grabMouseCursor( bool grabIt ) {
assert(g_Mouse);

if ( grabIt) {
g_Mouse->Acquire();
while ( ShowCursor( false ) >= 0 );
GetCursorPos( &g_MouseOldPos );
}
else {
g_Mouse->Unacquire();
SetCursor(LoadCursor(NULL, IDC_ARROW));
while( ShowCursor( true ) <= 0 );
g_Mouse->Acquire();
if ( g_MouseIsGrabbed ) SetCursorPos( g_MouseOldPos.x, g_MouseOldPos.y );
}

g_MouseIsGrabbed = grabIt;
}

Share this post


Link to post
Share on other sites

This topic is 4746 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this