Close a child window

Hello,

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.

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>     //for std::wcout & std::endl
#include <string>       //for std::wstring
using namespace 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

        int const 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
        int const 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;
}


What Am I doing wrong?

-ScottA
What Am I doing wrong?


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.



Windows Error Codes: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
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.

-ScottA
Under the Remarks section of the DestroyWindow() page
A thread cannot use DestroyWindow to destroy a window created by a different thread.


DestoryWindow(): http://msdn.microsoft.com/en-us/library/windows/desktop/ms632682(v=vs.85).aspx

Which is why you are getting "Access Denied".
Ouch!
So there's no way to close a window like this?
No way at all?

BTW- Thank you for helping

-ScottA
I don;t think I've ever actually tried this. I'm sure you can speghetti code together something using "SetActiveWindow()" and "SendInput()"

SetActiveWindow(): http://msdn.microsoft.com/en-us/library/windows/desktop/ms646311(v=vs.85).aspx

SendInput(): http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx
In this particular case, you can use

PostMessage(hwnd, WM_KEYDOWN, VK_ESCAPE, 0);

(as the escape key closes the Find dialog)

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.

This also works for Notepad's Find dialog.

PostMessage(hwnd, WM_COMMAND, (WPARAM)MAKELONG(IDCANCEL, BN_CLICKED), NULL);

But the final NULL should really be the HWND of the button.

Andy
Last edited on
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.

Would that be any easier?

-ScottA
Last edited on
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!

Andy
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. :/

-ScottA
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...)

Andy
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.

-ScottA
@ 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.
No pop-ups.
The window just sits there.

-ScottA
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.

1: http://technet.microsoft.com/en-us/sysinternals/bb545021.aspx
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.


-ScottA
Hello again.
I found out that the windows that I want to close do have a hotkey that will close them.
The hotkey is Shift+W.

Can anyone tell me what the values would be for this key combo?
Andy posted the code for the Esc key. But I need the one for Shift+W.

PostMessage(hwnd, WM_COMMAND, (WPARAM)MAKELONG(IDCANCEL, BN_CLICKED), NULL);


-ScottA
Last edited on
I found the code I needed.
And was successful in closing the windows the way I wanted.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
		INPUT ip;
		ip.type = INPUT_KEYBOARD;
		ip.ki.wScan = 0;
		ip.ki.time = 0;
		ip.ki.dwExtraInfo = 0;

		//Press the "Shift" key
		ip.ki.wVk = VK_SHIFT;
		ip.ki.dwFlags = 0; // 0 for key press
		SendInput(1, &ip, sizeof(INPUT));
 
		//Press the "W" key
		ip.ki.wVk = 'W';
		ip.ki.dwFlags = 0; // 0 for key press
		SendInput(1, &ip, sizeof(INPUT));
 
		//Release the "W" key
		ip.ki.wVk = 'W';
		ip.ki.dwFlags = KEYEVENTF_KEYUP;
		SendInput(1, &ip, sizeof(INPUT));
 
		//Release the "Shift" key
		ip.ki.wVk = VK_SHIFT;
		ip.ki.dwFlags = KEYEVENTF_KEYUP;
		SendInput(1, &ip, sizeof(INPUT));



-ScottA
Topic archived. No new replies allowed.