(winapi) mouse hell

Started by
9 comments, last by fir 10 years, 4 months ago

I need obtain a MOUSE_DX and MOUSE_DY values where

MOUSE_DX is a difference between MOUSE_X and MOUSE_PREV_X

someone once gave stupid answer to me that i can hide cursor substract

succesive MOUSE_X between mouse move events, and when cursor

goes away from the centre of the sceen call ShowCursorPost to the

cantre of the screen - but this is a real hell : it is stupid perself also

calling ShowCursorPost generate fake mouse move events so

then I would need to filter out this fake movements then (It is hell)

Is there some more reasonable way of obtaining the MOUSE_DX

MOUSE_DY I need?

(much tnx for answr, very important)

Advertisement

http://msdn.microsoft.com/en-us/library/windows/desktop/ms645536%28v=vs.85%29.aspx


ShowCursorPost

You mean SetCursorPos?

Anyway, the method your friend suggested should work, but instead of subtracting the previous mouse cooridnates from the current coordinates like he said (or maybe you misunderstood), you should instead subtract the center of the screen from current coordinates. And SetCursorPos won't genrate WM_MOUSEMOVE if the cursor is already at the position you give it - that would cause an infinite loop when you call SetCursorPos while processing WM_MOUSEMOVE. So you will only get one unwanted WM_MOUSEMOVE message for when you move the cursor back to the center, but since you're subtracting those same coordinates, you'll get dx and dy values of 0, which you can easily ignore. You should also use SetCapture.

Yes, the standard way to get unfiltered (unaccelerated and unbounded) mouse movement events is through WM_INPUT, but I don't see how the SetCursorPos method is stupid... I find it quite ingenious, actually.


ShowCursorPost

You mean SetCursorPos?

Anyway, the method your friend suggested should work, but instead of subtracting the previous mouse cooridnates from the current coordinates like he said (or maybe you misunderstood), you should instead subtract the center of the screen from current coordinates. And SetCursorPos won't genrate WM_MOUSEMOVE if the cursor is already at the position you give it - that would cause an infinite loop when you call SetCursorPos while processing WM_MOUSEMOVE. So you will only get one unwanted WM_MOUSEMOVE message for when you move the cursor back to the center, but since you're subtracting those same coordinates, you'll get dx and dy values of 0, which you can easily ignore. You should also use SetCapture.

Yes, the standard way to get unfiltered (unaccelerated and unbounded) mouse movement events is through WM_INPUT, but I don't see how the SetCursorPos method is stupid... I find it quite ingenious, actually.

(yes SetCursorPos, sorry for typos)

Well the thing you say is some modification of the thing i use

- maybe it would work somewhat better (need to check it)

why this (the way I used it is bad i wrote some description

previously I can add)

does the games use the way you write -it still seem bad for

me

what exactly shoul i do, SetCursorPos(centreof window) in every WM_MOUSEMOVE handler?

//////////////

" (more explaining for questions )

I want to use mouse as a steering device - something like mowing yaw/pitch/roll of the camera

For this purpose I need to gest something like MOUSE_DELTA_X MOUSE_DELTA_Y where such numbers are indeed the MOUSE_X-MOUSE_PREV_X where MOUSE_X/Y are coordinates of the mouse cursor given to me by WM_MOUSEMOVE

allright - this works to some extent but not much: I need the DX DY walues related to mouse movements but do not need a mouse cursor at all, when mouse cursor hits the screen edge i will not gest full DX but some cutted and then all zeros

To prevent this i call (as somebody advice me) SetCursorPos when the cursor nears to the edge of the desktop (the window really becouse I do not want him to exit my window) then I call SetCursorPos to the centre of the client area (I also make cursor invisible, and also clip it to the window size but it also brings a lot of trouble, need to unclip the areo on alt+tab etc it is all tiresome and it is all a complex workaround for such simple thing like obtaining DX DY) I just do not need this f*cking invisible cursor moving on screen at all here - but I need mouse DX DY only

but let assume that this machinery with invisible cursor is tiresomely coded and debugged

the other trouble is that when I call SetCursorPos It also generates fake mouse movement backward and it generates fake DX and DY then (it is hard to filter - at least i do not know how to do it all in a robust way)

(can this fake mouse move been easily filtered out?)

I did it all this invisible cursor clipping SetCursorPos and filtering out the false DX DY but it is very ugly thing very error prone and confusing - all this for simple obtaining (cursor independant/mouse related)DX DY for every move - this is hell It made me a long hours to debug this stuff so I am angry - this is coding hell - this is terribly wrong so I am angry and need a good way of doing it "

With the version i say I think will work like that:

(say that i move a mouse to het +2, +10) mousemove

in mousemove handler i wil receive +2, +10, OK, then i will

SetCursprPos and it will generate next mouse move with -2, -10

and this brings the same trouble how to filter this fake movements I do not need?

Also can I get more than one mousemove per frame, say

when i receive +2, +10 and still moving the mouse in the

next one can I receive +1, +7 - continue of my movement

then fake -2, -10 , then again fake -1, -7?

why this (the way I used it is bad i wrote some description previously I can add)

does the games use the way you write -it still seem bad for me

what exactly shoul i do, SetCursorPos(centreof window) in every WM_MOUSEMOVE handler?

As tonemgub suggested, you should always treat the center of the screen as the "previous mouse position":

case WM_MOUSEMOVE: {
    int x = GET_X_PARAM(lParam);
    int y = GET_Y_PARAM(lParam);
    
    int dx = x - center_x;
    int dy = y - center_y;
    
    if ( dx || dy ) {
        on_mouse_move( dx, dy );
        SetCursorPos( center_x, center_y );
    }
} break;
A WM_MOUSEMOVE is still generated when snapping the cursor back to the center of the screen, but the event is ignored, since dx and dy would be 0. As far as I know, most FPS games use this approach.

Also can I get more than one mousemove per frame

Yes, it may be possible to receive multiple WM_MOUSEMOVE events per frame. You may want to handle accordingly:
void on_mouse_move( int dx, int dy ) {
    total_dx += dx;
    total_dy += dy;
}

void on_update( float dt ) {
    update_camera_look(total_dx * sensitivity_x * dt, total_dy * sensitivity_y * dt);
    total_dx = 0;
    total_dy = 0;
}

why this (the way I used it is bad i wrote some description previously I can add)

does the games use the way you write -it still seem bad for me

what exactly shoul i do, SetCursorPos(centreof window) in every WM_MOUSEMOVE handler?

As tonemgub suggested, you should always treat the center of the screen as the "previous mouse position":


case WM_MOUSEMOVE: {
    int x = GET_X_PARAM(lParam);
    int y = GET_Y_PARAM(lParam);
    
    int dx = x - center_x;
    int dy = y - center_y;
    
    if ( dx || dy ) {
        on_mouse_move( dx, dy );
        SetCursorPos( center_x, center_y );
    }
} break;
A WM_MOUSEMOVE is still generated when snapping the cursor back to the center of the screen, but the event is ignored, since dx and dy would be 0. As far as I know, most FPS games use this approach.

Also can I get more than one mousemove per frame

Yes, it may be possible to receive multiple WM_MOUSEMOVE events per frame. You may want to handle accordingly:

void on_mouse_move( int dx, int dy ) {
    total_dx += dx;
    total_dy += dy;
}

void on_update( float dt ) {
    update_camera_look(total_dx * sensitivity_x * dt, total_dy * sensitivity_y * dt);
    total_dx = 0;
    total_dy = 0;
}

Allright , much tnx for that - It still looks not quite good way

(I mean quite wrong) way of doing that - but this is probably

slight improvement about my way - and code looks quite nice

If i use this approach i need to clip the mouse to the window

- it then works bad on alt + tab, is there an pair of events

i should unclip and clip again the cursor? this is all complicated and dirty


If i use this approach i need to clip the mouse to the window

No, no, no, no, no...smile.png I said:


You should also use SetCapture.

Don't use ClipCursor - if you do that, you you only limit the cursor's movement space further, which is the only problem with this method. But if you leave it clipped to the whole screen, the chance that a single mouse move reaches the edge of the screen from the center is very small (if even possible at all).


If i use this approach i need to clip the mouse to the window

No, no, no, no, no...smile.png I said:


You should also use SetCapture.

Don't use ClipCursor - if you do that, you you only limit the cursor's movement space further, which is the only problem with this method. But if you leave it clipped to the whole screen, the chance that a single mouse move reaches the edge of the screen from the center is very small (if even possible at all).

But (at least if you have a fast mouse and a small window) it is quite managale to click with such invisible cursor out of its

parent window (and lost the focus) - i have seen that as far as i remember- this solution gets me quite angry


But (at least if you have a fast mouse and a small window) it is quite managale to click with such invisible cursor out of its

parent window (and lost the focus) - i have seen that as far as i remember- this solution gets me quite angry

That is why you use SetCapture. Just read the MSDN documentation for it: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646262%28v=vs.85%29.aspx

You're obviously after code, so here:


case WM_SETFOCUS:
    SetCapture(hwnd);
    break;

EDIT: I think you misunderstand this phrase from MSDN:

SetCapture captures mouse input either when the mouse is over the capturing window, or when the mouse button was pressed while the mouse was over the capturing window and the button is still down.

It does not mean that when your window has the mouse capture you can still click outside the window, and it will lose focus, if this is how you understand it. It means that you can only use SetCapture while the mouse cursor is above your window, or when you click inside your window, but after your window has the mouse captured, all mouse messages are sent to your window, until you call ReleaseCapture or your application loses focus (due to Alt+TAB, for ex.).

This topic is closed to new replies.

Advertisement