How to send double click on keyboard focused object from c++? - c++

the question is how to send double click to object who is already focused by keyboard? For example let's say that my mouse is on bottom right position on screen, if i open explorer by pressing WIN+E, and than press SPACE -> i will get focus to disk (c:\ disk for example), so i want to know on what coordinate is that focus that can send double click to it. Is there any function in c++ that do it for us?

mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(10);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
Sleep(10);
// Click Two
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(10);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
From google:
http://groups.google.com/group/borland.public.delphi.winapi/browse_thread/thread/f1380942baf5c1ae?pli=1
http://msdn.microsoft.com/en-us/library/ms646260(v=vs.85).aspx

I'm not sure that is possible - in your example, the Explorer window is highlighting the drive object - you need some way to obtain the coordinates of the object with in the explorer window (which you do not control, right?)
It's not hard to send a double-click to a window - but what is happening within the window is difficult to determine.

You can find currently focused window with GetFocus function. But there's in general no way to find where to send a double click event. You can easily find out the dimensions and the screen coordinates of any window with GetWindowRect function. You can send that event to the center of the window or to any of its corner or anywhere else, and in some cases that would suffice.
In your example you would need to figure out where the selected element is located on the screen and that element is not a window, its state is maintained by the parent window and generally there's no way to get that information.

Check out MSAA or UIAutomation on MSDN; these are APIs that allow you to access element information below the HWND level. They are designed for test tools and accessibility tools that need this information. For example, a screen magnifier can use these APIs to follow the keyboard focus, get the location of the current element, and determine the correct coordinates to zoom in on.
MSAA/UIA are supported widely within Windows - all the system controls (as used in explorer) support it, as does the content of IE, Firefox, and some other apps.
You can use the inspect.exe tool that's part of the Windows SDK to play with this functionality.
Note that before clicking on the target, you should check that the element at that point is the element you expect it to be: if there's some other dialog in the way, the click will go to that element instead.

Related

Is it possible to set the Window (x, y) Position in RAD Studio 10 c++?

I'm developing an application and it looks as if my Form object doesn't have anything for me to specify its exact coordinates.
I have a label at the top acting as a titlebar, in c# I could use a combination of my mouse coordinates and window coordinates to make the window move with the mouse when the user clicks and drags. However, in c++ (along side RAD studio) there doesn't appear to be anything online I can use as reference to pull this off.
I've tried windows api with:
SetWindowPos(this->GetOwnerWindow(), HWND_TOPMOST, 5,5,5,5, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
There's things like window position, but that only accepts integers or vars like "poScreenCenter".
Any insight on how this could be possible would be great.
TForm (and all UI controls in general) have Left and Top (and Width and Height) properties.
You can use the Label's OnMouse(Down|Up) events to set/unset a bool, and then have the Label's OnMouseMove event reposition the Form if the bool is set.
A simpler and more efficient solution is to have the OnMouseDown event send an undocumented WM_COMMAND(SC_DRAGMOVE) message to the Form's HWND and let the OS handle the rest for you. See Moving a caption-less window by using a "drag area" (written for Delphi, but it applies to C++Builder too, since they use the same VCL framework).

What is the difference of MouseInputs and KeyInputs (To get the window in the foreground)

Good day everybody.
It is so that one with SendInputs to send keys only has to call SetForegroundWindow() in order to bring the window into the foreground. This also works without problems.
Now it is so that one could think that with the mouse inputs the same procedure can be applied. But this was not possible. First you had to use the function AttachThreadInput() to get the window really in the foreground.
It is very confusing that it works with keys simply but with the mouse so cumbersome to be done. Can someone explain to me briefly why this is so?
Sorry for the title and the bad english, unfortunately, no other words have occurred to me.
Since it is too much code, I simply show the relevant for my question.
Keys:
if(SetForegroundWindow(window[id]))
{
//SENDINPUT for key, works without any problems. (Not with Mouse)
}
Mouse:
AttachThreadInput(dwCurID, dwMyID, TRUE);
SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
SetWindowPos(window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
SetForegroundWindow(window);
AttachThreadInput(dwCurID, dwMyID, FALSE);
//The Window is now on foreground, now use SendInput for Mouse. This way works
So I wonder really why not both works in the way of the key example. So the reason I know since the window is not really in the foreground and this is necessary for the MouseInputs. One might think that it would also be necessary for the Keyevents. Hence my confusion.
I wish you happy day!
If I understand the question correctly ... Yes, the keyboard and mouse input models are different.
But I think the real issue is that calling SetForegroundWindow on the window of another application is complicated. Windows has a long list of rules of when you can and cannot set the foreground window. (The intent is to make it hard for programs to push their windows in the user's face when the user wants to do something else.) What seems to work when you're testing might not actually work reliably in real life. For example, some of the rules depend on whether the current foreground window is owned by a process attached to a debugger. My guess is that you got lucky when you tested the keyboard case and you found a way around the rules when you worked on the mouse case.
Keyboard input is directed to the window with the keyboard focus. The window with keyboard focus is either the foreground window or a child of the foreground window. So to direct keyboard messages with SendInput to a particular application, you only have to make sure it has focus, which you can do by bringing its window to the foreground.
If you succeed, then the window you just brought to the foreground will make sure the window focus is set appropriate (e.g., by calling SetFocus on one of its children). If you were to try to call SetFocus yourself, on a window that belonged to another thread or process, you would first have to use AttachThreadInput just as you've done in the case for the mouse. (This is explained in SetFocus.)
Mouse input is (generally) directed to the window under the mouse, even if that window is not the foreground window. The big exception is when a window has "captured" the mouse, then all mouse input goes to that window, even if the mouse is over a different window. But the other exception is also the mouse scroll wheel messages, which seem to follow the window with keyboard focus.
I'm not entirely sure why (or whether) it's important to set the foreground window to send mouse input, unless it's because you're trying to make sure it gets the mouse scroll wheel messages.

How to set window top of any topmost window?

I prefer set Taskbar to hide, but still want show clock all the time. I make a small clock (80x41px) lay at bottom-right corner of screen. I make it Topmost [edit: with Timer]:
SetWindowPos(hwnd, HWND_TOPMOST, r.right - width, r.bottom - height, 0, 0, SWP_NOSIZE);
// r is my window's rect
When I click to TaskBar, my clock still on top of it. But when I play some fullscreen game it hide my clock. May be they use a special method.
My question is there is any way to show my window on top of every top-most window, even active top-most window? I don't need my app get keyboard or mouse input, just lay there to display time.
I know my question is quite specific as I write this clock for myself. I searched google but don't find any web pages can solve this (this question ask the same, but it want to get mouse event, and the answer say no, but I hope a window that doesn't need input maybe a special case).
Any help would be appreciated!
Edit
Incase impossible, How about draw a rectangle on top of screen? As I don't need get input, this maybe a replace solution. Is that possible?
It's not very elegant, but I've solved this before by constantly setting the window to HWND_TOPMOST on a one-second timer.
Is it within the own process?
As a general rule, a process can only expect to set the foreground window if that process is already the foreground process. (Microsoft documents the restrictions in the SetForegroundWindow() MSDN entry.)

Create a window using the WS_EX_NOACTIVATE flag ,but it can't be dragged until I release the mouse

I have created a window using the WS_EX_NOACTIVATE flag and it works great as far as not taking focus when you click the window. However when I drag the window or try to resize it, it doesn't redraw the window as your are moving and resizing it, only at the very end once you release the mouse button. Is there a way around this? I would like to see the window as I am resizing it. I have searched many documents, but I still don't find the resolution...
If you need a window that doesn't take focus when clicked, but can still be interacted with, you need to handle the WM_MOUSEACTIVATE, and return MA_NOACTIVATE.
Additional information and fully working sample code has been published by Raymond Chen. See How can I have a window that rejects activation but still receives pointer input?
It's a Windows bug. You need to call SetWindowPos(hwnd, 0, x, y, width, height, 0) on WM_MOVING. The coordinates to set are given to you in lParam which is a RECT*.
Note that doing this will activate the owned window and deactivate the owner, which is not what you want (and SWP_NOACTIVATE has no effect either).
To avoid that, you need to set WS_CHILD on the owned window. But set it after you created the window, via SetWindowLong(), otherwise your owned window will get clipped, like any child window.
And, as you probably already figured out, this only works for windows with WS_EX_TOOLWINDOW ex style. I wasn't able to make the owned window stay deactivated with any other style combination that doesn't include WS_EX_TOOLWINDOW.
That's winapi for you :(

Resizing Controls in MFC

I am writing a program which has two panes (via CSplitter), however I am having problems figuring out out to resize the controls in each frame. For simplicity, can someone tell me how I would do it for a basic frame with a single CEdit control?
I'm fairly sure it is to do with the CEdit::OnSize() function... But I'm not really getting anywhere...
Thanks! :)
A window receives WM_SIZE message (which is processed by OnSize handler in MFC) immediately after it was resized, so CEdit::OnSize is not what you are looking for.
You should add OnSize handler in your frame class and inside this handler as Rob pointed out you'll get width and height of the client area of your frame, then you should add the code which adjusts size and position of your control.
Something like this
void MyFrame::OnSize(UINT nType, int w, int h)
{
// w and h parameters are new width and height of your frame
// suppose you have member variable CEdit myEdit which you need to resize/move
myEdit.MoveWindow(w/5, h/5, w/2, h/2);
}
When your frame receives an OnSize message it will give you the new width and height - you can simply call the CEdit SetWindowPos method passing it these values.
Assume CMyPane is your splitter pane and it contains a CEdit you created in OnCreate called m_wndEdit:
void CMyPane::OnSize(UINT nType, int cx, int cy)
{
m_wndEdit.SetWindowPos(NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
}
GetDlgItem(IDC_your_slidebar)->SetWindowPos(...) // actually you can move ,resize...etc
SetWindowPos is a little heavy duty for this purpose. MoveWindow has just what is needed.
Others have pointed out that WM_SIZE is the message you should handle and resize the child controls at that point. WM_SIZE is sent after the resize has finished.
You might also want to handle the WM_SIZING message which gets sent while the resize is in progress. This will let you actively resize the child windows while the user is still dragging the mouse. Its not strictly necessary to handle WM_SIZING but it can provide a better user experience.
I use CResize class from CodeGuru to resize all controls automatically. You tell how you want each control to be resized and it does the job for you.
The resize paradigm is to specify how much each side of a control will move when the dialog is resized.
SetResize(IDC_EDIT1, 0, 0, 0.5, 1);
SetResize(IDC_EDIT2, 0.5, 0, 1, 1);
Very handy when you have a large number of dialog controls.
Source code
When it comes to the window size changes, there are three window messages you may be interested in: ON_WM_SIZE(), ON_WM_SIZING(), and ON_WM_GETMINMAXINFO().
As the official docs says:
ON_WM_SIZE whose message handler is ::OnSize() is triggered after the size of the CWnd has changed;
ON_WM_SIZING whose message handler is ::OnSizing() is triggered when the size of the client area of the clipbord-viewer window has changed;
ON_WM_GETMINMAXINFO whose message handler is ::OnGetMinMaxInfo() is triggered whenever the window needs to know the maximized position or dimensions , or the minimum or maximum tracking size.
If you want to restrict the size of the cwnd to some range, you may refer to message ON_WM_GETMINMAXINFO; and if you want to retrieve the size changes in real time, you may refer to the other two messages.
It is better to use the Dynamic Layout capabilities of each control at the Property section.
Let's say you want to have a specific control, like a heading, always at the center of the view/dialog, then you just choose the properties of Dynamic Layout of the control, Moving Type as Horizontal and Moving X as 50 but you keep sizing to None. This way, when you resize the view, the header remains always at the center. You have to keep in mind that the minimum of the resizing/moving is the size/position of the control within the dialog/view, when you designed it at the Resource View.
This way, you save the burden of geometry and the transformations.