I am trying to make my program click the button of another program. The part I am having issues with is identifying the handle of the button. This is the code I have so far:
BOOL CALLBACK EnumChildProc(HWND windowHandle, LPARAM lParam)
{
cout << "hwnd_Child = " << windowHandle << endl;
cout<<"WindowId: "<<GetWindowLongPtr(windowHandle, GWLP_ID)<<endl;
return TRUE;
}
HWND windowHandle = FindWindow(NULL, "nameOfProgramWindow");
EnumChildWindows(windowHandle, EnumChildProc, 0);
What is happening so far is that I find the handle of the parent window of the program. With that handle, I use the EnumChildWindows function to go through each of the child windows... and in 1 of those child windows I will have the window which contains 3 buttons, 1 of which is the button I want to press. In the callback function I need to put the GetWindowLongPtr() function to get the ID of the window I am looking for ... there is a problem though...
The problem is that each time I run this program again, the handle and the ID of the window which contains the buttons will change... So I can't use spy++ to get an ID to compare with the ID gotten since The ID changes. I have tested it out even (thats why i have all the "cout" code there);
Question: How do I then identify the window I am looking for in the callback function (and possibly the button I am looking for)?? PLEASE DON'T say spy++ cause the ID and Handle values change every time I open the program
The handle is always going to change each time that the code runs. Windows dynamically assigns handles. Nothing you or anyone else can do about that. It would be more surprising if it didn't change.
And it's no particular conspiracy that the control's ID changes. The only way that stays the same is if it's hard-coded in the original application, most probably via the use of a resource file. But if the programmer dynamically generates the controls at run-time, then there's no reason they would need to use the same ID. Just so long as they keep track of that ID in some kind of data structure if and when they need it.
You may be able to find another property of the button control that is constant—like the caption. But that's certainly not guaranteed. Lots of programs change the caption to reflect the current state.
The application developer is under no obligation to make it easy for another program to mess with the internals of something that does not belong to them.
Have you considered doing this the right way using UI Automation?
Related
In our Program we have a Dialog from a separate dll open to display infomation. I need to close this dialog when our system timer causes the system to lock.
I send information to the dll by registering a system message in both my MainFrm and EditDisplayDll
SYSTEMLOCK = RegisterWindowMessage("SystemLock");
When I sent the message via
::PostMessage(GetActiveWindow()->m_hWnd,SYSTEMLOCK,0,0);
The message correctly sends to my EditDisplayDll and closes the dialog when the system locks; however, if I alt tab while waiting for the timeout and use another program(firefox, outlook, etc.) the message never correctly calls to the EditDisplayDll. The MainFrm and other windows inside of the MainFrm correctly lockout and hide themselves in either case.
I have tried also using HWND_BROADCAST with PostMessage and SendNotifyMessage. I have also tried to use FindWindow() and FindWindowEx() to specifically call the EditDisplayDll.
I cannot use something like GetDlgItem() because my MainFrm.cpp doesn't have access to this dll.
My decision to use GetActiveWindow() was because I believe it looks to windows specific to my program no matter what window I am in as seen in the imagery in Foreground Vs Active window
Finally, my question is, is there a way to call all Windows in my program no matter what program I am currently in or is there another way I could get access to the specific IDD of the EditDisplayDll in order to send the SYSTEMLOCK message to it?
CWnd *cWndED = FindWindow(_T("EditDisplay"),_T("EditDisplay")); HWND
hwnd = (HWND)cWndED;
You should use win32 API ::FindWindow with proper class, window name. And do not cast CWnd pointer to HWND. Your code should look like:
HWND hWnd = ::FindWindow(_T("ProperClass"), _T("ProperNmae"));
if (hWnd != NULL)
{
::PostMessage(hWnd, YOUR_MESSAGE, ....);
}
I will suggest you to find your Dll window class and name using Spy++ and then try to find that using above method. Remember it's always better to use native API for this kind of tasks.
FindWindow is a good solution if you know both, name of the window and the element.
If you want to get the HWND of your window - no element inside the window -, you can pass as first parameter NULL.
::FindWindow(NULL, _T("WindowName"));
Back to your code: If you are lucky your PostMessage does nothing, otherwise the active window may catch your message. Who knows how/if it is handled in the active window ? Use the PostMessage if you have a valid IsWindow(HWND) from FindWindow or FindWindowEx.
In case you want a CWnd from your HWND take a look at this. (The call may be slow)
HWND hWnd = ::FindWindow(_T("ClassName"), _T("WindowName"));
if (hWnd && IsWindow(hWnd))
{
::PostMessage(hWnd, MESSAGE_TO_BE_SEND, lParam_or_Flags);
}
I'm trying to come up with a solution for setting up a notification when focus enters a text field. The end goal in mind is to recreate the type of functionality you see on mobile devices with on screen keyboards.
So far I've been exploring SetWinEventHook with EVENT_OBJECT_FOCUS and GetGUIThreadInfo with GUI_CARETBLINKING.
From the docs:
EVENT_OBJECT_FOCUS
An object has received the keyboard focus. The system sends this event
for the following user interface elements: list-view control, menu
bar, pop-up menu, switch window, tab control, tree view control, and
window object.
GUI_CARETBLINKING The caret's blink state. This bit is set if the
caret is visible.
Using these methods I've come up with this solution:
void TextInputHelper::setupEventHook(FREContext iCtx)
{
ctx = iCtx;
CoInitialize(NULL);
evHook = SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_END, NULL,
handleEventObjectFocus, 0, 0,
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
}
void CALLBACK handleEventObjectFocus(HWINEVENTHOOK hook, DWORD evt, HWND hwnd,
LONG idObj, LONG idChild, DWORD thread, DWORD time)
{
GUITHREADINFO threadInfo;
threadInfo.cbSize = sizeof(GUITHREADINFO);
BOOL result = GetGUIThreadInfo(thread, &threadInfo);
if(threadInfo.flags & GUI_CARETBLINKING)
{
//text field focus
}
}
This does seem to work in some cases but its definitely not reliable. Programs like Notepad an IE seem to work fine but others like Firefox do not. This also will not work for things like text fields on websites because it doesn't look like handleEventObjectFocus will get called.
Does anyone know of another way to approach this problem? I've been searching around and it seems like I might be looking for something in the Accessibility APIs but I haven't been able to dig up to much on it.
Thanks!
edit
To clarify, I'm looking to receive a notification when focus enters any text field. This application is a win32 dll and will never have focus its self.
If you're using standard Windows controls WM_SETFOCUS should do the trick. No need to get fancy with hooking etc.
EDIT: For system wide behavior you can check out SetWindowsHookEx. To catch events system-wide you need to use it from within a DLL. You can use a combination of hooks including one that catches WM_SETFOCUS.
If you're trying to supply an alternative text input method, you should look into "IME" - "Input Method Editor". These are directly supported by the OS.
You can catch the entrance into a text field using the EN_SETFOCUS notification.
WM_FOCUS is for the window itself, not for controls that are in it. Otherwise said, if you want to use WM_FOCUS, you'll have to subclass your EDIT field. It's not necessary here.
EDIT: it wasn't completely clear that you wanted a system-wide behavior. IN that case you have to use an hook (cf. SetWindowsHookEx) as explained in the answer above. Sorry.
Is there way to get the HWND handler of my window?
I'm using win32.
You could call GetActiveWindow to get the active control in your application, then repeatedly call GetParent on the returned handle until it returns NULL. The last valid handle you get should be the handle of your main window.
The easier way as someone else said is to store the returned value from CreateWindow somewhere.
It's probably good to understand why there is no simple way. It all boils down to "which window?". You'll likely have multiple windows visible on your screen, right now. For instance, the taskbar at the bottom of your screen is a window. even your own app typically has more than one. For instance, the "File Save" dialog is a window. Even the simple MessageBox is a window.
So, how do you identify which window you're talking about? The common answer is that you identify them by their HWND. So, to get the position of the "File Save" dialog window, you ask for the position associated with that HWND. Obviously, you can get any property that way, except the HWND itself ! It makes sense to ask the X/Y position of HWND(0x5e21), but it's stupid to ask which HWND belongs to HWND(0x5e21).
Now, it may happen that you have another more-or-less unique property and you want to get the HWND from that. For instance, you may have an X/Y position. In that case, WindowFromPoint(xy) will return the HWND at that position.
But the most common case is that you need to react to a Windows message for your window. In that case, you get the HWND of your window as the first argument of your WindowProc().
So, unless you tell us what unique information you do have, we can't tell you how to find the matching HWND.
Didn't you create your window via CreateWindow() or CreateWindowEx()? The CreateWindowEx() function and the CreateWindow() function both return the HWND of the newly created window.
Also, the operating system passes you the HWND of your window(s) via your window procedure. It's not a function that you call; it's a function that the operating system calls to let your application do any processing that's needed.
In Windows, suppose you have multiple windows (HWNDs) of the same window class open. How do you keep track of the context data in the window procedure so that, for example, window 1 does not get modified when the user tried to type in window 2?
CreateWindow() does not return until after the WndProc() has been called several times, so you can't simply set the resulting HWND to the context data and do a lookup in the WndProc(); you do need to set it in the WndProc().
WndProc() doesn't directly have the context information passed to it except on window creation messages, but unfortunately window creation messages aren't exactly the first messages to be passed to WndProc(). Nay, I find things such as WM_SIZE, WM_NCSIZE, and even some others are passed before I ever see WM_CREATE.
Storing the HWND in a linked list type of storage mechanism would be inefficient with large amounts of windows: each control in a window is simply another type of window and therefore another HWND of which you need to keep track; after a few hundred controls, searching the linked list for the HWND will be a major bottleneck in the program after a few dozen messages are passed to the program in a short amount of time!
From what I hear, some people use SetWindowLong() - but I also hear that some libraries like to use that too to store their own context information separate from the program and that window data collisions can sometimes occur. How can that be avoided?
if I'm understanding you correctly, you want to avoid one window to catch the messages from another. One way to avoid this is to use the solution proposed in this thread, which keeps track of the windows that is created by you and makes sure that the correct windows gets the messages associated to it by storing the pointer for the caller in the GWL_USERDATA .
// ...
m_hWnd = CreateWindowEx(0,"Classname","Title",WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
320,200,NULL,NULL,hInstance, /*the magic pointer*/ this);
// ...
if(uMsg == WM_CREATE)
{
// collected here..
pParent = (CWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
// .. and then stored for later lookup
SetWindowLongPtr(hWnd,GWL_USERDATA,(LONG_PTR)pParent);
}
// ...
You can also catch the WM_NCCREATE message, as proposed by Moo-Juice.
And I don't think you should worry about the messages pre-WM_CREATE, because the window isn't even fully initialized at that point. If you need to set text you do that after the call to CreateWindow(Ex), be it user input or a SendMessagecall.
Whoever creates the window owns that window 100%. If you are the one to call CreateWindow(), then you can use GetWindowLong, knowing that it's yours.
If a library creates the window, however, you can't because it's not yours.
(Aside: Nothing is stopping anyone from stepping on anyone else's toes, but the convention is pretty standard).
If you are using a library that does this, it will generally have some mechanism to associate your own data with a window. Of course, you will need to refer to the documentation for that.
Use Windows properties : SetProp( HWND ,... ) , Getprop( HWND ,... ) and RemoveProp( HWND ,... )
Can't you use WNDCLASS.cbWndExtra to declare whatever private storage your class needs and then it will be allocated by Windows whenever it creates a window of that class.
I need to enumerate all running applications. In particular, all top windows. And for every window I need to add my custom item to the system menu of that window.
How can I accomplish that in C++?
Update.
I would be more than happy to have a solution for Windows, MacOS, and Ubuntu (though, I'm not sure if MacOS and Ubuntu have such thing as 'system menu').
For Windows, another way to get the top-level windows (besides EnumWindows, which uses a callback) is to get the first child of the desktop and then retrieve all its siblings:
HWND wnd = GetWindow(GetDesktopWindow(), GW_CHILD);
while (wnd) {
// handle 'wnd' here
// ...
wnd = GetNextWindow(wnd, GW_HWNDNEXT);
}
As for getting the system menu, use the GetSystemMenu function, with FALSE as the second argument. The GetMenu mentioned in the other answers returns the normal window menu.
Note, however, that while adding a custom menu item to a foreign process's window is easy, responding to the selection of that item is a bit tricky. You'll either have to inject some code to the process in order to be able to subclass the window, or install a global hook (probably a WH_GETMESSAGE or WH_CBT type) to monitor WM_SYSCOMMAND messages.
Once you have another window's top level handle, you may be able to call GetMenu() to retrieve the Window's system menu and then modify it, eg:
HMENU hMenu = GetMenu(hwndNext);
You can use EnumWindows() to enumerate top level Windows.
I don't have a specific answer for the second part of your question, but if you subclass the window, I imagine you can modify the system menu.
EDIT: or do what Chris said: call GetMenu()
Re: the update - please note that not even Microsoft Windows requires windows to have a sytem menu. GetMenu( ) may return 0. You'll need to intercept window creation as well, because each new top window presumably needs it too.
Also, what you propose is rather intrusive to other applications. How are you going to ensure they don't break when you modify their menus? And how are you going to ensure you suppress the messages? In particular, how will you ensure you intercept them before anyone else sees them? To quote Raymond Chen, imagine what happens if two programs would try that.