I'm having trouble closing child windows.
I'm sure I'm missing something really simple. But I can't see what I'm doing wrong.
I'm trying to close the "Find" window when a Notepad file is open.
#include <iostream> //for std::wcout & std::endl
#include <string> //for std::wstring
usingnamespace std;
#define UNICODE
#include <windows.h>
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
{
//The child window we want to close is the "Find" window
hwnd = FindWindow(0, L"Find");
if(!hwnd) cout<< "!No child window with that name found" <<endl;
if(hwnd)
{
SetForegroundWindow(hwnd); //Activate this child window
cout << "hwnd_Child_ID = " << hwnd << endl; //Print the child window's handle ID
intconst bufferSize = 1 + GetWindowTextLength( hwnd ); //Get the number of chars in the window's name
wstring title( bufferSize, '\0' ); //Create a new string using this size value
intconst nChars = GetWindowText( hwnd, &title[0], bufferSize ); //Read the chars and put them in this variable
title.resize( nChars ); //Update the title variable with the values of each char
wcout << "'" << title << "'" << endl; //Print the title of the child window
//At this point I have successfully found the Find window
//And the window handle ID is correct(checked with Spy++)
DestroyWindow(hwnd); //<----Why does this not close the window?
}
return TRUE; //If return is FALSE it stops the recursion
}
int main()
{
//Finds any Notepad file window that's open
HWND const window = FindWindow(L"NotePad", 0);
if( window == FALSE )
{
cout << "!Didn't find the window." << endl;
}
else
{
//Now lets find a specific child window and close it by using a call back procedure
EnumChildWindows(window, EnumChildProc, 0);
}
system("pause");
return 0;
}
You're not checking the result of "DestroyWindow()" then calling "GetLastError()" if it fails. You should see a '5' which is an Access Denied error when attempting this.
I don't understand. How can it be an Access Denied problem when other window functions work properly on it?
Example:
ShowWindow(hwnd, SW_MINIMIZE); //works fine
As do all the other window manipulation functions.
I can move, scale, minimize, maximize the Find window with my code.
But for some reason. I cannot close the window.
The only function that does not work is the DestroyWindow() function. And I'm baffled why this is happening.
But I've only been coding this windows stuff for a couple of days.
There's tons of examples on the web for creating your own window and closing it. But I can't find any examples of closing a window that another program has opened.
Of course, this approach needs your app to understand its target a bit (what the shortcut keys are, etc.) And the LPARAM value is prob not setup correctly for the general case; but this approach is prob. OK for testing purposes in a controlled environment.
Thanks Andy.
But I have to be able to close the window without using a hotkey so I can use it on other programs besides Notepad.
I'm rather stunned at how hard it is to find any example code for doing this kind of thing.
I never would have guessed that closing a window like this would be such a hard thing to do.
I'm a bit shocked!
If it helps at all. Or makes it simpler.
What about closing the topmost window? Or maybe the active window?
I can put SetActiveWindow() in the code I posted to make the child window active.
Well, Escape is a standard hotkey, so it will work with most dialog boxes. So it's good for more than just Notepad.
I hope you weren't shocked that an app it's allowed to kill another apps window. I'd be shocked if that was allowed!!
I am not aware of a simple approach that works for all cases. It is existed I'm sure it would be well known; as it stands, GUI testing can a bit of a pain. You're not supposed to force an app to do something; you have to ask it nicely!
I can see where it could be a security issue to let another app close another app's window. But I have no other choice but to force them to close.
I make plugins for a program called Cinema4D. And they don't have any API hooks for closing the child windows in their SDK. So the only way I can do this is by closing the windows using the OS itself.
Not the best solution. But it's the only way.
I can minimize, scale, and move them around. But the one thing that I really, really need to do is close them. And that's the one thing that I can't figure out how to do.
Funny how it always seems to work out like that. :/
If you're targetting a specific app (i.e. Cinema4D) then you prob don't need a general solution. All being well, what closes one of their child windows will close all the others.
Out of interest, why does a plugin need to close a window? It's usually it the user's perogative to decide which windows are opened and closed, so I'm curious about when the capability is needed (in a general sense...)
There's several reasons why the user wants a window to automatically close.
One reason would be that the plugin executes a few things and then starts rendering the scene. Which makes a window pop up.
The user might want that window to automatically close when it's finished rendering.
Not being able to close the child windows (not the main app) with code is something that plugin developers keep asking for.
The software company says they can't add window handles to their SDK because the software is cross platform(MAC/PC). And closing windows is an OS specific task.
So far I've figured out how to make a plugin change (min. move. etc...) a specific child window based on it's name. Which is handy, and something I'm going to pass on to the other PC based developers to explore.
But the holy grail that the plugin devs. want is closing these child windows.
That one I still can't solve. And it's the most important one.
@ OP: If you're really up for this then want you want is referred to as a 'shim'. This can be done several ways but you'll need to know what function calls to intercept and handle; usually that means running the binary through a debugger like Olly Dbg or IDA Pro. I'm not to familiar with this program specifically, when the animation ends does the window just sit there? Or does it pop-up with a message box of some kind (like "Would you like to replay or quit?")? If there is a pop-up then you just have to replace that function call with a 'return', if not then this is where I start getting in over my head.
Then this might be out of my league. Does the rendering window start up it's own thread (use Process Explorer from Sysinternals1)? That would be much easier to work with. You'd still need some way to know when the animation is finished playing though and that is something the dev team needs to provide.
I'm fairly certain it does use a new thread when rendering.
But my rendering example is only one example. And most of the time I would want to close a window that does not have it's own thread.