I need an underlying process to gather information about other applications used by Windows. I suspect this would be done using WAPI hooks. What I wish to do is for my program to detect when windows changes focus from one program to another and tell me which one currently has focus.
First I need an event that triggers each time Windows swaps focus between two applications. All events I've found so far only handles changes made from or to the program it's being used by, but I need to find all focus-changes, even if it's between two other programs.
I'll also need a function that gives me the window in focus. Would this work, or is this only internally (windows within the current application and not other programs)?
Cheers
Depending on how accurate you need your focus change detection system to be you might be able to get away with a service that polls for the foreground window using the API function you described GetForegroundWindow (yes this is system-wide, not process specific).
You can then use the handle of that function to determine which process is the current active/focused process. Then retrieve the focused element (child window) of that process..
HWND hwnd = GetForegroundWindow();
DWORD remoteThreadId = GetWindowThreadProcessId(hwnd, NULL);
DWORD currentThreadId = GetCurrentThreadId();
AttachThreadInput(rThreadId, curThreadId, TRUE);
HWND focusElement = GetFocus();
AttachThreadInput(rThreadId, curThreadId, FALSE);
Keep doing this.. and do whatever you need to do with focusElement
UPDATE
Well, apparently, as #Kenneth K. posted in a comment, there is a global EVENT_SYSTEM_FOREGROUND event that you can hook so that you application gets notified when the foreground (focused) window changes. This way you don't need to loop continuously to detect these changes.
EVENT_SYSTEM_FOREGROUND = 3;
WINEVENT_OUTOFCONTEXT = 0;
You can follow the example in this answer to see how to hook this event and get the notifications. Then whenever the foreground (focused) window changes you can hook that window's message loop and look form focus changed events withing that window using the SetWindowsHookEx function.
Another options is to consult the list of system events on MSDN and see if there is one you can use instead of the EVENT_SYSTEM_FOREGROUND, or along with it to detect control-level focus events. Perhaps the EVENT_OBJECT_FOCUS might be useful.
Please let me know if this is still unclear..
Related
I'm trying to hook directly into window size changes (before or while it is happening) to set other applications from changing its size.
If i use WinEvent hook (thanks pinvoke), I can receive EVENT_SYSTEM_MOVESIZESTART but only when user manually tries to resize them. If a program attempts to do it on itself (probably through SetWindowPos), it won't fire.
My hope is to hook into WM_WINDOWPOSCHANGING and deny it.
pwp->flags |= SWP_NOSIZE;
return FORWARD_WM_WINDOWPOSCHANGING(hwnd, pwp, DefWindowProc);
this is pretty much how I would do it if I can hook WM_WINDOWPOSCHANGING.
I have a C# application that I am kicking off a separate win32 window from. I'm marshaling Win32 api calls into my C# application and trying to control the win32 from that. I'm toggling the window from a button press to be either maximized on top of all windows always or minimized.
It will show maximized, then ignore the first button press to hide, it then stays showing when I press the button again, then finally hides once I press the button a 3rd time with the same code. It behaves as desired from here on out. I'm sure it must be some Windows flags that aren't set properly until it goes through a maximize/minimize cycle first.
Here is the life cycle of the window:
Create window maximized
A:
Hide:
target_hwnd = FindWindowHandleByCaption()
ShowWindow(target_hwnd, SW_SHOWMINIMIZED);
Show:
target_hwnd = FindWindowHandleByCaption()
ShowWindow(target_hwnd, SW_SHOWMAXIMIZED);
Goto A:
What am I doing wrong? I've been at this for hours trying various code snippets to no avail.
Thanks in advance!
EDIT:
Solved my problem by just doing:
SendMessage(target_hwnd.ToInt32(), WM_SYSCOMMAND, SC_MINIMIZE, 0);
SendMessage(target_hwnd.ToInt32(), WM_SYSCOMMAND, SC_MAXIMIZE, 0);
Instead of using ShowWindow.
Per the ShowWindow() documentation:
nCmdShow
Type: int
Controls how the window is to be shown. This parameter is ignored the first time an application calls ShowWindow, if the program that launched the application provides a STARTUPINFO structure. Otherwise, the first time ShowWindow is called, the value should be the value obtained by the WinMain function in its nCmdShow parameter.
...
The first time an application calls ShowWindow, it should use the WinMain function's nCmdShow parameter as its nCmdShow parameter. Subsequent calls to ShowWindow must use one of the values in the given list, instead of the one specified by the WinMain function's nCmdShow parameter. As noted in the discussion of the nCmdShow parameter, the nCmdShow value is ignored in the first call to ShowWindow if the program that launched the application specifies startup information in the structure. In this case, ShowWindow uses the information specified in the STARTUPINFO structure to show the window. On subsequent calls, the application must call ShowWindow with nCmdShow set to SW_SHOWDEFAULT to use the startup information provided by the program that launched the application. This behavior is designed for the following situations:
Applications create their main window by calling CreateWindow with the WS_VISIBLE flag set.
Applications create their main window by calling CreateWindow with the WS_VISIBLE flag cleared, and later call ShowWindow with the SW_SHOW flag set to make it visible.
I am able to close another application window (calculator) from my application by using the following code:
hwnd = FindWindow(null, "Calculator");SendMessage(hwnd,WM_CLOSE,0,IntPtr.Zero);
But I want to disable the mouse wheel in the same calculator application window. I tried the following way, but it doesn't work:
SendMessage(hwnd, WM_MOUSEWHEEL, 0, IntPtr.Zero);
You need to Hook Into the Event and catch the occurence if you want to disable it for specific hWnds.
Look into this:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd373640(v=vs.85).aspx
If you define your callback function, it does need to take care about the correct distribution of the events to all Windows except the one you are searching for, despite that I'm not sure if this is just a clone of the Eventmessage or if they are only directed to your application if the hook is set.
Important is also that the code provided in the example is not complete,
it is missing a message-loop which actually does the grabbing from the message-queue.
Edit
the link mentioned below
http://null-byte.wonderhowto.com/how-to/create-simple-hidden-console-keylogger-c-sharp-0132757/
I have an app that is already running - every now and then it triggers a FlashWindowEx event (the windows 7 icon flashes). I would like to capture this event but I can't seem to find any good info on how.
My thoughts were that it would go like this:
Hook into running process using Process.GetProcessesByName
Set up event handler for FlashWindowEx
Catch it and do whatever
I guess my question is:
Is this possible?
Is there a way to get a list of available events from a running process?
How would I hook into FlashWindowEx?
The WH_SHELL hook notifies you when a window is flashing. According to the documentation:
nCode = HSHELL_REDRAW
wParam = the handle of the window
lParam = TRUE if the window is flashing, FALSE otherwise.
I recently obtained a license for WinX DVD Ripper Platinum, and am annoyed by the fact that, when it's done ripping a DVD, it doesn't tell me so. There's no popup, no system "beep"- nothing. The progress dialog simply closes. The main window doesn't even focus itself...
To speed up my DVD-ripping proccess, I'm making a simple console application (using C# and VS2010) that:
Finds the handle of the process named "WinX_DVD_Ripper_Platinum" (the process name of the WinX DVD Ripper Platinum software)
Finds the handle of the progress dialog on that process using the GetChildWindows method defined in this sample at pinvoke.net
Starts a System.Timers.Timer instance that checks (or is supposed to check) whether the progress dialog has closed every 5 seconds (using the GetWindowLong function, and
Plays a few beeps with the System.Console.Beep method to tell the user that the rip is complete. The timer auto-resets, performing the check (or repeating the beep if the dialog has closed) every 5 seconds until the user presses a key in the console window.
Steps 1, 2, and 4 are working fine, but I'm having problems with step 3- this, my question is, which of the window style constants should I use to check if the window is visible? (WS_VISIBLE did NOT work...)
For more details, this is the function I'm using to check the dialog's visibility:
private static bool IsWindowVisible(IntPtr hwnd)
{
var style = GetWindowLong(hwnd, GWL.GWL_EXSTYLE);
var visible = style & (WS flag goes here);
return visible != 0;
}
Have you tried using IsWindowVisible() instead?