WPF Always on Top doesn't work [duplicate] - c#

I have a clock application. I have set the Window's TopMost property. But, randomly, some other window or visual studio comes above clock.
Is there any other way to make my window (clock app) to display always on top of all other applications.

I know that this question is old, but I don't quite understand why the accepted answer has received up votes... or why it was accepted... it doesn't really answer the question, or provide a solution and answers posted these days that are that short are almost always down voted and/or deleted by the community. Ah well, I guess it was posted in different times.
Either way, as old as it is, I have a possible solution for anyone who may come across this post in the future. You can simply handle the Window.Deactivated Event and/or the Application.Deactivated Event. The Window.Deactivated Event occurs when a window becomes a background window and the Application.Deactivated Event occurs when an application stops being the foreground application.
The idea is to set the relevant TopMost property to true each time your application or Window loses focus:
private void Window_Deactivated(object sender, EventArgs e)
{
// The Window was deactivated
this.TopMost = true;
}
It's worth noting that other developers can also use this technique, so this doesn't guarantee that your Window will always remain on top, but it works for me and the situation is still certainly improved by using it.

This should do the trick in most cases
private void Window_Deactivated(object sender, EventArgs e)
{
// The Window was deactivated
Topmost = false; // set topmost false first
Topmost = true; // then set topmost true again.
}

I also had this problem when setting Window.Topmost = true on already existing window sometimes worked, sometimes not. Below is my workaround, you can probably combine it with Window_Deactivated approach mentioned by other people, if WS_EX_TOPMOST style is lost at runtime.
App.Current.MainWindow.Topmost = true;
// Get this window's handle
IntPtr hwnd = new WindowInteropHelper(App.Current.MainWindow).Handle;
// Intentionally do not await the result
App.Current.Dispatcher.BeginInvoke(new Action(async () => await RetrySetTopMost(hwnd)));
Extra code:
private const int RetrySetTopMostDelay = 200;
private const int RetrySetTopMostMax = 20;
// The code below will retry several times before giving up. This always worked with one retry in my tests.
private static async Task RetrySetTopMost(IntPtr hwnd)
{
for (int i = 0; i < RetrySetTopMostMax; i++)
{
await Task.Delay(RetrySetTopMostDelay);
int winStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
if ((winStyle & WS_EX_TOPMOST) != 0)
{
break;
}
App.Current.MainWindow.Topmost = false;
App.Current.MainWindow.Topmost = true;
}
}
internal const int GWL_EXSTYLE = -20;
internal const int WS_EX_TOPMOST = 0x00000008;
[DllImport("user32.dll")]
internal static extern int GetWindowLong(IntPtr hwnd, int index);

Are you sure it's a random window? If another window is also a topmost window, it is possible for it to come above your window.

Related

How to distinguish a physical mouse click from a code one?

I'm writing an autoclicker right now. I have a very difficult problem to solve at my level of knowledge.
I have low level hooks to detect Mouse KeyDown & KeyUp.
private bool LeftButtonStatus;
private void AutoClicker_Load(object sender, EventArgs e)
{
core.mouseHook.LeftButtonDown += new MouseHook.MouseHookCallback(mouseHook_LeftKeyDown);
core.mouseHook.LeftButtonUp += new MouseHook.MouseHookCallback(mouseHook_LeftKeyUp);
}
private void mouseHook_LeftKeyDown(MouseHook.MSLLHOOKSTRUCT ma)
{
LeftButtonStatus = true;
StartClicking();
}
private void mouseHook_LeftKeyUp(KeyboardHook.VKeys key)
{
LeftButtonStatus = false;
StartClicking();
}
private void StartClicking()
{
if (LeftButtonStatus)
LeftButtonTimer.Start();
else
LeftButtonTimer.Stop();
}
private void LeftButtonTimer_Tick(object sender, EventArgs e)
{
Core.LeftClick();
}
My click method in the Core class looks like this:
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
public static void LeftClick()
{
mouse_event(((int)KeyStates.LeftDown) | ((int)KeyStates.LeftDown), 0, 0, 0, 0);
}
The problem is that when I call Core.LeftClick(); my hooks detect it
and stops the Timer.
How to do I make sure Core.LeftClick(); is ignored by the mouseHook_LeftKeyUp and mouseHook_LeftKeyDown methods?
You could use a flag in your own code where you set ignore = true in LeftClick() and check if (ignore == true) in your hook methods. But the problem there is you open yourself up to a race condition where a user-generated click could be processed between the time that it's set to true and when your hook is run, which would lead to a user-generated click being ignored.
A better way would be to use the dwExtraInfo parameter of mouse_event. The documentation describes it as:
An additional value associated with the mouse event.
This seems like a great way to send some flag along in the event itself.
It is meant to be a pointer to a location in memory for some data, but I found an example of someone setting it to some arbitrary integer value (in their case 111) and it presumably worked. You could try that.
It would look something like this:
public static void LeftClick()
{
mouse_event(((int)KeyStates.LeftDown) | ((int)KeyStates.LeftDown), 0, 0, 0, 111);
}
private void mouseHook_LeftKeyDown(MouseHook.MSLLHOOKSTRUCT ma)
{
if (ma.dwExtraInfo == 111) return;
LeftButtonStatus = true;
StartClicking();
}
Your method signature for mouseHook_LeftKeyUp is different, but is that correct? If you can change that to use MSLLHOOKSTRUCT too, then you can do the same there, if you need to.
In your DllImport attribute, the type of dwExtraInfo should technically be IntPtr, but in this case it shouldn't matter.
This answer consolidates and incorporates info and ideas from other SO posts here and here.
Your question is how to distinguish a physical mouse click from a virtual one. I see that in your code you're using a mouse hook and one way to "close the loop" is by examining the dwExtraInfo flag in the callback per Gabriel Luci's excellent suggestion. But what I set out to do is find a threadsafe approach that doesn't rely on a hook to detect auto clicks so I ended up discarding the mouse hook for my testing. And I tried several things, but what I found was most reliable in my experience is to essentially set a ~100 ms watchdog timer using a thread synchronization object (like the easy-to-use SemaphoreSlim). This semaphore can be tested by whatever target ultimately consumes the click to determine whether the WDT is has expired by calling Wait(0) on the semaphore and looking at the bool return value.
In the first of two tests, I checked the AutoClick button and let it run. As expected, the physical click shows up in black and the auto clicks show up in blue. The indicators all light up as expected.
For the autoClick methods, I used SendInput since mouse_event is obsolete (see Hans Passant comment on this post.
public void autoClick(Control control)
{
autoClick(new Point
{
X = control.Location.X + control.Width / 2,
Y = control.Location.Y + control.Height / 2,
});
}
public void autoClick(Point clientPoint)
{
Cursor.Position = PointToScreen(clientPoint);
var inputMouseDown = new INPUT { Type = Win32Consts.INPUT_MOUSE };
inputMouseDown.Data.Mouse.Flags = (uint)MOUSEEVENTF.LEFTDOWN;
// Go ahead and decorate with a flag as Gabriel Luci suggests.
inputMouseDown.Data.Mouse.ExtraInfo = (IntPtr)MOUSEEXTRA.AutoClick;
var inputMouseUp = new INPUT { Type = Win32Consts.INPUT_MOUSE };
inputMouseUp.Data.Mouse.Flags = (uint)MOUSEEVENTF.LEFTUP;
var inputs = new INPUT[]
{
inputMouseDown,
inputMouseUp,
};
if (0 == SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT))))
{
Debug.Assert(false, "Error: SendInput has failed.");
}
}
[Flags]
enum MOUSEEXTRA : uint{ AutoClick = 0x40000000, }
The handler for the Auto Click 5 checkbox positions and clicks the mouse to light up 5 "indicator" check boxes.
const int SETTLE = 100;
SemaphoreSlim _sslimAutoClick = new SemaphoreSlim(1, 1);
/// <summary>
/// Responds to the button by auto-clicking 5 times.
/// </summary>
private async void onAutoClick(object sender, EventArgs e)
{
if (checkBoxAutoClick.Checked)
{
checkBoxAutoClick.Enabled = false;
foreach (var indicator in indicators)
{
await _sslimAutoClick.WaitAsync();
autoClick(indicator);
// Don't await here. It's for the benefit of clients.
Task
.Delay(SETTLE)
.GetAwaiter()
.OnCompleted(() =>_sslimAutoClick.Release());
// Interval between auto clicks.
await Task.Delay(TimeSpan.FromSeconds(2));
}
checkBoxAutoClick.Enabled = true;
checkBoxAutoClick.Checked = false;
}
}
As a more rigorous test, I repeated this but while the 5x autoclick is running I did a few manual clicks to make sure they intersperse and print in black. Again, it worked as expected.
If you'd like to browse the full code or experiment with it, the full sample code is on GitHub.

C# Set Windows Form to front but not give it focus [duplicate]

I'm using a Form to show notifications (it appears at the bottom right of the screen), but when I show this form it steals the focus from the main Form. Is there a way to show this "notification" form without stealing focus?
Hmmm, isn't simply overriding Form.ShowWithoutActivation enough?
protected override bool ShowWithoutActivation
{
get { return true; }
}
And if you don't want the user to click this notification window either, you can override CreateParams:
protected override CreateParams CreateParams
{
get
{
CreateParams baseParams = base.CreateParams;
const int WS_EX_NOACTIVATE = 0x08000000;
const int WS_EX_TOOLWINDOW = 0x00000080;
baseParams.ExStyle |= ( int )( WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW );
return baseParams;
}
}
Stolen from PInvoke.net's ShowWindow method:
private const int SW_SHOWNOACTIVATE = 4;
private const int HWND_TOPMOST = -1;
private const uint SWP_NOACTIVATE = 0x0010;
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
static extern bool SetWindowPos(
int hWnd, // Window handle
int hWndInsertAfter, // Placement-order handle
int X, // Horizontal position
int Y, // Vertical position
int cx, // Width
int cy, // Height
uint uFlags); // Window positioning flags
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void ShowInactiveTopmost(Form frm)
{
ShowWindow(frm.Handle, SW_SHOWNOACTIVATE);
SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
frm.Left, frm.Top, frm.Width, frm.Height,
SWP_NOACTIVATE);
}
(Alex Lyman answered this, I'm just expanding it by directly pasting the code. Someone with edit rights can copy it over there and delete this for all I care ;) )
This is what worked for me. It provides TopMost but without focus-stealing.
protected override bool ShowWithoutActivation
{
get { return true; }
}
private const int WS_EX_TOPMOST = 0x00000008;
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= WS_EX_TOPMOST;
return createParams;
}
}
Remember to omit setting TopMost in Visual Studio designer, or elsewhere.
This is stolen, err, borrowed, from here (click on Workarounds):
https://connect.microsoft.com/VisualStudio/feedback/details/401311/showwithoutactivation-is-not-supported-with-topmost
If you're willing to use Win32 P/Invoke, then you can use the ShowWindow method (the first code sample does exactly what you want).
Doing this seems like a hack, but it seems to work:
this.TopMost = true; // as a result the form gets thrown to the front
this.TopMost = false; // but we don't actually want our form to always be on top
Edit: Note, this merely raises an already created form without stealing focus.
The sample code from pinvoke.net in Alex Lyman/TheSoftwareJedi's answers will make the window a "topmost" window, meaning that you can't put it behind normal windows after it's popped up. Given Matias's description of what he wants to use this for, that could be what he wants. But if you want the user to be able to put your window behind other windows after you've popped it up, just use HWND_TOP (0) instead of HWND_TOPMOST (-1) in the sample.
In WPF you can solve it like this:
In the window put these attributes:
<Window
x:Class="myApplication.winNotification"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Notification Popup" Width="300" SizeToContent="Height"
WindowStyle="None" AllowsTransparency="True" Background="Transparent" ShowInTaskbar="False" Topmost="True" Focusable="False" ShowActivated="False" >
</Window>
The last one attribute is the one you need ShowActivated="False".
I have something similar, and I simply show the notification form and then do
this.Focus();
to bring the focus back on the main form.
Create and start the notification Form in a separate thread and reset the focus back to your main form after the Form opens. Have the notification Form provide an OnFormOpened event that is fired from the Form.Shown event. Something like this:
private void StartNotfication()
{
Thread th = new Thread(new ThreadStart(delegate
{
NotificationForm frm = new NotificationForm();
frm.OnFormOpen += NotificationOpened;
frm.ShowDialog();
}));
th.Name = "NotificationForm";
th.Start();
}
private void NotificationOpened()
{
this.Focus(); // Put focus back on the original calling Form
}
You can also keep a handle to your NotifcationForm object around so that it can be programmatically closed by the main Form (frm.Close()).
Some details are missing, but hopefully this will get you going in the right direction.
This works well.
See: OpenIcon - MSDN and SetForegroundWindow - MSDN
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
static extern bool OpenIcon(IntPtr hWnd);
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
public static void ActivateInstance()
{
IntPtr hWnd = IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle;
// Restore the program.
bool result = OpenIcon(hWnd);
// Activate the application.
result = SetForegroundWindow(hWnd);
// End the current instance of the application.
//System.Environment.Exit(0);
}
You might want to consider what kind of notification you would like to display.
If it's absolutely critical to let the user know about some event, using Messagebox.Show would be the recommended way, due to its nature to block any other events to the main window, until the user confirms it. Be aware of pop-up blindness, though.
If it's less than critical, you might want to use an alternative way to display notifications, such as a toolbar on the bottom of the window. You wrote, that you display notifications on the bottom-right of the screen - the standard way to do this would be using a balloon tip with the combination of a system tray icon.
You can handle it by logic alone too, although I have to admit that the suggestions above where you end up with a BringToFront method without actually stealing focus is the most elegant one.
Anyhow, I ran into this and solved it by using a DateTime property to not allow further BringToFront calls if calls were made already recently.
Assume a core class, 'Core', which handles for example three forms, 'Form1, 2, and 3'. Each form needs a DateTime property and an Activate event that call Core to bring windows to front:
internal static DateTime LastBringToFrontTime { get; set; }
private void Form1_Activated(object sender, EventArgs e)
{
var eventTime = DateTime.Now;
if ((eventTime - LastBringToFrontTime).TotalMilliseconds > 500)
Core.BringAllToFront(this);
LastBringToFrontTime = eventTime;
}
And then create the work in the Core Class:
internal static void BringAllToFront(Form inForm)
{
Form1.BringToFront();
Form2.BringToFront();
Form3.BringToFront();
inForm.Focus();
}
On a side note, if you want to restore a minimized window to its original state (not maximized), use:
inForm.WindowState = FormWindowState.Normal;
Again, I know this is just a patch solution in the lack of a BringToFrontWithoutFocus. It is meant as a suggestion if you want to avoid the DLL file.
I don't know if this is considered as necro-posting, but this is what I did since I couln't get it working with user32's "ShowWindow" and "SetWindowPos" methods. And no, overriding "ShowWithoutActivation" doesn't work in this case since the new window should be always-on-top.
Anyway, I created a helper method that takes a form as parameter; when called, it shows the form, brings it to the front and makes it TopMost without stealing the focus of the current window (apparently it does, but the user won't notice).
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern IntPtr SetForegroundWindow(IntPtr hWnd);
public static void ShowTopmostNoFocus(Form f)
{
IntPtr activeWin = GetForegroundWindow();
f.Show();
f.BringToFront();
f.TopMost = true;
if (activeWin.ToInt32() > 0)
{
SetForegroundWindow(activeWin);
}
}
I know it may sound stupid, but this worked:
this.TopMost = true;
this.TopMost = false;
this.TopMost = true;
this.SendToBack();
I needed to do this with my window TopMost. I implemented the PInvoke method above but found that my Load event wasn't getting called like Talha above. I finally succeeded. Maybe this will help someone. Here is my solution:
form.Visible = false;
form.TopMost = false;
ShowWindow(form.Handle, ShowNoActivate);
SetWindowPos(form.Handle, HWND_TOPMOST,
form.Left, form.Top, form.Width, form.Height,
NoActivate);
form.Visible = true; //So that Load event happens
You don't need to make it anywhere near as complicated.
a = new Assign_Stock();
a.MdiParent = this.ParentForm;
a.Visible = false; //hide for a bit.
a.Show(); //show the form. Invisible form now at the top.
this.Focus(); //focus on this form. make old form come to the top.
a.Visible = true; //make other form visible now. Behind the main form.
Github Sample
Form.ShowWithoutActivation Property
Add this in your child form class
protected override bool ShowWithoutActivation
{
get { return true; }
}
Working Code
Form2
public partial class Form2 : Form
{
Form3 c;
public Form2()
{
InitializeComponent();
c = new Form3();
}
private void textchanged(object sender, EventArgs e)
{
c.ResetText(textBox1.Text.ToString());
c.Location = new Point(this.Location.X+150, this.Location.Y);
c .Show();
//removethis
//if mdiparent 2 add this.focus() after show form
c.MdiParent = this.MdiParent;
c.ResetText(textBox1.Text.ToString());
c.Location = new Point(this.Location.X+150, this.Location.Y);
c .Show();
this.Focus();
////-----------------
}
}
Form3
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
//ShowWithoutActivation = false;
}
protected override bool ShowWithoutActivation
{
get { return true; }
}
internal void ResetText(string toString)
{
label2.Text = toString;
}
}
When you create a new form using
Form f = new Form();
f.ShowDialog();
it steals focus because your code can't continue executing on the main form until this form is closed.
The exception is by using threading to create a new form then Form.Show(). Make sure the thread is globally visible though, because if you declare it within a function, as soon as your function exits, your thread will end and the form will disappear.
Figured it out: window.WindowState = WindowState.Minimized;.

Disabling the Close-Button temporarily

I need to disable just the close button (minimize and maximize should be allowed) temporarily.
Every solution I've tried disables all the buttons or just disables the close button permanently. Is there a way to do it temporarily?
The way to permanently disable the close button is to set the CS_NOCLOSE style for the form's window class. To do this from a WinForms application, you override the form's CreateParams property and add the SC_NOCLOSE flag using the | operator, e.g.:
protected override CreateParams CreateParams
{
get
{
const int CS_NOCLOSE = 0x200;
CreateParams cp = base.CreateParams;
cp.ClassStyle = cp.ClassStyle | CS_NOCLOSE;
return cp;
}
}
This is a permanent solution, though, since you cannot update window class styles on-the-fly. You would have to destroy and recreate the window class.
However, you can instead disable the "Close" command in the system menu, which also also automatically disables the close button in the title bar.
internal static class NativeMethods
{
public const int SC_CLOSE = 0xF060;
public const int MF_BYCOMMAND = 0;
public const int MF_ENABLED = 0;
public const int MF_GRAYED = 1;
[DllImport("user32.dll")]
public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool revert);
[DllImport("user32.dll")]
public static extern int EnableMenuItem(IntPtr hMenu, int IDEnableItem, int enable);
}
public class MyForm : Form
{
// ...
// If "enable" is true, the close button will be enabled (the default state).
// If "enable" is false, the Close button will be disabled.
bool SetCloseButton(bool enable)
{
IntPtr hMenu = NativeMethods.GetSystemMenu(this.Handle, false);
if (hMenu != IntPtr.Zero)
{
NativeMethods.EnableMenuItem(hMenu,
NativeMethods.SC_CLOSE,
NativeMethods.MF_BYCOMMAND | (enable ? NativeMethods.MF_ENABLED : NativeMethods.MF_GRAYED));
}
}
}
Note that this really is a transient operation. If you do anything that causes the system menu to be modified by the framework (such as maximizing or minimizing the form), your modifications will be obliterated. More details are in my related answer here. This is normally a problem, and why you'd prefer to use the first solution. But in this case, since you want to dynamically disable and re-enable, it is no big deal.
Finally, do be mindful of the fact that what you're proposing runs counter to the Windows UI Guidelines for dialog boxes. They say, in essence, that users expect to see a close button and that its presence gives them a feeling of security that they can always safely "get out" of whatever popped up of the screen. Thus, you should not disable it. It does call out a progress dialog as an exception, but it goes on to say that a progress dialog should always have a "Cancel" button that allows aborting the operation. In that case, you can simply make the close button in the title bar invoke this "Cancel" button—no need to disable it.
Although it may be possible, I have never seen it. That's just not how programs do it and your program should follow known patterns so it's users know how to use it.
If closing a program is temporarily not possible, show a message explaining why, when your user tries. This way you can present a solution ("you must first do...") instead of simply presenting a problem ("cannot be closed").
In addition, there are multiple ways to close a form. You are only looking at one of them. Disabling one will still leave the others and you would want to prevent all options that lead to closing your window, so it's best to handle the Closing event appropriately.
isprocessing = true;
form.FormClosing += new FormClosingEventHandler(form_cancel);
private void form_cancel(object sender, FormClosingEventArgs e)
{
if (isprocessing)
{
e.Cancel = true; //disables the form close when processing is true
}
else
{
e.Cancel = false; //enables it later when processing is set to false at some point
}
}
This worked for me
The Close Button Is Disabled On Below Conditon :
If We Add : MessageBoxButtons.YesNo
DialogResult Dr = MessageBox.Show(this, "", "", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
You can't hide it, but you can disable it:
private const int CP_NOCLOSE_BUTTON = 0x200;
protected override CreateParams CreateParams
{
get
{
CreateParams myCp = base.CreateParams;
myCp.ClassStyle = myCp.ClassStyle | CP_NOCLOSE_BUTTON ;
return myCp;
}
}
Source: http://www.codeproject.com/Articles/20379/Disabling-Close-Button-on-Forms
If you absolutely need to hide it, the only way to do it is to create a borderless form, then draw your own minimize and maximize buttons. Here is an article on how to do this: http://www.codeproject.com/Articles/42223/Easy-Customize-Title-Bar
Before considering either of these solutions, you should maybe rethink why you need to do this. Depending on what you are trying to do, there is probably a much better way to present the UI to the user other than taking away the familiar 'X' close button.
As per other answers you are working against the guidelines and framework but, if you really must, one work around would be to put all your form content into a Usercontrol and then pass that between form instances that either have the close button enabled or disabled on load.
So as you trigger the disable or enable of the close button you create a new form instance in which the close button is toggled and then pass in the reference to your usercontrol, then dereference the usercontrol in the current form and transfer to the new form.
You'd likely get a some flicker as you did this. Terrible idea IMHO but it is "an" option.
Using Win32 API, you can do this the following way:
[DllImport("User32.dll")]
private static extern uint GetClassLong(IntPtr hwnd, int nIndex);
[DllImport("User32.dll")]
private static extern uint SetClassLong(IntPtr hwnd, int nIndex, uint dwNewLong);
private const int GCL_STYLE = -26;
private const uint CS_NOCLOSE = 0x0200;
private void Form1_Load(object sender, EventArgs e)
{
var style = GetClassLong(Handle, GCL_STYLE);
SetClassLong(Handle, GCL_STYLE, style | CS_NOCLOSE);
}
You will need to use GetClassLong / SetClassLong to enable the CS_NOCLOSE style. You then can remove it with the same operations, just use (style & ~CS_NOCLOSE) in SetClassLongPtr.
Actually, you can do this in WPF apps as well (yeah, I know, the question is about WinForms, but maybe someone will need this some day):
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
var style = GetClassLong(hwnd, GCL_STYLE);
SetClassLong(hwnd, GCL_STYLE, style | CS_NOCLOSE);
}
Still, you should consider what others have suggested: just show a MessageBox or another kind of message to indicate that user should not close the window right now.
Edit:
Since window class is just a UINT, you can use GetClassLong and SetClassLong functions instead of GetClassLongPtr and SetClassLongPtr (as says MSDN):
If you are retrieving a pointer or a handle, this function has been superseded by the GetClassLongPtr function. (Pointers and handles are 32 bits on 32-bit Windows and 64 bits on 64-bit Windows.)
This resolves the problem described by Cody Gray regarding the absense of *Ptr funcs in 32-bit OS.

How to prevent my C# winforms application from stealing focus when I set the visible properly to true?

I've got a C# winforms application that runs in the background, listening for hotkeys to be pressed. When a hotkey is pressed, my form makes a brief appearance. The form is always running, but set to hidden until I receive a hotkey event, at which time I set the visible property to true. The code looks like this:
void hook_volumeDown(object sender, KeyPressedEventArgs e)
{
this.Visible = true;
}
It should be noted that the topmost property of this form is set to true.
The really odd part is, after my C# app has stolen focus from another application, it will never do it again. For example: I launch my app, then launch some fullscreep app like Team Fortress 2. Then I press my hotkey. Team Fortress 2 minimizes, and I see my form. Then, however, I can restore TF2, and press my hotkey again all I want (with the desired effect), and TF2 will remain focused.
At any rate, I'm looking for a way to fix this. I've found a lot of questions here covering similar problems, but all of them are related to creating/launching a new form, not making an existing one visible (unless I missed something). I could rework the application to create a new form every time I need one, but that would entail creating yet another form to be invisible all the time just to wait for hotkey events, so I'd rather leave it as it is.
Any ideas?
I think you problem is related to the fact that Visible = true behaves differently between the first and subsequent calls. The first time visible is called and the window handle has not been created, the Window is created by calling CreateWindowEx which has some style parameters which controls how the window should behave. I think you need to make sure that the window is created with the style WS_EX_NOACTIVATE, which you can do by overriding CreateParams.
Other things to try out:
1) The ShowWindow function (used by Visible = true) ignores the focus parameter the first time it is called (http://msdn.microsoft.com/en-us/library/ms633548%28VS.85%29.aspx) if the program provides a STARTUPINFO structure. Dig into reflector and find out if the Form class provides a STARTUPINFO structure and if so, how to manipulate it.
2) The Form has a ShowWithoutActivation property than can be overriden and set to true, have you overriden this?
Sorry for the "no exact answer", but I hope this at least gives you some starting points for further investigation. Good luck.
Seeing KeyPressedEventArgs being used in your function looks really strange. Hot keys can be implemented by P/Invoking the RegisterHotKey() API function. It sends a message to your window when the hot key is pressed. Here's an example of a form that's invisible at start up, springs alive when you press the hot key. Ctrl+Alt+U in this case:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1 {
public partial class Form1 : Form {
private const int MYKEYID = 0; // In case you want to register more than one...
public Form1() {
InitializeComponent();
this.FormClosing += (s, args) => UnregisterHotKey(this.Handle, MYKEYID);
}
protected override void SetVisibleCore(bool value) {
if (value && !this.IsHandleCreated) {
this.CreateHandle();
RegisterHotKey(this.Handle, MYKEYID, MOD_CONTROL + MOD_SHIFT, Keys.U);
value = false;
}
base.SetVisibleCore(value);
}
protected override void WndProc(ref Message m) {
if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == MYKEYID) {
this.Visible = true;
if (this.WindowState == FormWindowState.Minimized)
this.WindowState = FormWindowState.Normal;
SetForegroundWindow(this.Handle);
}
base.WndProc(ref m);
}
// P/Invoke declarations
private const int WM_HOTKEY = 0x312;
private const int MOD_ALT = 1;
private const int MOD_CONTROL = 2;
private const int MOD_SHIFT = 4;
[DllImport("user32.dll")]
private static extern int RegisterHotKey(IntPtr hWnd, int id, int modifier, Keys vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
}
}
Note that the SetForegroundWindow() function is the rub, possibly also the source of the problem you describe in your question. Windows doesn't permit an app to shove a window in the user's face when the user is actively using another window. At least several seconds of inactivity must expire before it will allow the window to steal the focus. With the given code, that is easy enough to see, the taskbar button of your form will be blinking. Avoid setting the ShowInTaskbar property to false. It isn't necessary to do so with this code, the taskbar button won't show up until the hot key is pressed.

Bring a window to the front in WPF

How can I bring my WPF application to the front of the desktop? So far I've tried:
SwitchToThisWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle, true);
SetWindowPos(new WindowInteropHelper(Application.Current.MainWindow).Handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetForegroundWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle);
None of which are doing the job (Marshal.GetLastWin32Error() is saying these operations completed successfully, and the P/Invoke attributes for each definition do have SetLastError=true).
If I create a new blank WPF application, and call SwitchToThisWindow with a timer, it works exactly as expected, so I'm not sure why it's not working in my original case.
Edit: I'm doing this in conjunction with a global hotkey.
myWindow.Activate();
Attempts to bring the window to the foreground and activates it.
That should do the trick, unless I misunderstood and you want Always on Top behavior. In that case you want:
myWindow.TopMost = true;
I have found a solution that brings the window to the top, but it behaves as a normal window:
if (!Window.IsVisible)
{
Window.Show();
}
if (Window.WindowState == WindowState.Minimized)
{
Window.WindowState = WindowState.Normal;
}
Window.Activate();
Window.Topmost = true; // important
Window.Topmost = false; // important
Window.Focus(); // important
In case you need the window to be in front the first time it loads then you should use the following:
private void Window_ContentRendered(object sender, EventArgs e)
{
this.Topmost = false;
}
private void Window_Initialized(object sender, EventArgs e)
{
this.Topmost = true;
}
Or by overriding the methods:
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
Topmost = false;
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
Topmost = true;
}
I know this question is rather old, but I've just come across this precise scenario and wanted to share the solution I've implemented.
As mentioned in comments on this page, several of the solutions proposed do not work on XP, which I need to support in my scenario. While I agree with the sentiment by #Matthew Xavier that generally this is a bad UX practice, there are times where it's entirely a plausable UX.
The solution to bringing a WPF window to the top was actually provided to me by the same code I'm using to provide the global hotkey. A blog article by Joseph Cooney contains a link to his code samples that contains the original code.
I've cleaned up and modified the code a little, and implemented it as an extension method to System.Windows.Window. I've tested this on XP 32 bit and Win7 64 bit, both of which work correctly.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interop;
using System.Runtime.InteropServices;
namespace System.Windows
{
public static class SystemWindows
{
#region Constants
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_SHOWWINDOW = 0x0040;
#endregion
/// <summary>
/// Activate a window from anywhere by attaching to the foreground window
/// </summary>
public static void GlobalActivate(this Window w)
{
//Get the process ID for this window's thread
var interopHelper = new WindowInteropHelper(w);
var thisWindowThreadId = GetWindowThreadProcessId(interopHelper.Handle, IntPtr.Zero);
//Get the process ID for the foreground window's thread
var currentForegroundWindow = GetForegroundWindow();
var currentForegroundWindowThreadId = GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero);
//Attach this window's thread to the current window's thread
AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true);
//Set the window position
SetWindowPos(interopHelper.Handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
//Detach this window's thread from the current window's thread
AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false);
//Show and activate the window
if (w.WindowState == WindowState.Minimized) w.WindowState = WindowState.Normal;
w.Show();
w.Activate();
}
#region Imports
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("user32.dll")]
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
#endregion
}
}
I hope this code helps others who encounter this problem.
To make this a quick copy-paste one -
Use this class' DoOnProcess method to move process' main window to foreground (but not to steal focus from other windows)
public class MoveToForeground
{
[DllImportAttribute("User32.dll")]
private static extern int FindWindow(String ClassName, String WindowName);
const int SWP_NOMOVE = 0x0002;
const int SWP_NOSIZE = 0x0001;
const int SWP_SHOWWINDOW = 0x0040;
const int SWP_NOACTIVATE = 0x0010;
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
public static void DoOnProcess(string processName)
{
var allProcs = Process.GetProcessesByName(processName);
if (allProcs.Length > 0)
{
Process proc = allProcs[0];
int hWnd = FindWindow(null, proc.MainWindowTitle.ToString());
// Change behavior by settings the wFlags params. See http://msdn.microsoft.com/en-us/library/ms633545(VS.85).aspx
SetWindowPos(new IntPtr(hWnd), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
}
}
}
HTH
Why some of the answers on this page are wrong!
Any answer that uses window.Focus() is wrong.
Why? If a notification message pops up, window.Focus() will grab the focus away from whatever the user is typing at the time. This is insanely frustrating for end users, especially if the popups occur quite frequently.
Any answer that uses window.Activate() is wrong.
Why? It will make any parent windows visible as well.
Any answer that omits window.ShowActivated = false is wrong.
Why? It will grab the focus away from another window when the message pops up which is very annoying!
Any answer that does not use Visibility.Visible to hide/show the window is wrong.
Why? If we are using Citrix, if the window is not collapsed when it is closed, it will leave a weird black rectangular hold on the screen. Thus, we cannot use window.Show() and window.Hide().
Essentially:
The window should not grab the focus away from any other window when it activates;
The window should not activate its parent when it is shown;
The window should be compatible with Citrix.
MVVM Solution
This code is 100% compatible with Citrix (no blank areas of the screen). It is tested with both normal WPF and DevExpress.
This answer is intended for any use case where we want a small notification window that is always in front of other windows (if the user selects this in the preferences).
If this answer seems more complex than the others, it's because it is robust, enterprise level code. Some of the other answers on this page are simple, but do not actually work.
XAML - Attached Property
Add this attached property to any UserControl within the window. The attached property will:
Wait until the Loaded event is fired (otherwise it cannot look up the visual tree to find the parent window).
Add an event handler that ensures that the window is visible or not.
At any point, you can set the window to be in front or not, by flipping the value of the attached property.
<UserControl x:Class="..."
...
attachedProperties:EnsureWindowInForeground.EnsureWindowInForeground=
"{Binding EnsureWindowInForeground, Mode=OneWay}">
C# - Helper Method
public static class HideAndShowWindowHelper
{
/// <summary>
/// Intent: Ensure that small notification window is on top of other windows.
/// </summary>
/// <param name="window"></param>
public static void ShiftWindowIntoForeground(Window window)
{
try
{
// Prevent the window from grabbing focus away from other windows the first time is created.
window.ShowActivated = false;
// Do not use .Show() and .Hide() - not compatible with Citrix!
if (window.Visibility != Visibility.Visible)
{
window.Visibility = Visibility.Visible;
}
// We can't allow the window to be maximized, as there is no de-maximize button!
if (window.WindowState == WindowState.Maximized)
{
window.WindowState = WindowState.Normal;
}
window.Topmost = true;
}
catch (Exception)
{
// Gulp. Avoids "Cannot set visibility while window is closing".
}
}
/// <summary>
/// Intent: Ensure that small notification window can be hidden by other windows.
/// </summary>
/// <param name="window"></param>
public static void ShiftWindowIntoBackground(Window window)
{
try
{
// Prevent the window from grabbing focus away from other windows the first time is created.
window.ShowActivated = false;
// Do not use .Show() and .Hide() - not compatible with Citrix!
if (window.Visibility != Visibility.Collapsed)
{
window.Visibility = Visibility.Collapsed;
}
// We can't allow the window to be maximized, as there is no de-maximize button!
if (window.WindowState == WindowState.Maximized)
{
window.WindowState = WindowState.Normal;
}
window.Topmost = false;
}
catch (Exception)
{
// Gulp. Avoids "Cannot set visibility while window is closing".
}
}
}
Usage
In order to use this, you need to create the window in your ViewModel:
private ToastView _toastViewWindow;
private void ShowWindow()
{
if (_toastViewWindow == null)
{
_toastViewWindow = new ToastView();
_dialogService.Show<ToastView>(this, this, _toastViewWindow, true);
}
ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(_toastViewWindow);
HideAndShowWindowHelper.ShiftWindowIntoForeground(_toastViewWindow);
}
private void HideWindow()
{
if (_toastViewWindow != null)
{
HideAndShowWindowHelper.ShiftWindowIntoBackground(_toastViewWindow);
}
}
Additional links
For tips on how ensure that a notification window always shifts back onto the visible screen, see my answer: In WPF, how to shift a window onto the screen if it is off the screen?.
If the user is interacting with another application, it may not be possible to bring yours to the front. As a general rule, a process can only expect to set the foreground window if that process is already the foreground process. (Microsoft documents the restrictions in the SetForegroundWindow() MSDN entry.) This is because:
The user "owns" the foreground. For example, it would be extremely annoying if another program stole the foreground while the user is typing, at the very least interrupting her workflow, and possibly causing unintended consequences as her keystrokes meant for one application are misinterpreted by the offender until she notices the change.
Imagine that each of two programs checks to see if its window is the foreground and attempts to set it to the foreground if it is not. As soon as the second program is running, the computer is rendered useless as the foreground bounces between the two at every task switch.
I know that this is late answer, maybe helpful for researchers
if (!WindowName.IsVisible)
{
WindowName.Show();
WindowName.Activate();
}
I have had a similar problem with a WPF application that gets invoked from an Access application via the Shell object.
My solution is below - works in XP and Win7 x64 with app compiled to x86 target.
I'd much rather do this than simulate an alt-tab.
void Window_Loaded(object sender, RoutedEventArgs e)
{
// make sure the window is normal or maximised
// this was the core of the problem for me;
// even though the default was "Normal", starting it via shell minimised it
this.WindowState = WindowState.Normal;
// only required for some scenarios
this.Activate();
}
Well, since this is such a hot topic... here is what works for me. I got errors if I didn't do it this way because Activate() will error out on you if you cannot see the window.
Xaml:
<Window ....
Topmost="True"
....
ContentRendered="mainWindow_ContentRendered"> .... </Window>
Codebehind:
private void mainWindow_ContentRendered(object sender, EventArgs e)
{
this.Topmost = false;
this.Activate();
_UsernameTextBox.Focus();
}
This was the only way for me to get the window to show on top. Then activate it so you can type in the box without having to set focus with the mouse. control.Focus() wont work unless the window is Active();
Well I figured out a work around. I'm making the call from a keyboard hook used to implement a hotkey. The call works as expected if I put it into a BackgroundWorker with a pause. It's a kludge, but I have no idea why it wasn't working originally.
void hotkey_execute()
{
IntPtr handle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(delegate
{
Thread.Sleep(10);
SwitchToThisWindow(handle, true);
});
bg.RunWorkerAsync();
}
To show ANY currently opened window import those DLL:
public partial class Form1 : Form
{
[DllImportAttribute("User32.dll")]
private static extern int FindWindow(String ClassName, String WindowName);
[DllImportAttribute("User32.dll")]
private static extern int SetForegroundWindow(int hWnd);
and in program We search for app with specified title (write title without first letter (index > 0))
foreach (Process proc in Process.GetProcesses())
{
tx = proc.MainWindowTitle.ToString();
if (tx.IndexOf("Title of Your app WITHOUT FIRST LETTER") > 0)
{
tx = proc.MainWindowTitle;
hWnd = proc.Handle.ToInt32(); break;
}
}
hWnd = FindWindow(null, tx);
if (hWnd > 0)
{
SetForegroundWindow(hWnd);
}
These codes will work fine all times.
At first set the activated event handler in XAML:
Activated="Window_Activated"
Add below line to your Main Window constructor block:
public MainWindow()
{
InitializeComponent();
this.LocationChanged += (sender, e) => this.Window_Activated(sender, e);
}
And inside the activated event handler copy this codes:
private void Window_Activated(object sender, EventArgs e)
{
if (Application.Current.Windows.Count > 1)
{
foreach (Window win in Application.Current.Windows)
try
{
if (!win.Equals(this))
{
if (!win.IsVisible)
{
win.ShowDialog();
}
if (win.WindowState == WindowState.Minimized)
{
win.WindowState = WindowState.Normal;
}
win.Activate();
win.Topmost = true;
win.Topmost = false;
win.Focus();
}
}
catch { }
}
else
this.Focus();
}
These steps will works fine and will bring to front all other windows into their parents window.
Just wanted to add another solution to this question. This implementation works for my scenario, where CaliBurn is responsible for displaying the main Window.
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<IMainWindowViewModel>();
Application.MainWindow.Topmost = true;
Application.MainWindow.Activate();
Application.MainWindow.Activated += OnMainWindowActivated;
}
private static void OnMainWindowActivated(object sender, EventArgs e)
{
var window = sender as Window;
if (window != null)
{
window.Activated -= OnMainWindowActivated;
window.Topmost = false;
window.Focus();
}
}
The problem could be that the thread calling your code from the hook hasn't been initialized by the runtime so calling runtime methods don't work.
Perhaps you could try doing an Invoke to marshal your code on to the UI thread to call your code that brings the window to the foreground.
If you are trying to hide the window, for example you minimize the window, I have found that using
this.Hide();
will hide it correctly, then simply using
this.Show();
will then show the window as the top most item once again.
Remember not to put the code that shows that window inside a PreviewMouseDoubleClick handler as the active window will switch back to the window who handled the event.
Just put it in the MouseDoubleClick event handler or stop bubbling by setting e.Handled to True.
In my case i was handling the PreviewMouseDoubleClick on a Listview and was not setting the e.Handled = true then it raised the MouseDoubleClick event witch sat focus back to the original window.
This is a combination of a few suggestions above that works well and is simple. It only comes to front when those events fire, so any window that pops up after the event will stay on top of course.
public partial class MainWindow : Window
{
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
Topmost = true;
Topmost = false;
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
Topmost = true;
Topmost = false;
}
....
}
I wanted to create a launcher with the keyboard hook and had the same problem.
After much trial and error, this solved the problem.
void Active()
{
MainWindow0.Show();
MainWindow0.Focus();
MainWindow0.Activate();
MainWindow0.WindowState = WindowState.Normal;
}
void Deactive()
{
MainWindow0.Hide();
MainWindow0.WindowState = WindowState.Minimized;
}
I built an extension method to make for easy reuse.
using System.Windows.Forms;
namespace YourNamespace{
public static class WindowsFormExtensions {
public static void PutOnTop(this Form form) {
form.Show();
form.Activate();
}// END PutOnTop()
}// END class
}// END namespace
Call in the Form Constructor
namespace YourNamespace{
public partial class FormName : Form {
public FormName(){
this.PutOnTop();
InitalizeComponents();
}// END Constructor
} // END Form
}// END namespace

Categories