How to get HWND of one or more hidden windows? - c

I need get the HANDLE or HWND of a hidden window to terminate it with EndTask((HWND)hProc,TRUE,TRUE);. I used all ways listed below but none of them work. When I manually set a handle to a hidden window with spy++, this worked correctly.
NOTE: This window not show with ShowWindow() and then use FindWindow(). How does spy++ get and show these handles?
I used:
FindProcessId
and then
hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, id);
or
hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
Create process not work: access denied.
FindWindow() does not work for this hidden window.
How can I get the handle for the hidden window so I can terminate the process?

FindWindow will search any type of Windows and it does not matter it's hidden or not.
Maybe your problem with FindWindow is that, window you were looking for, was child of another one and for this reason you are unable to find that.
So you should use FindWindowEx and search into children's windows.

Related

Unparented Window cant have HMENU id set?

I have a custom window class (that I created with RegisterClassEx()). If I create a window instance of this class and set its HMENU property the CreateWindowEx() function fails.
Why can I not set this kind of window's id/HMENU id?
// hwnd = NULL
hwnd = CreateWindowEx(0, WND_CLASS_NAME.c_str(), wndTitle.c_str(), wndFlags,
wndDimensions.left, wndDimensions.top, wndDimensions.right, wndDimensions.bottom,
NULL, (HMENU)50001, hinstance, NULL);
// hwnd is valid
hwnd = CreateWindowEx(0, WND_CLASS_NAME.c_str(), wndTitle.c_str(), wndFlags,
wndDimensions.left, wndDimensions.top, wndDimensions.right, wndDimensions.bottom,
NULL, 0, hinstance, NULL);
The whole purpose is to be able to call GetDlgCtrlId(hwnd);.
This cannot work. The CreateWindowEx function is a little bit confusing in that the interpretation of the parameters differs, depending on which type of window you are creating. You have to read the documentation carefully to avoid making erroneous assumptions.
There are two fundamental types of windows: overlapped/pop-up windows (I think there used to be a distinction back in 16-bit Windows, but that distinction is no longer relevant; these are practically identical) and child windows. The first type are the ones you intuitively think of, since they're the ones that look like windows. They're what an application uses for its main window, dialog boxes, floating tool windows, etc. The second type are a specific type of windows that can only be used as children of another window. Controls are child windows—things like buttons, static controls, listviews, etc. Child windows are hosted by a parent window (they always have a parent), which can either be another child window or an overlapped/pop-up window.
Only child windows have application-defined IDs. You specify this ID when calling the CreateWindowEx function with the WS_CHILD style flag (which requests the creation of a child window). When that flag is present, the hMenu parameter is not interpreted as a handle to a menu. Rather, it is interpreted as the child window's ID.†
When calling the CreateWindowEx function without the WS_CHILD style flag (which means you are passing either WS_OVERLAPPED or WS_POPUP, which we have already seen are essentially interchangeable), the hMenu parameter is interpreted as a handle to a menu. If it is a valid handle to a menu, then this menu is associated with the window. If it is NULL, then the window uses the class menu (the one specified when RegisterClassEx was called during creation of the window class).‡
The function's documentation tries to make this clear in the description of the hMenu parameter.
It says:
hMenu [in, optional]
Type: HMENU
A handle to a menu, or specifies a child-window identifier, depending on the window style. For an overlapped or pop-up window, hMenu identifies the menu to be used with the window; it can be NULL if the class menu is to be used. For a child window, hMenu specifies the child-window identifier, an integer value used by a dialog box control to notify its parent about events. The application determines the child-window identifier; it must be unique for all child windows with the same parent window.
The implication should be obvious. A window cannot have both a menu and an ID. It has either a menu (if it is an overlapped/pop-up window) or a child-window ID (if it is a child window). Child windows never have menus—this is technically impossible because they have IDs. So what you are trying to do is impossible: overlapped/pop-up windows cannot have an ID set.
You state in the question that your intent is to be able to call the GetDlgCtrlID function, but that function's documentation is pretty clear about the fact that it works only for child windows. For starters, the very name of the function implies that it works for controls (abbreviated to "ctrl"), which by definition must be child windows. Reading further (italicized annotations are mine):
GetDlgCtrlID accepts child window handles as well as handles of controls in dialog boxes. [Technically, this is an unnecessary distinction. As we have seen, controls in dialog boxes are child windows. But, presumably, the author was taking special care to be as clear as possible.] An application sets the identifier for a child window when it creates the window by assigning the identifier value to the hmenu parameter when calling the CreateWindow or CreateWindowEx function.
Although GetDlgCtrlID may return a value if hwndCtl is a handle to a top-level window, top-level windows [by this is meant either overlapped or pop-up windows] cannot have identifiers and such a return value is never valid.
Note in particular that final sentence.
Of course, there is some way to identify overlapped and pop-up windows: their handle. This is the value returned to you by the CreateWindowEx function (assuming it is successful), and you can save this handle as the window's ID. It is guaranteed to be unique system-wide (although it may be reused for another window after your window has been destroyed), and is the most reliable way of identifying a window.
If, for some reason, you are unable to save the window handle but still need to find a top-level window later, you can call the FindWindow function. This uses the window class name and the window caption to find a matching window. If it finds a match, it returns the window handle. (Note again the distinction between top-level and child windows. FindWindow does not work on child windows. If you want to search child windows, you must call FindWindowEx instead.)
† Note that, once a child window has been created, its ID can be set or retrieved by passing the GWL_ID index to the GetWindowLongPtr or SetWindowLongPtr functions, respectively. This index only has meaning for child windows, because no other type of window has an ID.
‡ Note that, once an overlapped/pop-up window has been created, its menu handle can be retrieved with GetMenu or set with SetMenu. Again, the documentation for those functions is forced to emphasize the fact that child windows cannot have menus. GetMenu fails when called on a child window, returning an "undefined" result; SetMenu similarly fails, setting an error code.

multiple windows, single tray icon

My goal is to have a single icon for all the windows of my application.
After some reading, my understanding is that creating a tray icon is achieved through Shell_NotifyIcon(). This function gets a NOTIFYICONDATA structure which contains a hWnd field. This HWND is used by the system to notify the corresponding window of tray icon events. These events are handled by a WindowProc callback that is set on the window with SetWindowLongPtr().
Hence my questions:
How can a single icon notify all the windows of my app of say a left mouse click ?
Can I Shell_NotifyIcon() multiple times with different NOTIFYICONDATA structures, each one with a different hWnd, but with the same icon ?
What if the original window that got registered for creating the tray icon is destroyed ?
Would creating a hidden proxy window be an appropriate solution ?
Some background: my application calls the WinAPI with C (using js-ctypes), and should ideally work on all Windows versions from XP on.
You practically answered your own question in the question itself. The best thing to do is create a hidden window that survives as long as you need the tray icon to exist.
You would call Shell_NotifyIcon() only once with the hWnd referring to this hidden window, and have this window post the messages to the individual windows that need to receive them.
This also gives you the flexibility of being able to decide to skip sending messages to a particular window, or being able to send a different message to each window, depending on the requirements of your particular application.

How to let the parent window of a child window (a.k.a. owned window) stay active with winapi?

I am writing a small C application using winapi. There I've got a window with a child window (toolbox). I am able to keep it inside this window and so on, but my question is: How to keep the main window active, if the child window gets focused?
The main window gets grayed out in this moment.
The windows get created by:
hMainWindow = DialogBoxParam(.......);
hChildWindow = CreateDialogParam(..., hMainWindow, ...);
ShowWindow (hChildWindow, SW_SHOW);
Here a little image of the behaviour of the two windows:
I've found out that simply creating it as WS_CHILD and explicitly NOT as WS_POPUP solves that. It also turns the absolute window coordinates to relative ones so that I dont have to care about the window position anymore by moving the parent window.
// Solved
Create the child window as a modeless dialog box instead of a modal one. So instead of using DialogBox, use CreateDialog
Sorry, that's just the way Windows works: one active window at a time.
You can see this in Visual Studio if you bring up Find and Replace as a tool window, you'll see that it gets activated and the main VS window goes inactive.
Trying to have them both active at the same time could confuse users and accessibility tools like screen readers.

How can I cause my MessageBox to pop up on top of all forms?

I am currently providing information to the user with a message box in my C program, but the message box is appearing behind all other forms of my application.
How can I bring it forward so that it appears in front of all my forms, or set its parent?
Here is the code I'm currently using to show the message box:
MessageBox(0,error_msg, "Error - No Algorithm", MB_OK );
The reason it's appearing behind all forms now is because you've not specified an owner window. That causes it to appear directly on top of the desktop window. The problem is that your other windows are already covering up the desktop window, so they blissfully continue to cover up your message box, too.
The solution, as you suspect, is to specify one of your windows as the owner for the message box. You do that by specifying their window handle (HWND) as the first argument to the function:
MessageBox(hWnd, // the window handle for your owner window
error_msg, // the message to be displayed
"Error - No Algorithm", // the title
MB_OK); // flags indicating contents and behavior
The documentation provides additional information.
The first parameter to MessageBox is the HWND to parent to. 0 or NULL means "no parent", so the resulting message box will not be modal. You need to supply the parent HWND to get the behavior you want.
Late to this but just search for the window by class or title using FindWindow and supply that HWND as the first parameter to MessageBox.

Changing window procedure for console window

I want to make console window with a functional tray icon. I figured out that most probably it is necessary to replace initial console's window procedure so I will be able to control all messages including notify area events. But SetWindowLong() function returns 0, and GetLastError() tells that access is denied.
hwndFound = GetConsoleWindow();
SetWindowLong(hwndFound, GWL_WNDPROC, (long)WndProc);
What could it be, or maybe there is some other way to control tray icon manipulations?
If all you want to do is create a notification icon for a console application, there's nothing that says your Shell_NotifyIcon call has to point to the console window. Create an invisible dummy window with your own window class and procedure instead. Note that you'll probably have to do this from a secondary thread in order to run its message loop. (The console window is special, as it's hosted outside your process by conhost.exe/csrss.exe.)
No, you just need a window. Best thing is to startup a thread so you can pump a message loop and receive the icon notifications. Create a little hidden window that you can use for the Shell_NotifyIcon() call.
Which version of Windows are you using? I know that prior to Vista, console windows are treated specially, and can't be manipulated in many of the standard ways. This article by Raymond Chen might shed some further light.

Resources