How to check mouse click position is on required application? - c++

I know the mouse click position using API GetCursorPos and the handle of application (HWND).
How can I check mouse click position is on this application?
My view:
Get the bounding box of application from its handle. (GetWindowRect(hWnd, &rect);)
Check cursor position lies in this bounding box. (PtInRect(&rect, p))
This is not working if windows are overlapping.

As we know the handle of targeted screen handle and click cursor position:
// hWnd : Already known windows handle
GetCursorPos(&p);
HWND hWndFromPoint = WindowFromPoint(p);
// If the handle got from click point is child of the desire window means it is clicked on the desire window itself.
if (IsChild(hWnd, hWndFromPoint))
{
// Do something on Mouse click
}

Related

A message box that never loses focus

A message box created with
MessageBox (NULL, "Text", "Title", MB_ICONINFORMATION | MB_SYSTEMMODAL);
stays on top of other windows, but it loses keyboard focus when the user clicks another window.
How could I create a message box (or an Edit box or a dialog box) that never loses keyboard focus, so if I try to switch to another window using [ALT-TAB] or mouse or any other method, or if another application running in a background opens its own Edit box, the keyboard focus would jump back to my message / Edit box?
The standard MessageBox function doesn't have such an option, so I tried a custom Edit box. I experimented with WM_SETFOCUS, WM_KILLFOCUS, WM_NCACTIVATE, SetForegroundWindow, SetFocus, but had no luck so far. When I open another window, the keyboard focus stubbornly goes to that window.
RegisterHotKey(0,1,MOD_ALT,VK_TAB); //disables alt+tab until message box returns
SetTimer(hwnd,1,100,0); //0.1 sec is enough for message box window creation
MessageBox(0,"Text","Title",MB_ICONINFORMATION|MB_SYSTEMMODAL); //since it's system modal, main message loop will wait for it to return
ClipCursor(0); //frees cursor
UnregisterHotKey(0,1); //enables alt+tab again
Here we use a timer to clip cursor so that user won't be able to click outside of the message box. I left title part of the messagebox outside of the clip area because clicking there negates cursor clipping.
case WM_TIMER:
{
KillTimer(hwnd,1);
RECT rc;
GetWindowRect(FindWindow(0,"Title"),&rc);
rc.top+=22; //title area left out of clip area
ClipCursor(&rc); //user cannot move their mouse outside of the message box
break;
}
This however can't block Ctrl + Alt + Del but does what you ask.

how to set cursor position out off the application window? (c++)

I'm creating an application using C++ to set the cursor position even when the mouse is out off the application window... the Win32 library has the SetCursorPos function which according to the documentation
A window should move the cursor only when the cursor is in the window's client area
however I want to move the cursor outside the window : EVEN when the window IS HIDDEN...
I want it to be more like a mouse driver : windows reads the cursor position from it...
it seems that although the documentation says :
A window should move the cursor only when the cursor is in the window's client area
it can control the mouse even when the window is HIDDEN

Dragging the console window with ReadConsoleInput()

As you can see from the code snippet below, I've implemented a way to drag the Windows command prompt by its client area.
The problem with this code is that if the user follows these steps:
Unfocus console window
Focus console window by clicking and dragging it (without releasing)
Drag the window so that the cursor escapes window area (this can mean moving the cursor too quickly, or out of the set bounds (second monitor), or over the taskbar/other always-on-top window)
The console window will stop following the cursor, until it's moved to be inside the window again.
The fact that this does not happen when the console window is already in-focus at step 1, is what's really weird to me. I've tried debugging this for so many hours now, I just can't do it anymore. I'd appreciate any help regarding this.
// Continuously read input
while(ReadConsoleInput(hIn, &ir, 1, &nr))
{
switch(ir.EventType)
{
// Left mouse button down that either focuses or unfocuses console window
case FOCUS_EVENT:
// Left mouse button down that focuses console window
if(ir.Event.FocusEvent.bSetFocus)
{
GetCursorPos(&firstPos);
ScreenToClient(hWnd, &firstPos);
}
break;
case MOUSE_EVENT:
// Mouse did something inside console window
switch(ir.Event.MouseEvent.dwButtonState)
{
// Left mouse button down or up
case FROM_LEFT_1ST_BUTTON_PRESSED:
// Left mouse down or up, no drag
if(!ir.Event.MouseEvent.dwEventFlags)
{
GetCursorPos(&firstPos);
ScreenToClient(hWnd, &firstPos);
}
// Left button down, and mouse move. -> drag
if(ir.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
{
GetCursorPos(&currentRelativeToScreen);
// Calculate window position while dragging
// |
// v
if(currentRelativeToScreen.x - firstPos.x > scrnSz.right - ca.right)
wndPos.X = scrnSz.right - ca.right;
else if(currentRelativeToScreen.x - firstPos.x < 0)
wndPos.X = 0;
else
wndPos.X = currentRelativeToScreen.x - firstPos.x;
if(currentRelativeToScreen.y - firstPos.y > scrnSz.bottom - ca.bottom)
wndPos.Y = scrnSz.bottom - ca.bottom;
else if(currentRelativeToScreen.y - firstPos.y < 0)
wndPos.Y = 0;
else
wndPos.Y = currentRelativeToScreen.y - firstPos.y;
// End window position calculations
SetWindowPos(hWnd, 0, wndPos.X, wndPos.Y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
break;
default:
break;
}
break;
default:
break;
}
Drag the window so that the cursor escapes window area [...] The console window will stop following the cursor, until it's moved to be inside the window again.
This is the expected behavior, as documented at https://msdn.microsoft.com/en-us/library/windows/desktop/ms684239.aspx (emphasis added).
Mouse events are generated whenever the user moves the mouse, or presses or releases one of the mouse buttons. Mouse events are placed in a console's input buffer only when the console group has the keyboard focus and the cursor is within the borders of the console's window.
[ EDIT] To answer the followup comment about this.
this does not happen when the console window is already in-focus at step 1
Though not obvious from the official documentation, the console window appears to capture the mouse when clicked (and thus track it even when moved outside the console window) only if it already had the focus at the time of the click. For a console window out of focus, the 1st click gives it the focus (without globally capturing the mouse, so it only receives MOUSE_MOVE notifications while the cursor is within its client area), while the 2nd click enters exclusive capture mode (and receives all MOUSE_MOVE notifications regardless of cursor position).
This can be verified with a standard console window set to quick-edit mode. If the window has the input focus, then click-and-drag selects text in the console, even if the mouse is moved outside the window. However, if the window does not have the focus. the 1st click just gives it the focus, but does not enter any capture mode and dragging does not select any text.
on mouse move do:
if(button==leftButton){
ReleaseCapture();
SenMessage(hWnd,WM_NCLBUTTON_DOWN,HTCAPTION,lParam);
}

MFC Unclickable Button (Running away from cursor on MouseMove)

How would i make a button that will change it's position on MouseMove Event if the cursor is close enough to the center of the button in MFC ?
WM_MOUSEMOVE is not delivered to the button if the cursor is not over it (and is not captured, but you don't want that). So you have to process WM_MOUSEMOVE in the parent dialog. If you want your button to be a self-contained control, you have to subclass the parent window upon button creation.
Subclassing, in this context, means:
- you retrieve and store the parent's window proc address with GetParent()->GetWindowLong(GWL_WNDPROC)
- you set it to your procedure with SetWindowLong()
- in the procedure, you call the parent's previous window proc, after handling WM_MOUSEMOVE the way you want.
The WM_MOUSEMOVE coordinates will be relative to the screen, but you'll probably want to track the button position relative to the window that contains it. Use the ScreenToClient method on the parent window to convert, then you can compare the coordinates to see if it's close. Then use MoveWindow to move the button.
If you track the mouse cursor position you can determine when the cursor gets close to or enters the button window rect. You can then use the SetWindowPos() function to reposition the button window in the parent window client area.

How to get the window position and update to other windows?

I have 2 dialog boxes in which I will display 1 dialogbox at a time..If I click NEXT in the first dialog box,I will hide the first dialog box and display the second dialog and vice versa...Now say If I move the dialog box after clicking NEXT in the first dialog..and when I click BACK(in the second dialog) ...it goes back to its previous position(to diaplay the first dialog box)..so I have decided to get the current window's position and update to the other window position so that it doesnt move even If I click next/back..I am not sure how to get the windows position and update to other..please help me if you guys know about this..
You can create an OnMove handler for WM_MOVE messages to detect when your window moves. In the handler, you can either move the other window directly with MoveWindow, or you can send a private message to the window (something in the WM_APP range would be best) and let it move itself. Use GetWindowRect to get the width and height to pass to MoveWindow.