How do I create an "unfocusable" form in C#?
I'm looking to create a form in C# that cannot accept focus, i.e. when I click a button on the form, focus is not stolen from the application that currently has the focus.
See the Windows on-screen keyboard for an example of this. Note that when you click a button, the focus is not taken from the application you're currently using.
How can I implement this behaviour?
开发者_开发百科Update:
Turns out it's as simple as overriding the CreateParams
property and adding WS_EX_NOACTIVATE
to the extended window style. Thanks for pointing me in the right direction!
Unfortunately this has the undesirable side-effect that it messes with form movement, i.e. you can still drag and drop the form around the screen but the window's border is not displayed while dragging so it's difficult to precisely position it.
If anyone knows how to solve this it would be appreciated.
To disable activation by mouse:
class NonFocusableForm : Form
{
protected override void DefWndProc(ref Message m)
{
const int WM_MOUSEACTIVATE = 0x21;
const int MA_NOACTIVATE = 0x0003;
switch(m.Msg)
{
case WM_MOUSEACTIVATE:
m.Result = (IntPtr)MA_NOACTIVATE;
return;
}
base.DefWndProc(ref m);
}
}
To show form without activation (the only one way that worked for me in case of borderless form):
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr handle, int flags);
NativeMethods.ShowWindow(form.Handle, 8);
Standard way to do this (seems like it doesn't work for all form styles):
protected override bool ShowWithoutActivation
{
get { return true; }
}
If there are other ways of activating the form, they can be suppressed in similar manner.
This is the "NoFocusForm" I use:
public class NoFocusForm : Form
{
/// From MSDN <see cref="https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles"/>
/// A top-level window created with this style does not become the
/// foreground window when the user clicks it. The system does not
/// bring this window to the foreground when the user minimizes or
/// closes the foreground window. The window should not be activated
/// through programmatic access or via keyboard navigation by accessible
/// technology, such as Narrator. To activate the window, use the
/// SetActiveWindow or SetForegroundWindow function. The window does not
/// appear on the taskbar by default. To force the window to appear on
/// the taskbar, use the WS_EX_APPWINDOW style.
private const int WS_EX_NOACTIVATE = 0x08000000;
public NoFocusForm()
{
// my other initiate stuff
}
/// <summary>
/// Prevent form from getting focus
/// </summary>
protected override CreateParams CreateParams
{
get
{
var createParams = base.CreateParams;
createParams.ExStyle |= WS_EX_NOACTIVATE;
return createParams;
}
}
}
精彩评论