在没有窃取焦点的情况下显示表单?

Mat*_*ías 135 .net c# winforms

我正在使用表单来显示通知(它出现在屏幕的右下角),但是当我显示此表单时,它会从主表单中窃取焦点.有没有办法在不窃取焦点的情况下显示此"通知"表单?

Mar*_*nte 159

嗯,是不是简单地重写了Form.ShowWithoutActivation?

protected override bool ShowWithoutActivation
{
  get { return true; }
}
Run Code Online (Sandbox Code Playgroud)

如果您不希望用户也单击此通知窗口,则可以覆盖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;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 并关闭TopMost. (23认同)
  • 如果您确实想要TopMost,请参阅[其他答案](http://stackoverflow.com/a/156159/33080). (4认同)
  • ShowWithoutActivation,不敢相信我没找到它,浪费了整整一个下午! (3认同)
  • 我还需要设置`form1.Enabled = false`以防止内部控件窃取焦点 (2认同)
  • "WS_EX_NOACTIVATE"和"WS_EX_TOOLWINDOW"的值分别为"0x08000000"和"0x00000080". (2认同)

The*_*edi 68

PInvoke.netShowWindow方法中偷走了:

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);
}
Run Code Online (Sandbox Code Playgroud)

(Alex Lyman回答了这个问题,我只是通过直接粘贴代码来扩展它.拥有编辑权限的人可以在那里复制它并删除它,我所关心的所有;))

  • 我觉得令人难以置信的是,我们仍然需要链接到外部DLL文件以与表单进行交互.我们在.NET框架版本4!是时候把它包装好了. (50认同)
  • 接受的答案是不正确的.寻找ShowWithoutActivation (9认同)

Ale*_*man 14

如果您愿意使用Win32 P/Invoke,那么您可以使用ShowWindow方法(第一个代码示例完全符合您的要求).


Ren*_*Pet 12

这对我有用.它提供TopMost但没有焦点窃取.

    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;
       }
    }
Run Code Online (Sandbox Code Playgroud)

请记住在Visual Studio设计器或其他地方省略设置TopMost.

这是从这里偷来的,错误的,借来的(点击解决方法):

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

  • 最重要+没有重点的作品,它看起来是所有答案中最干净的。 (2认同)

Mat*_*ley 9

这样做似乎是一个黑客,但似乎工作:

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
Run Code Online (Sandbox Code Playgroud)

编辑:注意,这只会提高已经创建的表单而不会窃取焦点.


Mic*_*cah 9

来自Alex Lyman的pinvoke.net的示例代码/ TheSoftwareJedi的答案将使窗口成为"最顶层"的窗口,这意味着在弹出窗口后你无法将其置于正常窗口之后.鉴于Matias对他想要使用它的描述,这可能是他想要的.但是如果您希望用户能够在弹出窗口后将窗口置于其他窗口之后,则只需在示例中使用HWND_TOP(0)而不是HWND_TOPMOST(-1).


小智 6

在WPF中你可以像这样解决它:

在窗口中放置以下属性:

<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>
Run Code Online (Sandbox Code Playgroud)

最后一个属性是你需要ShowActivated ="False"的属性.