Keep window on top and steal focus in WinForms - c#

I realize that this would be COMPLETELY bad practice in normal situations, but this is just for a test app that needs to be taking input from a bar code scanner (emulating a keyboard). The problem is that I need to start up some scripts while scanning, so I need the window to regain focus directly after I click the script to run it. I've tried using Activate(), BringToFront(), Focus() as well as some Win32 calls like SetForegroundWindow(), Setcapture() and SetActiveWindow()... however the best I can get any of them to do is to make the taskbar item start blinking to tell me that it wants to have focus, but something is stopping it. BTW, I'm running this on XP SP2 and using .NET 2.0.
Is this possible?
Edit: To clarify, I am running the scripts by double-clicking on them in explorer. So I need it to steal focus back from explorer and to the test app.

I struggled with a similar problem for quite a while. After much experimentation and guessing, this is how I solved it:
// Get the window to the front.
this.TopMost = true;
this.TopMost = false;
// 'Steal' the focus.
this.Activate();

Visibility
Make the window a "Top-Most" window. This is the way the Task-Manager can remain on top of other windows. This is a property of a Form and you make the form top-most (floating above other windows) by setting the value to true.
You shouldn't need to override any of the "Active window" behaviour with the top-most setting.
Focus
I asked a similar question previously here on StackOverflow and the answer would solve your problem. You can make the application use a low-level input hook and get notification of the key-codes coming from the scanner. This way, your application always gets these keys even though the application does not have focus.
You may need to enhance the solution to squash the key-codes so that they are not transmitted to the "in-focus" application (e.g. notepad).
Since Windows 2000, there is no official mechanism for an application to grab focus without direct intervention of the user. Peeking at the input streams through the RawInputDevices hook is the only sensible way to go.
A number of articles may help (C# implementations)
RawInput article on CodeProject
MSDN documentation of RawInput

I had a similar problem and found the following to do the trick. Adapted to C# from here
// force window to have focus
uint foreThread = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
uint appThread = GetCurrentThreadId();
const uint SW_SHOW = 5;
if (foreThread != appThread)
{
AttachThreadInput(foreThread, appThread, true);
BringWindowToTop(form.Handle);
ShowWindow(form.Handle, SW_SHOW);
AttachThreadInput(foreThread, appThread, false);
}
else
{
BringWindowToTop(form.Handle);
ShowWindow(form.Handle, SW_SHOW);
}
form.Activate();
EDIT: Here are the necessary PInvoke definitions for C#:
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
// When you don't want the ProcessId, use this overload and pass IntPtr.Zero for the second parameter
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();
/// <summary>The GetForegroundWindow function returns a handle to the foreground window.</summary>
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll", SetLastError = true)]
static extern bool BringWindowToTop(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern bool BringWindowToTop(HandleRef hWnd);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);

The way I approached this problem was to spawn another thread whose only purpose was to ensure the Form is TopMost and has focus at all times. This code will make all other applications unusable while it is running, which is what I needed for my specific applications. You can add in a Sleep in keepFocus or have some other event trigger it.
using System.Threading; // be sure to include the System.Threading namespace
//Delegates for safe multi-threading.
delegate void DelegateGetFocus();
private DelegateGetFocus m_getFocus;
//Constructor.
myForm()
{
m_getFocus = new DelegateGetFocus(this.getFocus); // initialise getFocus
InitializeComponent();
spawnThread(keepFocus); // call spawnThread method
}
//Spawns a new Thread.
private void spawnThread(ThreadStart ts)
{
try
{
Thread newThread = new Thread(ts);
newThread.IsBackground = true;
newThread.Start();
}
catch(Exception e)
{
MessageBox.Show(e.Message, "Exception!", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
//Continuously call getFocus.
private void keepFocus()
{
while(true)
{
getFocus();
}
}
//Keeps Form on top and gives focus.
private void getFocus()
{
//If we need to invoke this call from another thread.
if (this.InvokeRequired)
{
try
{
this.Invoke(m_getFocus, new object[] { });
}
catch (System.ObjectDisposedException e)
{
// Window was destroyed. No problem but terminate application.
Application.Exit();
}
}
//Otherwise, we're safe.
else
{
this.TopMost = true;
this.Activate();
}
}
}

You might try focusing on a specific input, or try the setting .TopMost property to true (and then unsetting it again).
But I suspect your problem is that these methods all just place messages in the windows event queue, and your program has to wait for all existing events to finish processing before it will handle that one and focus the app.

Related

run another application within a C# program with his childs

I use a sample code to hunt process to my windows form application from specific List
void processStartEvent_EventArrived(object sender, EventArrivedEventArgs e)
{
string processName = e.NewEvent.Properties["ProcessName"].Value.ToString();
int processID = Convert.ToInt32(e.NewEvent.Properties["ProcessID"].Value);
if (_processNames.Contains(processName))
{
Process proc = Process.GetProcessById(processID);
if (GlobalVar.SourceWinForm.InvokeRequired)
{
GlobalVar.SourceWinForm.Invoke(new MethodInvoker(delegate { ProcessHandler.SetParent(proc.MainWindowHandle, GlobalVar.SourceWinForm.Handle); }));
}
else
{
ProcessHandler.SetParent(proc.MainWindowHandle, GlobalVar.SourceWinForm.Handle);
}
}
}
as you can see i use the function :
[DllImport("user32.dll")]
public static extern IntPtr SetParent(IntPtr hwc, IntPtr hwp);
everything work good except one thing.
for example i hunted notepad application into my app.
so it really give me the notepad into my app window but the problem start when
i press for example in the notepad "Format -> Font" it open a new sub window of notepad , this sub window , my apllication is not father of this sub window.
how i can hunt the full process ? include his child (subs) windows ?
you can use:
[DllImport("user32.dll")]
private static extern
bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern
bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern
bool IsIconic(IntPtr hWnd);
and then
// bring it to the foreground
if (IsIconic(proc.MainWindowHandle))
ShowWindowAsync(proc.MainWindowHandle, SW_RESTORE);
SetForegroundWindow(proc.MainWindowHandle);
Solution:
first of all i want to say the comments are correct and can help to someone else so please read the comments to my main question first.
but if you have specific scenario and you don't have any other option and you must use SetParent or other function like that. ( make sure you read first about SetParent and you understand what it dose )
the solution is to take the entire forms to foreground:
bool SetForegroundWindow(IntPtr hWnd);
this make all the other forms that inherit from the main form you loaded to see it on your main application ( this in case you application block and streach entire screen )

How can I determine when my application's console window gets or loses focus?

Is there a simple way to do this?
Or at the very least check if the console is currently in focus?
Imagine something like a game (thats not the case here but the analogy holds) - it would be useful if it could pause automatically. I need something similar.
If the window you were interested in were not a console window, this would have been very simple to do by just tapping into the appropriate focus event. But console windows don't have focus events, so the easy way out is not available here.
What you can do is set up an event handler to receive WinEvents generated by the UI Automation services. An event is generated whenever the window focus changes; you can get the HWND of the newly focused window and compare it to that of your console window. If they match, you just got focus; if they don't, you don't have focus (either just lost it or never had it to begin with).
The most convenient way to tap into UI Automation is through the System.Windows.Automation namespace. You can set up the event handler with AddAutomationFocusChangedEventHandler, which will give you an instance of AutomationFocusChangedEventArgs from which you can determine which window has received focus.
Here's some sample code:
AutomationFocusChangedEventHandler focusHandler = OnFocusChange;
Automation.AddAutomationFocusChangedEventHandler(focusHandler);
MessageBox.Show("Listening to focus changes");
Automation.RemoveAutomationFocusChangedEventHandler(focusHandler);
where OnFocusChange is:
void OnFocusChange(object source, AutomationFocusChangedEventArgs e)
{
var focusedHandle = new IntPtr(AutomationElement.FocusedElement.Current.NativeWindowHandle);
var myConsoleHandle = Process.GetCurrentProcess().MainWindowHandle;
if (focusedHandle == myConsoleHandle)
{
// ...
}
}
Note that I am assuming the console is your process's main window for simplicity; if that's not the case, you need to get a HWND to the console window some other way.
Also note that in order to receive automation events, your process must be running a message loop (in this case also known as a "dispatcher loop"), which in turn requires a thread being dedicated to running it. In the example above this happens automatically when MessageBox.Show is called, but in the general case you will have to take proper care of it.
I can't add a comment so I'm just going to have to post an answer. You can test the theory posted by DJ KRAZE like this:
/// <summary>Returns true if the current application has focus, false otherwise</summary>
public static bool ApplicationIsActivated()
{
var activatedHandle = GetForegroundWindow();
if (activatedHandle == IntPtr.Zero) {
return false; // No window is currently activated
}else{
Console.WriteLine("Application is focused!");
}
var procId = Process.GetCurrentProcess().Id;
int activeProcId;
GetWindowThreadProcessId(activatedHandle, out activeProcId);
return activeProcId == procId;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
So if it doesn't return false, then it will print "Application is focused!" in the application. You can always add something where "return false" is to do something when it's not focused as well.

How to set focus back to form after opening up a process (Notepad)?

I open up a notepad from my program using Process.Start() but the new opened notepad covers the screen. But I do want my application to maintain its focus.
I similarly (using the same Process.Start) open up MS Excel and Word but to get focus back to my form all I need to write is:
this.Focus();
But quirk with Notepad: I open notepad (and all other processes like this)
Process process = new Process();
process.StartInfo.UseShellExecute = true;
process.EnableRaisingEvents = true;
process.StartInfo.FileName = #"abc.log";
process.Start();
Now notepad takes the focus.
I tried these:
this.Activate(), this.Focus(), needless to mention
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern IntPtr SetFocus(HandleRef hWnd);
{
IntPtr hWnd = myProcess.Handle;
SetFocus(new HandleRef(null, hWnd));
}
[DllImport("User32")]
private static extern int SetForegroundWindow(IntPtr hwnd);
[DllImportAttribute("User32.DLL")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
private const int SW_SHOW = 5;
private const int SW_MINIMIZE = 6;
private const int SW_RESTORE = 9;
{
ShowWindow(Process.GetCurrentProcess().MainWindowHandle, SW_RESTORE);
SetForegroundWindow(Process.GetCurrentProcess().MainWindowHandle);
}
Another lengthier solution got from here.
All which still keeps the focus on notepad. Why is it so difficult to merely get focus to a window, that too application's own window?
EDIT: At best I can open the notepad minimized, but it still wouldn't give the focus to the form after trying all the above codes. Notepad opens minimized, but focus will be still on notepad (something that sometimes we see in windows xp) and form will be out of focused.
I tried almost everything on internet (so sure about it :)). At best I could get my form on top of all other forms, but without focus (going by #Hans Passant's method). Going by heavy blocks of codes all over, I somehow felt this aint gonna be easy. So I always used SetForegroundWindow() with chunks of other code. Never thought merely SetForegroundWindow() would do the trick.
This worked.
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
private void button1_Click(object sender, EventArgs e)
{
Process process = new Process();
process.StartInfo.FileName = #...\abc.log";
process.Start();
process.WaitForInputIdle(); //this is the key!!
SetForegroundWindow(this.Handle);
}
At times this method yields in a focus on the parent form (in cases where my desired form is a modal child form of its parent form); in such cases, just add this.Focus() to the last line..
Even this worked:
Microsoft.VisualBasic.Interaction.Shell(#"notepad.exe D:\abc.log",
Microsoft.VisualBasic.AppWinStyle.NormalNoFocus);
Solution provided by here
I had the same problem, i eventually wound up with programmatically calling alt-tab:
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
private void alttab()
{
uint WM_SYSCOMMAND = 0x0112;
int SC_PREVWINDOW = 0xF050;
PostMessage(Process.GetCurrentProcess().MainWindowHandle, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
}
//EDIT: You should use process.MainWindowHandle instead ofcourse
If you want to start a process and focus back to the form, then start that process with minimized state, like this:
Dim psi As New ProcessStartInfo("notepad")
psi.WindowStyle = ProcessWindowStyle.Minimized
Process.Start(psi)
Windows prevents apps from shoving their window into the user's face, you are seeing this at work. The exact rules when an app may steal the focus are documented in the MSDN docs for AllowSetForegroundWindow().
A back-door around this restriction is the AttachThreadInput() function. This code worked well, I did take a shortcut on finding the thread ID for the thread that owns the foreground window. Good enough for Notepad, possibly not for other apps. Do beware that Raymond Chen does not approve of this kind of hack.
private void button1_Click(object sender, EventArgs e) {
var prc = Process.Start("notepad.exe");
prc.WaitForInputIdle();
int tid = GetCurrentThreadId();
int tidTo = prc.Threads[0].Id;
if (!AttachThreadInput(tid, tidTo, true)) throw new Win32Exception();
this.BringToFront();
AttachThreadInput(tid, tidTo, false);
}
[DllImport("user32.dll", SetLastError = true)]
private static extern bool AttachThreadInput(int tid, int tidTo, bool attach);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
Try this:
public partial class MainForm : Form
{
private ShowForm showForm;
public MainForm()
{
InitializeComponent();
}
private void showButton_Click(object sender, EventArgs e)
{
this.showForm = new ShowForm();
this.showForm.FormClosed += showForm_FormClosed;
this.showForm.Show(this);
}
private void showForm_FormClosed(object sender, FormClosedEventArgs e)
{
this.Focus();
}
}

Restore a minimized window of another application

I'm adding some code to an app that will launch another app if it isn't already running, or if it is, bring it to the front. This requires a small amount of interop/WinAPI code, which I've gotten examples for from other sites but can't seem to get to work in Win7.
If the window is in some visible state, then the API's SetForegroundWindow method works like a treat (and this would be the main case, as per company policy if the external app is running it should not be minimized). However, if it is minimized (exceptional but important as my app will appear to do nothing in this case), neither this method nor ShowWindow/ShowWindowAsync will actually bring the window back up from the taskbar; all of the methods simply highlight the taskbar button.
Here's the code; most of it works just fine, but the call to ShowWindow() (I've also tried ShowWindowAsync) just never does what I want it to no matter what the command I send is:
[DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hWnd);
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMAXIMIZED = 3;
private const int SW_RESTORE = 9;
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
...
//The app is named uniquely enough that it can't be anything else,
//and is not normally launched except by this one.
//so this should normally return zero or one instance
var processes = Process.GetProcessesByName("ExternalApp.exe");
if (processes.Any()) //a copy is already running
{
//I can't currently tell the window's state,
//so I both restore and activate it
var handle = processes.First().MainWindowHandle;
ShowWindow(handle, SW_RESTORE); //GRR!!!
SetForegroundWindow(handle);
return true;
}
try
{
//If a copy is not running, start one.
Process.Start(#"C:\Program Files (x86)\ExternalApp\ExternalApp.exe");
return true;
}
catch (Exception)
{
//fallback for 32-bit OSes
Process.Start(#"C:\Program Files\ExternalApp\ExternalApp.exe");
return true;
}
I've tried SHOWNORMAL (1), SHOWMAXIMIZED (3), RESTORE (9), and a couple other sizing commands, but nothing seems to do the trick. Thoughts?
EDIT: I found an issue with some of the other code I had thought was working. The call to GetProcessesByName() was not finding the process because I was looking for the executable name, which was not the process name. That caused the code I thought was running and failing to actually not execute at all. I thought it was working because the external app will apparently also detect that a copy is already running and try to activate that current instance. I dropped the ".exe" from the process name I search for and now the code executes; however that seems to be a step backwards, as now the taskbar button isn't even highlighted when I call ShowWindow[Async]. So, I now know that neither my app, nor the external app I'm invoking, can change the window state of a different instance programmatically in Win7. What's goin' on here?
Working code using FindWindow method:
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string className, string windowTitle);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags);
[DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowPlacement(IntPtr hWnd, ref Windowplacement lpwndpl);
private enum ShowWindowEnum
{
Hide = 0,
ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,
Maximize = 3, ShowNormalNoActivate = 4, Show = 5,
Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8,
Restore = 9, ShowDefault = 10, ForceMinimized = 11
};
private struct Windowplacement
{
public int length;
public int flags;
public int showCmd;
public System.Drawing.Point ptMinPosition;
public System.Drawing.Point ptMaxPosition;
public System.Drawing.Rectangle rcNormalPosition;
}
private void BringWindowToFront()
{
IntPtr wdwIntPtr = FindWindow(null, "Put_your_window_title_here");
//get the hWnd of the process
Windowplacement placement = new Windowplacement();
GetWindowPlacement(wdwIntPtr, ref placement);
// Check if window is minimized
if (placement.showCmd == 2)
{
//the window is hidden so we restore it
ShowWindow(wdwIntPtr, ShowWindowEnum.Restore);
}
//set user's focus to the window
SetForegroundWindow(wdwIntPtr);
}
You can use it by calling BringWindowToFront().
I always have one instance of the application running so if you can have several open instances simultaneously you might want to slightly change the logic.
... Apparently you cannot trust the information a Process gives you.
Process.MainWindowHandle returns the window handle of the first window created by the application, which is USUALLY that app's main top-level window. However, in my case, a call to FindWindow() shows that the handle of the actual window I want to restore is not what MainWindowHandle is pointing to. It appears that the window handle from the Process, in this case, is that of the splash screen shown as the program loads the main form.
If I call ShowWindow on the handle that FindWindow returned, it works perfectly.
What's even more unusual is that when the window's open, the call to SetForegroundWindow(), when given the process's MainWindowHandle (which should be invalid as that window has closed), works fine. So obviously that handle has SOME validity, just not when the window's minimized.
In summary, if you find yourself in my predicament, call FindWindow, passing it the known name of your external app's main window, to get the handle you need.
I had the same problem. The best solution I have found is to call ShowWindow with the flag SW_MINIMIZE, and then with SW_RESTORE. :D
Another possible solution:
// Code to display a window regardless of its current state
ShowWindow(hWnd, SW_SHOW); // Make the window visible if it was hidden
ShowWindow(hWnd, SW_RESTORE); // Next, restore it if it was minimized
SetForegroundWindow(hWnd); // Finally, activate the window
from comments at: http://msdn.microsoft.com/en-us/library/ms633548%28VS.85%29.aspx
Tray calling ShowWindow(handle, SW_RESTORE); after SetForegroundWindow(handle);
This might solve your problem.
It sounds like you're trying to perform an action that has the same result as alt-tabbing, which brings the window back if it was minimized while "remembering" if it was maximized.
NativeMethods.cs:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
// Specify your namespace here
namespace <your.namespace>
{
static class NativeMethods
{
// This is the Interop/WinAPI that will be used
[DllImport("user32.dll")]
static extern void SwitchToThisWindow(IntPtr hWnd, bool fUnknown);
}
}
Main code:
// Under normal circumstances, only one process with one window exists
Process[] processes = Process.GetProcessesByName("ExternalApp.exe");
if (processes.Length > 0 && processes[0].MainWindowHandle != IntPtr.Zero)
{
// Since this simulates alt-tab, it restores minimized windows to their previous state
SwitchToThisWindow(process.MainWindowHandle, true);
return true;
}
// Multiple things are happening here
// First, the ProgramFilesX86 variable automatically accounts for 32-bit or 64-bit systems and returns the correct folder
// Secondly, $-strings are the C# shortcut for string.format() (It automatically calls .ToString() on each variable contained in { })
// Thirdly, if the process was able to start, the return value is not null
try { if (Process.Start($"{System.Environment.SpecialFolder.ProgramFilesX86}\\ExternalApp\\ExternalApp.exe") != null) return true; }
catch
{
// Code for handling an exception (probably FileNotFoundException)
// ...
return false;
}
// Code for when the external app was unable to start without producing an exception
// ...
return false;
I hope this provides a much simpler solution.
(General Rule: If a string value is ordinal, i.e. it belongs to something and isn't just a value, then it is better to get it programmatically. You'll save yourself a lot of trouble when changing things. In this case, I'm assuming that the install location can be converted to a global constant, and the .exe name can be found programmatically.)
I know its too late, still my working code is as follows so that someone later can get quick help :)
using System.Runtime.InteropServices;
using System.Diagnostics;
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
private static void ActivateApp(string processName)
{
Process[] p = Process.GetProcessesByName(processName);
if (p.Length > 0)
{
IntPtr handle = FindWindowByCaption(IntPtr.Zero, p[0].ProcessName);
ShowWindow(handle, 9); // SW_RESTORE = 9,
SetForegroundWindow(handle);
}
}
ActivateApp(YOUR_APP_NAME);
Actually, FindWindowByCaption is the key here, this method collects the window handle correctly when app is running silently in the system tray and also when app is minimized.

Determine if current application is activated (has focus)

Note: There's a very similar question, but it's WPF-specific; this one is not.
How can I determine if the current application is activated (i.e. has focus)?
This works:
/// <summary>Returns true if the current application has focus, false otherwise</summary>
public static bool ApplicationIsActivated()
{
var activatedHandle = GetForegroundWindow();
if (activatedHandle == IntPtr.Zero) {
return false; // No window is currently activated
}
var procId = Process.GetCurrentProcess().Id;
int activeProcId;
GetWindowThreadProcessId(activatedHandle, out activeProcId);
return activeProcId == procId;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
It has the advantage of being thread-safe, not requiring the main form (or its handle) and is not WPF or WinForms specific. It will work with child windows (even independent ones created on a separate thread). Also, there's zero setup required.
The disadvantage is that it uses a little P/Invoke, but I can live with that :-)
since it's likely that some element in your UI has contain focus for the form to be active try:
this.ContainsFocus
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.containsfocus(v=vs.110).aspx
The solution I found which requires neither native calls nor requires handling events is to check Form.ActiveForm. In my tests, that was null when no window in the application was focused and otherwise non-null.
var windowInApplicationIsFocused = Form.ActiveForm != null;
Ah, this is specific to winforms. But that applies to my situation ;-).
You can subscribe to Main Window's Activated event
First get the handle either using:
IntPtr myWindowHandle;
myWindowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
or
HwndSource source = (HwndSource)HwndSource.FromVisual(this);
myWindowHandle = source.Handle;
Then compare whethers it is the ForeGroundWindow:
if (myWindowHandle == GetForegroundWindow())
{
// Do stuff!
}
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
Handle the Activated event of your main application Form.
In WPF the easiest way to check if a window is active is:
if(this.IsActive)
{
//the window is active
}

Categories

Resources