PTVISIBLE always returns true when relevant point obscured by another window - windows

I am trying to ascertain whether the mouse cursor is over a specific window and whether there are any other windows obscuring that window at that specific point. The relevant point is obtained in screen coordinates by way of a mouse hook. I then use the ptVisible function to determine this. My code is:
DC := GetDC(wnd);
try
Result := PtVisible(DC, pt.X, pt.Y);
finally
ReleaseDC(wnd, DC);
end;
This always returns false even when there is nothing obscuring the window represented by the wnd handle.
I found very little on the web as to proper use of ptVisible. Can anyone advise if I am using it incorrectly?

You are not using it correctly. From the docs page, PtVisible() "determines whether the specified point is within the clipping region of a device context." This has nothing to do with mouse location or location of a pixel within a window. This has specific uses to check whether the point is within the clipping region of a graphics device context.
If you want to check whether the mouse is within a certain window, you might want to try checking if your mouse coordinate is within GetWindowRect(). And then to check whether or not any windows overlap, you'd want to EnumWindows() and then IntersectRect()

Related

How to get absolute mouse position with WM_INPUT set up?

I'm working on Direct3D Game engine, I got my mouse and keyboard setup from my previous project, but recently ran into problem:
The thing is, my engine is for a shooter/slasher game, so it requires a direct input, which was set in previous project using RAWMOUSE and WM_INPUT message parsing.
case WM_INPUT:
if (wParam == RIM_INPUT)
{
dword dwSize = 48;
RAWINPUT raw;
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &raw, &dwSize,
sizeof(RAWINPUTHEADER)) != dwSize)
OutputDebugString(TEXT("GetRawInputData does not return correct size !\n"));
if (raw.header.dwType == RIM_TYPEMOUSE)
{
this->mouse.TranslateMouseInput(raw.data.mouse);
}
break;
}
Problem is, that code returns only relative movement of mouse, it's useful in setting up a camera lookup, but when it comes to menu or basic GUI, which are controlled by mouse (buttons etc...) things go bad: GUI and other controls require cursor position to be calculated relative to client rectangle.
Closest thing I found to answer in WinAPI is GetCursorPos() combined with GetWindowRect(), but if window has a title bar relative offset of it does not count and (0,0) coordinate is set at the top of the title bar, but not on the client region.
How do I solve the issue without losing a relative mouse movement?
-Should I try parsing WM_MOUSEMOVE messages with WM_INPUT?
I've looked for a popular input solution for game engines, but didn't find any particular one.
Additional Info:
Mouse.cpp file
Mouse.h
Your best option when you need absolute mouse position is to use standard WM_MOUSE* messages, and only use WM_INPUT for relative mouse position. Typically you have a mode transition when bringing up a UI or some other aspect for getting in/out of relative 'look' mode.
WM_INPUT provides only relative information in most cases, and if you attempt to emulate absolute yourself you will be missing a lot of pointer ballistics that makes it feel really off.
Note that if you want your game to support use via remote desktop (typically for testing), then you need to deal with emulating relative input from absolute position because in the case of a virtual desktop you never get relative, only absolute, from WM_INPUT. This is indicated by MOUSE_VIRTUAL_DESKTOP.
You may want to take a look at the Mouse class implementation in DirectX Tool Kit.

Detecting when another application is clipping the mouse cursor?

What I am trying to do is to determine when another application is clipping the mouse cursor. I am using SetWindowsHookEx(WH_MOUSE_LL,...) to detect mouse movement. I could test the mouse position against its previous position every time my WH_MOUSE_LL callback is called, but this wont work if any of the sides of the application's window are touching the edge of the desktop as windows itself is also clipping the cursor.
More specifically, I am writing a program that overrides the default mapping of the virtual desktop when there are multiple monitors. I have everything working except in the case where a fullscreen application is running and constraining the mouse to its window. I cannot distinguish between the cursor actually trying to exit the side of the screen or if the current in-focus application is clipping it.
Is it possible to tell weather the in-focus app is clipping the mouse or maybe to prevent windows itself from constraining the cursor within the desktop, allowing the aforementioned check to work? Is there some other solution that I am missing?
Thank you.
Ah, I'm an idiot. GetClipCursor(RECT*) will do the trick.

How to track mouse movements without limiting it to screen size?

I'm using WM_MOUSEMOVE to get changes in mouse position. When simulating "knobs" for example it's desired to let the user go up/down with mouse without any limits. In this cases I hide cursor and use SetCursorPos to change its position every time user moves with it and detect just the difference from the original position.
Unfortunately it doesn't seem to work - if I set the mouse position, it sometimes works, but sometimes is one or more pixels away, which is just wrong. And even bigger trouble is that after the call another WM_MOUSEMOVE seems to be delivered, which unfortunately does the same thing as it wants to move the cursor back to the original position again. So it ends up in an infinite cycle or settings mouse position and receiving messages until the user releases the mouse button.
What's the correct approach or what's the problem?
The raw input system can do this - it lets you register for raw mouse input that isn't clipped or confined to the screen boundaries.
Broadly speaking, you register for raw input using RegisterRawInputDevices(). Your window will then receive WM_INPUT messages, which you process using the GetRawInputData() function.
See Using Raw Input for an example.
I hide cursor and use SetCursorPos to change its position every time user moves with it and detect just the difference from the original position.
This is just plain wrong. Instead, use SetCapture() to capture the mouse. All movements will be reported as WM_MOUSEMOVE messages with coordinates that are relative to the specified window, even if the mouse is outside of that window, until you release the capture.
Asking the user to move the mouse continuously, even after the cursor hit the screen limit is a very bad idea in terms of User Interface, IMHO.
Some games have another approach: when the mouse hit the "limit", the game enter a special mode: things appears to function exactly as if the mouse was moving, even if the user don't move it. When the user wants to exit that mode, he just has to move the mouse of the limit.
Doing so requires a timer, armed when the mouse hit some limit, executing code periodically as if the mouse was moving. The timer is stopped when a real mouse movement makes it leaves the limit.
Ok folks, so I found a solution simple enough:
The main problem is that SetCursorPos may not set the coordinates accurately, I guess it's because of some high resolution processing, nevertheless it's probably a bug. Anyway if SetCursorPos doesn't set the coordinates correctly (but +-1 in x and/or y) it also sends WM_MOUSEMOVE to the target window. As a result the window performs the exact same operation as before and this goes on and on.
So the solution is to remove all WM_MOUSEMOVE messages right after SetCursorPos:
MSG msg;
while (::PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) { };
Then retrieving the current mouse cursor pos using ::GetCursorPos .
It's ugly but seems to fix the problem. It basically seems that in some position of the mouse, the system always adds or subtracts 1 in either coordinate, so this way you let system do the weird stuff and use the new coordinates without trying to persuade system that your coordinates are the correct ones :).

Programmatically find blink cursor position in windows c++?

How to find out blink cursor position in windows, from c++? In many cases I need send button click on the position of the blinking cursor, but I didn't find any important function which will take care of that.
OS win 7(64), c++
It is called "caret", cursor is the mouse pointer. You use GetCaretPos() to get its position. But the returned position is relative to the client area of the window that owns the caret. Which probably means that you need to find that window first, use GetForegroundWindow() for that. And don't send button click messages, they are posted so use PostMessage().
Avoid all of this by just using SendInput().
Note that UIPI (the user interface component of UAC) prevents you from poking stuff into a window owned by an elevated process.
GetGUIThreadInfo() is probably your best bet; pass it with idThread = 0 to get the info from the currently active thread, and then check the rcCaret member of the returned GUITHREADINFO structure. You'll then need to use ClientToScreen() with the hwndCaret value to convert client-relative coordinates to screen coordinates.
Note that this only works for apps that use the Win32 caret functions - specifically SetCaretPos(). If an app draws its own caret without using these, you may not get anything meaningful back. (Some apps, like Word, draw their own caret, but still call SetCaretPos so that accessibility aids that need to track the caret can use this technique.)
The rectangle you get back can sometimes be wider than the actual caret. When a bitmap is used for the caret, as is the case for Right-To-Left or Left-To-Right carets that have a little 'flag' attached to the top, you'll get back a rectangle that's a bit wider than the actual caret area, and may need to adjust or otherwise figure out where within this area the actual caret bar is - it may or may not be in the exact middle. Looks like for Notepad++ you should be fine, though.

Painting data from device context

I've just got a fresh device context (DC):
GetDC(someForeignHwnd)
Most normal people now want to paint on this. I don't. I want to display the context in my own program. Or duplicate, I wouldn't even mind the window I stole the context from beeing empty.
In my case, I want it in a TPanel in Delphi, but anything else helping me understanding goes.
Afterwards, I'll probably find the DC invalid by the time I get to display it.
My main problem is: Showing the content of another window in my own. But that isn't important. First of all, I want to know how these DC are of any use. Can I do something like the following?
Canvas.Draw(0, 0, MyNewDC);
The answer can be in Java, C, or Pascal. Is it just not possible or just a stupid idea?
While it's possible to use a device context that you retrieve via GetDC() as the SOURCE for BitBlt(), etc., you will likely not get the results that you're looking for. When you call GetDC() for a specific window, Windows essentially returns a device context for the screen, but with a clipping region set to exclude any portions of the screen where the window is not visible. For example, if there happens to be another window overlapping the source window, the portion of the source window that is covered is clipped from the device context. Therefore, you can only "retrieve" the bits that are actually visible.
You may have better luck sending a WM_PRINT or WM_PRINTCLIENT message to the window. However, not all windows respond to these messages, so this isn't a universal solution.

Resources