Setting/Getting my absolute mouse position in windowed mode - c++

I searched, but most posts are just telling me what I already have, so below is basically my code right now:
DIKeyboard->Acquire();
DIMouse->Acquire();
DIMouse->GetDeviceState(sizeof(DIMOUSESTATE), &mouseCurrState);
DIKeyboard->GetDeviceState(sizeof(keyboardState),(LPVOID)&keyboardState);
MousePos.x += mouseCurrState.lX;
MousePos.y += mouseCurrState.lY;
Any post telling me how to get absolute position just says to use those last two lines. But my program is windowed, and the mouse can start anywhere on the screen.
i.e. If my mouse happens to be in the centre of my screen, that becomes position 0,0. I basically just want the top left of my window (not my screen) to be my 0,0 mouse coordinates, but am having a hard time finding anything relevant.
Thanks for any help! :)

Following the discussion in the comments, you'll have to decide which method works best for you. Unfortunately, having never worked with DirectInput, I do not know the ins-and-outs of it.
However, Window Messages work best for RTS-style controls, where a cursor is drawn to screen. This is due to the fact that this respects user settings, such as mouse acceleration and mouse speed, whereas DirectInput only uses the driver settings (so not the control panel settings). The user will expect the mouse to feel the same, especially in windowed mode.
DirectInput works better for FPS-style controls, when there is no cursor drawn, as window messages give you only the cursor coordinates, and not offset values. This means that once you are at the edge of the screen, window messages will no longer allow you to detect the mouse being moved further (actually, I am not 100% sure on this, so if someone could verify, please feel free to comment).
For keyboard, I would definitely suggest window messages, because DirectInput offers no advantages, and WM input is easier to use, and quite powerful (the WM_KEYDOWN messages contains a lot of useful data), and it'll allow you (via TranslateMessage) to get good text input, adjusted to locale, etc.).
Solving your problem with DirectInput:
You could probably use GetCursorPos followed by ScreenToClient to initialise your MousePos structure. I'm guessing you'll need to redo this every time you lose mouse input and reacquire it.
Hybrid solution (for RTS like controls):
It might be possible to use a hybrid solution for the mouse if you desire RTS-like controls. If this is the case, I suggest, though I have not tested this, to use WM for the movement of the mouse, which avoids the need for workaround mentioned above, and only use DirectInput to detect additional mouse buttons.
Now one thing I think you should do in such a hybrid approach is not directly use the button when you detect it via DirectInput, but rather post a custom application message to your own message queue (using PostMessage and WM_APP) with the relevant information. I suggest this because using WM you do not get the real-time state of the mouse & keyboard, but rather the state at the time of the message. Posting a message that the button was pressed allows you to handle the extra buttons in the same state-dependent manner (I don't know how noticeable this 'lag' effect is). It also makes the entire input handling very uniform, as every bit of input with this enters as a window message.

Related

When resizing, make the window transparent with a dotted-line border

I'm asking this question ahead of time, since I haven't gotten around to attempting an actual, real implementation yet. Win32 (C++) is turning out to be a colossal pain to program. But, my question is this:
I want to make my application's window become fully transparent with a dotted perimeter when resizing the window. How would I accomplish this? Think of what happens in Windows 3/3.1 (I believe it was this version) when resizing a window. Everything goes transparent, with a dotted-outline where the mouse is moving, then it repaints the entire contents. That's what I'm trying to achieve.
A while ago, I tried handling the WM_(ENTER/EXIT)SIZEMOVE messages and make use of SetWindowLong() to set the WS_EX_TRANSPARENT extended style, but my window became (indefinitely) pass-through, and when the window's focus was killed, it could never again regain focus.
Do I need to handle other messages like WM_NCLBUTTON(DOWN/UP)? I have a boolean flag to tell me when to halt drawing during resizing, and the logic for determining when I'm resizing works perfectly, but I cannot get the visuals to work. I'm not sure which parts of the Win32 API to actually use. I've done some research, and uxtheme.lib/.h seems promising, but I'm not sure how that would work with WM_NCPAINT, which I have been using with (some) luck.
EDIT
I need to clarify something, in case anyone was confused or unsure of what I meant. What I meant by the Windows 3.1/3 resizing scenario is that once WM_ENTERSIZEMOVE has occurred, the window (controls, caption, frame) should be made entirely invisible, and the window's nonclient-region's perimeter should display a dotted-outline of sorts. Then, only until the resize has been finished, when WM_EXITSIZEMOVE has occurred should the entire window (controls, caption, frame) be fully redrawn, updated, and returned to its normal, functional state. Sorry for any miscommunication!
I found the answer... After so long, finally found it. Here's where I found it! http://www.catch22.net/tuts/win32/docking-toolbars-part-2# - Hope it helps anyone else possibly in my shoes!
And it turns out that the solution was rather simple. In fact, the core concept of what is explained is near-completely what I was thinking, yet I just had no idea how to implement it. The solution involves overriding the default WM_NCLBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP (specifically when initiating a window movement) messages, and drawing a patterned rectangle which follows the position of the cursor. Then, afterwards, calling SetWindowPos or some other similar function to relocate the window.
Basically, block Windows from attempting to display anything graphics related until the resizing has been finished. Then, and only then, make Windows move the entire window in one huge, foul swoop.
Based on Remy's comment, there is a global option and corresponding registry setting for this, so perhaps try setting the registry setting when the move starts and restoring it when the move finishes.
Unfortunately this doesn't work as Windows appears only to pick up the setting on restart, broadcasting WM_SETTINGCHANGE also doesn't trigger it, which is a pity as doing something yourself that the OS already has an implementation of do is rather a poor state of affairs.

Capture mouse movement in win32/Opengl

At the moment I simply use the WM_MOUSEMOVE message, but it limits the mouse movement to the maximum resolution. So what's the best way of capturing the mouse with Win32 (on a OpenGl window)? I don't want to use freeglut or any extra library.
For games and realtime DirectInput is very suitable, it's moderately hard to use.
That is not core win32 api, the winapi way of getting the input is either GetCursorPos/SetCursorPos driven by your own update loop, so you query and reset with your own frequency.
Or SetCapture and then upon WM_MOUSEMOVE you call SetCursorPos.
The point of setting the cursor pos is to give room for movement so you can get the delta, the amount the cursor moved since the last update and then put it back the cursor into the center of your window.
If you want to be able to capture mouse events after the mouse has existed the window, then you might want to look into the SetCapture function
If your problem is that you want to make a FPS game and you want your character to be able to spin in a continuous motion, then you want to set the mouse position to the center of the window after each mouse move event and handle input based on the difference between the position of the cursor when the mouse move event is fired and the center of the screen. To set the position of the mouse you can use the SetCursorPos function.
Your best bets are to either use DirectInput (which can be a bit of a pain to set up) or RawInput.
There is a fairly comprehensive example available in the Using RawInput page (See example 2).

Exclusive mouse/keyboard with the Winapi

DirectInput had an option to have exclusive mouse/keyboard access. I'm now moving away from using DirectInput and was wondering how I could achieve the same behavior by just using the winapi?
Edit: I guess I could just use SetCursorPos() to the middle of the window and hide the cursor via ShowCursor()
In the case of the mouse, use the Windows raw input API.
Use the flag RIDEV_CAPTUREMOUSE in your RAWINPUTDEVICE structure for the call to RegisterRawInputDevices. This will prevent mouse clicks from activating other windows. In combination with that, use the ShowCursor function to hide the mouse cursor. Those 2 things will reproduce the DirectInput exclusive mouse behavior. In its later revisions, DirectInput (for the keyboard and mouse) is just a wrapper around the raw input api.
I don't believe there is any equivalent control over the keyboard (and I don't think there was in DirectInput either.) However, this is generally not a problem since the user won't be able to get the input focus onto another app unless they specifically want to with alt-tab or ctrl-alt-dlt.
Have you looked at SetCapture()?
It would help if your question were clearer. A lack of mouse input (ie WM_MOUSEMOVE messages) to an app is generally something the app is robust to. After all, a perfectly stationary mouse won't generate any such messages. So I'm guessing that you're doing something a little unusual.
There is also a mechanism for tracking the mouse leaving your app's window(s) - see here. It involves setting up a TrackMouseEvent structure which is a little painful but it does all seem to work in my experience. I'm wondering if in fact it is this mechanism which is pausing your app?
Can't help much more than that on the info provided I'm afraid.
Use ClipCursor() to confine the mouse within a specific rectangle of the screen, such as the rectangle of your window.

Raw mouse input with Windows

Reading this article "Taking Advantage of High-Definition Mouse Movement" - http://msdn.microsoft.com/en-us/library/windows/desktop/ee418864(v=vs.100).aspx, I surmise that one should use raw input for more precise readings from input devices.
The article states that WM_MOUSEMOVE's primary disadvantage is that it is limited to the screen resolution.
Upon close inspection of the RAWMOUSE structure I see that lLastX and lLastY are long values and you get the delta via them.
To me it looks like WM_MOUSEMOVE and WM_INPUT is the same except with WM_INPUT you do not get acceleration (pointer ballistics) applied.
Are both WM_MOUSEMOVE and WM_INPUT limited to the screen resolution?
If so, what is the benefit of using WM_INPUT?
RAWMOUSE gives you logical coordinates for the mouse based on the mouse's native resolution.
That is, you see the actual movement of the mouse.
Windows will use the mouse speed and acceleration (ballistics) settings to update the cursor position. Because of course the two are not linked - the apparent movement of the mouse must be interpreted to generate a cursor movement else how can more than one mouse be supported?
If you wish to control a pointer, as far as I can tell there is no reason to duplicate the Windows mouse ballistics calculations. Just let windows do it. Therefore for controlling the pointer, you should just use WM_MOUSEMOVE. That is, unless you wish to disable the mouse acceleration settings in your application.
However, if you want to control the player's POV (point of view), or use the mouse to control an in-game object such as a spaceship flight yoke, then the RAWMOUSE data gives you the best possible access to the movement of the mouse, and you can implement your own algorithm to convert that into flight yoke/POV movement.
The main benefit and reason to use it is that that with rawInput you can use two mouses or more. Presently I write small game prototype which is designed to be played by two players with two mouses/mices - It is more complicated but It works and it is not bad because I do nod need to link external libs.

How do I get the window that currently has the cursor on top of it with X11?

How can I retrieve the top window of which the cursor is on top of in the X11 server?
The window doesn't have to be ”active” (selected, open, whatever), it just has to have the cursor floating on top of it.
Thanks in advance.
You can use XQueryPointer() to get the mouse position. Then get a window list using XQueryTree(). XQueryTree() returns the window list in proper z-order so you can just loop through all the windows until you find one whose bounding box is under the pointer, XGetWindowAttributes() will give you everything you need to figure out the bounding box. I'm not sure what you would do with shaped windows though.
I haven't work with X11 for a few years so this might be a rather clunky approach but it should work. I also don't have my O'Reilly X11 books anymore, you'll want to get your hands on book one of that series if you're going to work with low level X11 stuff; I think the whole series is available for free online these days.
I haven't programmed X11 for over a decade, so forgive me if I get this wrong.
I believe you can register for mouse movement events on your windows. If you handle such event by storing the window handle in some variable or other, and then handling the event so it doesn't percolate down the tree, then at the time you want to identify the window you can just query the variable.
However this will only work when the mouse is over a window you have registered a suitable event handler for, so you won't know about windows belonging to other applications - unless there is a way to register for events on other people's windows which may be possible.
The advantage over the other answer is that you don't have to traverse the whole tree. The disadvantage is that you need to handle a great many mouse movement events, and it may not work to find other people's windows.
I believe there may also be mouse enter and mouse leave events too which would reduce the amount of processing required.