since I couldn't find an answer to this question I researched a bit further into the MSDN and I found isChild(). It might give me the answer to that other question.
Now, in order to use isChild() I need to pass the HWND of the parent application that I want to check, in this case my own application.
How do I get the HWND of my own application?
I don't know the title since it changes constantly so I can't use FindWindow().
Thanks
Edit:
Since it's not clear, I'll add more information:
I am not creating a window. I don't have access to the creation of a window. My code is a piece of code that gets compiled together with whatever application the other programmer is coding and I have no access to how the window is created, the title or any other information.
So, how do I get the HWND to the "WINDOW" of the application I am running?
Your application doesn't have a HWND. The window does. An application may have no windows or it may have many, so there is no general function to "Get the application's HWND".
The obvious solution is just to hold on to the handle when you get it. When you create the window, a HWND is returned. Store that.
Use GetTopWindow() and GetNextWindow() to walk through windows z-order.
However, don't think it is necessary, but you can use GetCurrentProcessId() and
GetWindowThreadProcessId(), may be something like following will help you:
HWND FindMyTopMostWindow()
{
DWORD dwProcID = GetCurrentProcessId();
HWND hWnd = GetTopWindow(GetDesktopWindow());
while(hWnd)
{
DWORD dwWndProcID = 0;
GetWindowThreadProcessId(hWnd, &dwWndProcID);
if(dwWndProcID == dwProcID)
return hWnd;
hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
}
return NULL;
}
Can't you just hold onto the handle returned from CreateWindow? If not, why not?
Presumably your code gets called by main application code, otherwise what use is it? In which case I acnnot see why your code's API cannot include some way of informing you of the handle of the application's main window.
As others have already pointed out
In general, an application can have zero or multiple top-level windows.
If you're creating the window yourself you can just remember the HWND somewhere.
But maybe your code is in a DLL, so you didn't actually create the top-level window yourself. So what to do?
I would suggest the following:
Use EnumWindows to enumerate all top-level windows.
Use GetWindowLongPtr to get the HINSTANCE for each top-level window. Compare this against the HINSTANCE of the application, which you can get using GetModuleHandle(NULL). If they're identical, you've found your main window.
Edit: Here is some code. Turns out you also have to use IsWindowVisible because there seem to be quite a few invisible "helper" windows.
HWND hwndMain;
BOOL CALLBACK EnumWindowProc(HWND hwnd, LPARAM lParam)
{
HINSTANCE hinst=(HINSTANCE)GetModuleHandle(NULL);
if((HINSTANCE)GetWindowLongPtr(hwnd, GWL_HINSTANCE)==hinst &&
IsWindowVisible(hwnd))
{
hwndMain=hwnd;
return FALSE;
}
else
return TRUE;
}
Then in the place you want to find the window:
hwndMain=NULL;
EnumWindows(EnumWindowProc, 0);
And after this, hwndMain should contain the handle of the window, or NULL if none exists.
Using EnumWindows is a bit burdensome but is recommended over calling GetWindow in a loop because, as MSDN notes: "An application that calls GetWindow to perform this task risks being caught in an infinite loop or referencing a handle to a window that has been destroyed."
You can inject a DLL in a thread who appeal user32.dll
http://msdn.microsoft.com/en-us/library/ms821625.aspx
This is old for me, but IIRC you should receive the HWND as a parameter in the window proc. You can save it in a global variable somewhere in the beginning.
What about your windows class name?
Is it always different on window creation?
If not you could still you FindWindow().
Related
I'm using the SetWindowPos function for an automation task to show a window. I know that there are two ways that Windows provides to do this:
Synchronously: SetWindowPos or ShowWindow.
Asynchronously: SetWindowPos with SWP_ASYNCWINDOWPOS or ShowWindowAsync.
Now, I'd like to get the best of both worlds: I want to be able to show the window synchronously, because I'd like it to be done when the function returns. But I don't want the call to hang my process - if it takes too long, I want to be able to abort the call.
Now, while looking for an answer, the only thing I could come up with is using a separate thread and using SendMessageTimeout, but even then, if the thread hangs, there's not much I can do to end it except of TerminateProcess, which is not a clean solution.
I also have seen this answer, but as far as I understand, it has no alternative for native WinAPI.
The answer in the question you linked to simply loops until either the desired condition occurs or the timeout expires. It uses Sleep() every iteration to avoid hogging the processor. So a version for WinAPI can be written quite simply, as follows:
bool ShowWindowAndWait(HWND hWnd, DWORD dwTimeout) {
if (IsWindowVisible(hWnd)) return true;
if (!ShowWindowAsync(hWnd, SW_SHOW)) return false;
DWORD dwTick = GetTickCount();
do {
if (IsWindowVisible(hWnd)) return true;
Sleep(15);
} while (dwTimeout != 0 && GetTickCount() - dwTick < dwTimeout);
return false;
}
Unfortunately I think this is the best you're going to get. SendMessageTimeout can't actually be used for this purpose because (as far as I know anyway) there's no actual message you could send with it that would cause the target window to be shown. ShowWindowAsync and SWP_ASYNCWINDOWPOS both work by scheduling internal window events, and this API isn't publicly exposed.
I am trying to automate an external Windows application. The goal is to make this application start minimized without showing any active window/splash screens and without stealing focus from other applications.
I wrote a little program on C that calls EnumWindows() in a loop and uses ShowWindow() to minimize the required window. It is quite fast and works in 80% of cases. Unfortunately, sometimes the application window is still showing and stealing the focus for a short period of time.
What would be a better (sure) way to intercept the window?
Is using SetWindowsHookEx hooks the only alternative?
Have you tried using the wShowWindow member of the STARTUPINFO structure you pass to CreateProcess() when starting the application? That was designed to do exactly things like this.
If dwFlags specifies STARTF_USESHOWWINDOW, this member can be any of the values that can be specified in the nCmdShow parameter for the ShowWindow function, except for SW_SHOWDEFAULT. Otherwise, this member is ignored.
For GUI processes, the first time ShowWindow is called, its nCmdShow parameter is ignored wShowWindow specifies the default value. In subsequent calls to ShowWindow, the wShowWindow member is used if the nCmdShow parameter of ShowWindow is set to SW_SHOWDEFAULT.
For example:
STARTUPINFO si = { sizeof(si) }
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_MINIMIZE;
CreateProcess(..., &si, ...);
I had a small debate with a fellow programmer. He uses the following idiom in his code:
HWND hWnd = SomeFunctionWhichReturnsAWindow();
if(hWnd != NULL && hWnd != INVALID_HANDLE_VALUE)
{
// All good
}
else
{
// Error
}
I told him that in my opinion this is a wrong approach, as the HWND type has nothing to do with the INVALID_HANDLE_VALUE definition, but he's sure that this is good code, as a valid handle can never be equal to INVALID_HANDLE_VALUE, and it's in the mood of "better safe than sorry".
So, is it an acceptable and correct idiom?
It is a mistake to compare an HWND against INVALID_HANDLE_VALUE. Although, in practise this is not a mistake that will hurt you.
The only HWND value reserved by CreateWindowEx as being invalid is NULL. Now, it happens to be an implementation detail that INVALID_HANDLE_VALUE cannot ever be a valid HWND, but that is just implementation detail. The function that yields window handles, CreateWindowEx, uses NULL to indicate failure. That's all you need to know.
If you wish to win your argument with your colleague, I suggest you look inside SomeFunctionWhichReturnsAWindow and find out which Win32 API is called to produce the HWND. Then consult the documentation. That will show you that NULL is the reserved invalid value.
For the sake of clarity you absolutely should change the code to test against NULL alone.
INVALID_HANDLE_VALUE is defined as -1. An invalid HWND is defined as 0. No API will ever return HWND(-1) on failure, so checking for INVALID_HANDLE_VALUE is meaningless, it will never happen.
However, there are some APIs that accept reserved non-zero HWND values as input, and thus cannot be used as valid HWND return values, either:
PeekMessage() and GetMessage():
If hWnd is NULL, (Peek/Get)Message retrieves messages for any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL (see the MSG structure). Therefore if hWnd is NULL, both window messages and thread messages are processed.
If hWnd is -1, (Peek/Get)Message retrieves only messages on the current thread's message queue whose hwnd value is NULL, that is, thread messages as posted by PostMessage (when the hWnd parameter is NULL) or PostThreadMessage.
So there is a logical difference between HWND(0) and HWND(-1). And in fact, because of that difference, a valid HWND will never be -1 because a message loop would never be able to retrieve messages for it.
Also SetWindowPos() has some reserved values as well:
hWndInsertAfter [in, optional]
Type: HWND
A handle to the window to precede the positioned window in the Z order. This parameter must be a window handle or one of the following values.
HWND_BOTTOM
(HWND)1
Places the window at the bottom of the Z order. If the hWnd parameter identifies a topmost window, the window loses its topmost status and is placed at the bottom of all other windows.
HWND_NOTOPMOST
(HWND)-2
Places the window above all non-topmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a non-topmost window.
HWND_TOP
(HWND)0
Places the window at the top of the Z order.
HWND_TOPMOST
(HWND)-1
Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.
CreateWindowEx and the similar functions that return a HWND clearly state that an invalid HWND is 0. Anything other might be valid.
Therefore, checking for INVALID_HANDLE_VALUE is 100% wrong, no matter what you might assume.
Making assumptions such as "this will probably never hurt" are very much dangerous and, although at this time valid, in the future you may be used to assume similar features that are not that innocent.
HWND can't be used in comparison to INVALID_HANDLE_VALUE as this two are two different things. Most resources, such as a file, etc return HANDLE and must be compared to INVALID_HANDLE_VALUE to ensure the resource is okay for use by any function which depends on it. However, HWND refers to handle for windows GUI objects. So is save to compare HWND values to 0 for invalid return handles rather than using INVALID_HANDLE_VALUE which is also -1.
Furthermore, to more information on the HANDLE type, you can check this StackOverflow previous answers to learn more.
A HANDLE is a context-specific unique identifier. By context-specific,
I mean that a handle obtained from one context cannot necessarily be
used in any other aribtrary context that also works on HANDLEs.
For example, GetModuleHandle returns a unique identifier to a
currently loaded module. The returned handle can be used in other
functions that accept module handles. It cannot be given to functions
that require other types of handles. For example, you couldn't give a
handle returned from GetModuleHandle to HeapDestroy and expect it to
do something sensible.
The HANDLE itself is just an integral type. Usually, but not
necessarily, it is a pointer to some underlying type or memory
location. For example, the HANDLE returned by GetModuleHandle is
actually a pointer to the base virtual memory address of the module.
But there is no rule stating that handles must be pointers. A handle
could also just be a simple integer (which could possibly be used by
some Win32 API as an index into an array).
The question is the windows handle is valid or not, Why not just use IsWindow()?
I'm writing a dll in which a function is used to call :
mouseHook = SetWindowsHookEx(
WH_MOUSE_LL,
MouseHookProc,
0, // tried too with (HINSTANCE) inj_hModule, which is hModule from DllMain
0);
When I put this in DllMain, or in the dll's WndProc (the one working with the messages, for instance in case WM_CREATE: or whatever ), it is working OK.
But I need to put it in a separate function, so I can hook when I call it. When I do it, GetLastError says that it succeeded, but the hook isn't working, MouseHookProc is just never called (I put some trace in it to check).
I also tried with other hInstance values for the 3rd parameter, no success either...
Searching for a solution, I read that low level hooks must be set globally, I must confess that I'm not sure to fully understand that as I think it may be the problem, is some regular function not global and wndproc functions global ??? Not sure.
It is quite frustrating as it works ok when I call it at init, if I don't find a solution quickly maybe I'll dispatch some custom message so I can SetWindowsHookEx when I want but it will still be in the wndproc...
Thanks for helping me and Merry Christmas everyone !!!
I have seen RocketDock redirect the minimize animation in Vista so windows minimize to the dock, and am just curious how this was done. Is the actual minimize animation redirected to the dock, or is something like a hook to stop Windows from minimizing the window and RocketDock has a custom animation when the window is minimized?
I am working on an open source multi-monitor taskbar project called "OpenMMT." I've recently discovered (through many headaches) how to accomplish this.
The following explanation assumes that you know how to go about using RegisterShellHookWindow.
On the window procedure that will receive the shell hooks, look for HSHELL_GETMINRECT.
Now, from here on out is where I had problems. According to MSDN, the lparam member passed contains a pointer to a "SHELLHOOK" object. Which is true, however, I could not get it to work for the simple fact that the "rc" member of that structure, is a RECT that differs from the actual RECT structure in the Windows header files. The RECT in the header files uses LONG for its members, were as on here, we want SHORT.
Anyways, here's a snippet on how I accomplished this.
Structures to define:
typedef struct {
SHORT left;
SHORT top;
SHORT right;
SHORT bottom;
} REALRECT, *LPREALRECT;
typedef struct {
HWND hWnd;
REALRECT rc;
} DOCUMENT_ME_RIGHT_MICROSOFT, *LPDOCUMENT_ME_RIGHT_MICROSOFT;
Then on the Window Procedure:
case HSHELL_GETMINRECT:
{
LPDOCUMENT_ME_RIGHT_MICROSOFT lpShellHook = (LPDOCUMENT_ME_RIGHT_MICROSOFT)lParam;
// lpShellHook now contains all the info. If you want to change the location
// of the animation, simply change the lpShellHook->rc members to point
// to the right coordinates and then return TRUE;
return TRUE;
}
When minimizing programs from my application I encountered some instances where the animation would default back to the original one. I resolved this by minimizing them like so:
void MinimizeApp(HWND hWnd) {
SetForegroundWindow(hWnd);
ShowWindowAsync(hWnd, SW_MINIMIZE);
}
If you want more info regarding my project or you just want to peek at the source, feel free to do so at https://github.com/Fafson/OpenMMT
The ptMinPosition member of the WINDOWPLACEMENT structure specifies the coordinates of the window when it is minimized, so SetWindowPlacement function can be used to that effect. But some testing shows the window should not have a task bar button for that to work (i.e. no WS_EX_APPWINDOW).
I don't know how RocketDock works, but I guess this could be achieved by installing a global WH_CBT hook, and acting upon (setting the ex_style and then setting minimized coordinates) HCBT_MINMAX notification.
You can use the AnimateWindow API function, and pass it e.g. AW_HOR_POSITIVE | AW_VER_POSITIVE to get a diagonal animation.
I'd start with a global hook catching WM_SYSCOMMAND/SC_MINIMIZE, and use AnimateWindow to target the top right corner.
If this doesn't provide the desired effect, the next step would be to use WM_PRINT/WM_PRINTCLIENT to get a copy of the window into a bitmap (I believe this is what AnimateWindow does internally), then hiding the window and doing my own animation.