I have a form that pops up on a user's screen and has TopMost=true
, but it steals the focus. How can I get it to not steal focus when it first appears?
问题:
回答1:
Paste this code in your form:
protected override bool ShowWithoutActivation { get { return true; } }
回答2:
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):
回答3:
You can do it like this:
private const int SW_SHOWNOACTIVATE = 4; private const int HWND_TOPMOST = -1; private const uint SWP_NOACTIVATE = 0x0010; [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowPos")] private 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 [System.Runtime.InteropServices.DllImport("user32.dll")] private static extern bool ShowWindow(System.IntPtr hWnd, int nCmdShow); public static void ShowInactiveTopmost(System.Windows.Forms.Form frm) { try { ShowWindow(frm.Handle, SW_SHOWNOACTIVATE); SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST, frm.Left, frm.Top, frm.Width, frm.Height, SWP_NOACTIVATE); } catch (System.Exception ex) { // error handling } }
回答4:
I tested the below code using a timer on form1 to instantiate and show form2 with form1 as owner.
In form2's Shown event I then set focus to the owner, which is the current active form.
I have a textbox on form1 and was able to continuesly write in the textbox without loosing focus during this process.
My timer code in form1:
private void timer1_Tick(object sender, EventArgs e) { Form2 popup = new Form2(); popup.TopMost = true; popup.Show(this); timer1.Enabled = false; }
My code in the Shown event of form2:
private void Form2_Shown(object sender, EventArgs e) { this.Owner.Focus(); }
You can do this or simply set TopMost to false and use the override of ShowWithoutActivation as Hans Passant stated.
Edit: (Or use p/invoke as seen in Hans Passant's additional comment I missed while I wrote this)
回答5:
I came across the same problem. I'm not using C# but C++. I figure this could be useful anyways:
Using windows.h:
BOOL WINAPI SetWindowPos( __in HWND hWnd, __in_opt HWND hWndInsertAfter, __in int X, __in int Y, __in int cx, __in int cy, __in UINT uFlags );
Passing the flag SWP_NOACTIVATE to the uFlags argument worked for me.
回答6:
You can set:
this.TopMost = True;
on Load event of that form.
It's OK with me!
回答7:
Instead of writing .setfocus()
in _activated
event; write it to .shown
event of the form.