Opening a WinForms Form with TopMost = true but not having it steal focus?

穿精又带淫゛_ 提交于 2019-12-17 09:47:58

问题


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):

https://connect.microsoft.com/VisualStudio/feedback/details/401311/showwithoutactivation-is-not-supported-with-topmost




回答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.



来源:https://stackoverflow.com/questions/3729899/opening-a-winforms-form-with-topmost-true-but-not-having-it-steal-focus

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!