Show a Form Without Stealing Focus

Show a 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;
}
}

How to keep a Form always on top without stealing focus from the active Window?

  1. Make a standard Form, set its FormBorderStyle = none. Make it TopMost (this setting is another topic per se, I'm no going to discuss it here).
  2. Override CreateParams to set the WS_EX_NOACTIVATE and WS_EX_TOOLWINDOW extended styles. This prevents the Form from being activated when mouse events are generated inside its surface (see the docs about these styles).
  3. Add some non-selectable Button Controls to it (the ButtonNoSel Control shown below) and set their Tag property to the Unicode char corresponding to the Emoji image these buttons show.
  4. Add the same Click handler to all the Buttons.

These Buttons, when clicked, simply use SendKeys::Send() (a.k.a. SendInput()) to send the selected Unicode char to the foreground Window, casting to string the Tag property value.

This is how it works (setting the Emoji to a Web Page shown by FireFox):

Sample Image



using namespace System;
using namespace System::ComponentModel;
using namespace System::Windows::Forms;
using namespace System::Drawing;

public ref class frmKeyBoard : public System::Windows::Forms::Form
{
public:
frmKeyBoard(void) { InitializeComponent(); }

// [...] Initialization...

protected:
property System::Windows::Forms::CreateParams^ CreateParams {
virtual System::Windows::Forms::CreateParams^ get() override {
auto cp = Form::CreateParams;
cp->ExStyle |= (WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW);
return cp;
}
}

// Event handler for all the Buttons
private:
System::Void buttonNoSelAll_Click(System::Object^ sender, System::EventArgs^ e) {
Control^ ctl = safe_cast<Control^>(sender);
SendKeys::Send(ctl->Tag->ToString());
}
};

Add this simple Custom Control to the Project.

This Control simply uses Control.SetStyle, setting ControlStyles::Selectable = false to prevent the child Control to become the ActiveControl when interacted with, since it doesn't receive the focus.

using namespace System;
using namespace System::Windows::Forms;
using namespace System::ComponentModel;

namespace CustomControls {
[ToolboxItem(true)]
public ref class ButtonNoSel : public System::Windows::Forms::Button
{
public:
ButtonNoSel(void) {
this->InitializeComponent();
this->SetStyle(ControlStyles::Selectable, false);
}

private:
void InitializeComponent(void) {
this->UseVisualStyleBackColor = true;
}

protected:
~ButtonNoSel() { }
};
}

Note that this Form must run on its own thread.

If you need to show this Form from another one, use Task.Run() to show it as a Dialog Window, calling ShowDialog(). This will start the Message Loop.

For example, from a Button.Click handler of another Form (here, named MainForm).

private: 
void ShowKeyboard() {
frmKeyBoard^ fk = gcnew frmKeyBoard();
fk->ShowDialog();
delete fk;
}

private:
System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
Task::Run(gcnew Action(this, &MainForm::ShowKeyboard));
}

Show a form without taking focus

If we are talking about wfp, try setting the property ShowActivated="False"

Show a window without setting focus

This article shows how to "Show a Form without stealing focus" by overriding the CreateParams method.

Opening a form in C# without focus

protected override bool ShowWithoutActivation
{
get
{
return true;
}
}

Override this property in your form code and it should do the trick for you.

Show a Form behind everything else, and without stealing focus?

A little bit of PInvoke using SetWindowPos function

public static class HWND {
public static readonly IntPtr
NOTOPMOST = new IntPtr(-2),
BROADCAST = new IntPtr(0xffff),
TOPMOST = new IntPtr(-1),
TOP = new IntPtr(0),
BOTTOM = new IntPtr(1);
}

public static class SWP {
public static readonly int
NOSIZE = 0x0001,
NOMOVE = 0x0002,
NOZORDER = 0x0004,
NOREDRAW = 0x0008,
NOACTIVATE = 0x0010,
DRAWFRAME = 0x0020,
FRAMECHANGED = 0x0020,
SHOWWINDOW = 0x0040,
HIDEWINDOW = 0x0080,
NOCOPYBITS = 0x0100,
NOOWNERZORDER = 0x0200,
NOREPOSITION = 0x0200,
NOSENDCHANGING = 0x0400,
DEFERERASE = 0x2000,
ASYNCWINDOWPOS = 0x4000;
}

[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

private void button1_Click(object sender, EventArgs e) {
RunnerForm frm = new RunnerForm();
SetWindowPos(frm.Handle, HWND.BOTTOM, 0, 0, 0, 0, SWP.SHOWWINDOW | SWP.NOMOVE | SWP.NOOWNERZORDER | SWP.NOSIZE | SWP.NOACTIVATE);
}

How do I prevent the original form from losing focus when I show another form?

Cody Gray 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 ;)

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);
frm.TopMost = false;
}


Related Topics



Leave a reply



Submit