找到你要的答案

Q:Popup in winforms (but not registered as a new standalone window)

Q:弹出在WinForms(但没有注册为一个新的独立窗口)

I would like to display information messages on the screen, over my main form.

The problem I have is that I don't want this to be registered in windows as a new form, since this shows up in the taskbar when switching between apps. I have many of these info boxes popping up to notify you of events.

The idea is that it should work similar to a dialogbox (don't get registered as a standalone form) with the exception that it don't expect you to interact with the dialog.

So far I use the following:

var notification = new Notification();
notification.ShowInTaskbar = false;
notification.Show();

Can anyone please point out how you can prevent this window from being registered as a standalone window

EDIT: Thanks for the suggested link @shf301 : Best way to hide a window from the Alt-Tab program switcher?

I had a look at it but it's unrelated. The link explains how to hide an application from the alt-tab menu. In this example I don't want to hide my application, I simply want to show popups without them being registered as new windows.

我想在屏幕上显示信息信息,在我的主要形式。

我的问题是,我不希望这是注册在Windows作为一种新的形式,因为这显示在任务栏上的应用程序之间切换时。我有许多这些信息箱弹出通知你的事件。

这个想法是,它应该工作类似一个对话框(不要注册为独立的形式)与异常,它不要求你和对话互动。

到目前为止我使用以下:

var notification = new Notification();
notification.ShowInTaskbar = false;
notification.Show();

任何人都可以指出你如何阻止这个窗口被注册为一个独立的窗口

EDIT: Thanks for the suggested link @shf301 : Best way to hide a window from the Alt-Tab program switcher?

我看了一下,但它无关。的链接解释了如何躲避ALT标签菜单的应用。在这个例子中我不想隐藏我的申请,我只是想显示弹出窗口不被注册为新的Windows。

answer1: 回答1:

This is not so easy because basically popups are not supported in windows forms. Although windows forms is based on win32 and in win32 popup are supported. If you accept a few tricks, following code will set you going with a popup. You decide if you want to put it to good use : (This is the way for instance tooltips are made)

class PopupWindow : Control
{
    private const int WM_ACTIVATE = 0x0006;
    private const int WM_MOUSEACTIVATE = 0x0021;

    private Control ownerControl;

    public PopupWindow(Control ownerControl)
        :base()
    {
        this.ownerControl = ownerControl;
        base.SetTopLevel(true);
    }

    public Control OwnerControl
    {
        get
        {
            return (this.ownerControl as Control);
        }
        set
        {
            this.ownerControl = value;
        }
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams createParams = base.CreateParams;

            createParams.Style = WindowStyles.WS_POPUP |
                                 WindowStyles.WS_VISIBLE |
                                 WindowStyles.WS_CLIPSIBLINGS |
                                 WindowStyles.WS_CLIPCHILDREN |
                                 WindowStyles.WS_MAXIMIZEBOX |
                                 WindowStyles.WS_BORDER;
            createParams.ExStyle = WindowsExtendedStyles.WS_EX_LEFT |
                                   WindowsExtendedStyles.WS_EX_LTRREADING |
                                   WindowsExtendedStyles.WS_EX_RIGHTSCROLLBAR | 
                                   WindowsExtendedStyles.WS_EX_TOPMOST;

            createParams.Parent = (this.ownerControl != null) ? this.ownerControl.Handle : IntPtr.Zero;
            return createParams;
        }
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    public static extern IntPtr SetActiveWindow(HandleRef hWnd);

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_ACTIVATE:
                {
                    if ((int)m.WParam == 1)
                    {
                        //window is being activated
                        if (ownerControl != null)
                        {
                            SetActiveWindow(new HandleRef(this, ownerControl.FindForm().Handle));
                        }
                    }
                    break;
                }
            case WM_MOUSEACTIVATE:
                {
                    m.Result = new IntPtr(MouseActivate.MA_NOACTIVATE);
                    return;
                    //break;
                }
        }
        base.WndProc(ref m);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        e.Graphics.FillRectangle(SystemBrushes.Info, 0, 0, Width, Height);
        e.Graphics.DrawString((ownerControl as VerticalDateScrollBar).FirstVisibleDate.ToLongDateString(), this.Font, SystemBrushes.InfoText, 2, 2);
    }
}

Experiment with it a bit, you have to play around with its position and its size. Use it wrong and nothing shows.

This is not so easy because basically popups are not supported in windows forms. Although windows forms is based on win32 and in win32 popup are supported. If you accept a few tricks, following code will set you going with a popup. You decide if you want to put it to good use : (This is the way for instance tooltips are made)

class PopupWindow : Control
{
    private const int WM_ACTIVATE = 0x0006;
    private const int WM_MOUSEACTIVATE = 0x0021;

    private Control ownerControl;

    public PopupWindow(Control ownerControl)
        :base()
    {
        this.ownerControl = ownerControl;
        base.SetTopLevel(true);
    }

    public Control OwnerControl
    {
        get
        {
            return (this.ownerControl as Control);
        }
        set
        {
            this.ownerControl = value;
        }
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams createParams = base.CreateParams;

            createParams.Style = WindowStyles.WS_POPUP |
                                 WindowStyles.WS_VISIBLE |
                                 WindowStyles.WS_CLIPSIBLINGS |
                                 WindowStyles.WS_CLIPCHILDREN |
                                 WindowStyles.WS_MAXIMIZEBOX |
                                 WindowStyles.WS_BORDER;
            createParams.ExStyle = WindowsExtendedStyles.WS_EX_LEFT |
                                   WindowsExtendedStyles.WS_EX_LTRREADING |
                                   WindowsExtendedStyles.WS_EX_RIGHTSCROLLBAR | 
                                   WindowsExtendedStyles.WS_EX_TOPMOST;

            createParams.Parent = (this.ownerControl != null) ? this.ownerControl.Handle : IntPtr.Zero;
            return createParams;
        }
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    public static extern IntPtr SetActiveWindow(HandleRef hWnd);

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_ACTIVATE:
                {
                    if ((int)m.WParam == 1)
                    {
                        //window is being activated
                        if (ownerControl != null)
                        {
                            SetActiveWindow(new HandleRef(this, ownerControl.FindForm().Handle));
                        }
                    }
                    break;
                }
            case WM_MOUSEACTIVATE:
                {
                    m.Result = new IntPtr(MouseActivate.MA_NOACTIVATE);
                    return;
                    //break;
                }
        }
        base.WndProc(ref m);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        e.Graphics.FillRectangle(SystemBrushes.Info, 0, 0, Width, Height);
        e.Graphics.DrawString((ownerControl as VerticalDateScrollBar).FirstVisibleDate.ToLongDateString(), this.Font, SystemBrushes.InfoText, 2, 2);
    }
}

实验一点,你必须玩它的位置和它的大小左右。使用错误,没有显示。

answer2: 回答2:

The only way that I know to show a window within a program (without it appearing in the taskbar) is to use a Multiple Document Interface (MDI). This is somewhat complicated but can do exactly the task you want: showing a window within a window.

More info on MDIs in .NET: http://csharp.net-informations.com/gui/cs-mdi-form.htm

我知道一个窗口内显示程序的唯一途径(没有出现在任务栏)是使用多文档界面(MDI)。这有点复杂,但可以完成您想要的任务:在窗口中显示窗口。

在MDIS更多信息。网:http://csharp.net-informations.com/gui/cs-mdi-form.htm

answer3: 回答3:

@Philip's answer is correct.

I had to add the following:

    internal class WindowsExtendedStyles
    {

        public const int WS_EX_DLGMODALFRAME = 0x00000001;

        public const int WS_EX_NOPARENTNOTIFY = 0x00000004;

        public const int WS_EX_TOPMOST = 0x00000008;

        public const int WS_EX_ACCEPTFILES = 0x00000010;

        public const int WS_EX_TRANSPARENT = 0x00000020;

        public const int WS_EX_MDICHILD = 0x00000040;

        public const int WS_EX_TOOLWINDOW = 0x00000080;

        public const int WS_EX_WINDOWEDGE = 0x00000100;

        public const int WS_EX_CLIENTEDGE = 0x00000200;

        public const int WS_EX_CONTEXTHELP = 0x00000400;

        public const int WS_EX_RIGHT = 0x00001000;

        public const int WS_EX_LEFT = 0x00000000;

        public const int WS_EX_RTLREADING = 0x00002000;

        public const int WS_EX_LTRREADING = 0x00000000;

        public const int WS_EX_LEFTSCROLLBAR = 0x00004000;

        public const int WS_EX_RIGHTSCROLLBAR = 0x00000000;

        public const int WS_EX_CONTROLPARENT = 0x00010000;

        public const int WS_EX_STATICEDGE = 0x00020000;

        public const int WS_EX_APPWINDOW = 0x00040000;

        public const int WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE;

        public const int WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;

        public const int WS_EX_LAYERED = 0x00080000;

        public const int WS_EX_NOINHERITLAYOUT = 0x00100000; // Disable inheritence of mirroring by children

        public const int WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring

        public const int WS_EX_COMPOSITED = 0x02000000;

        public const int WS_EX_NOACTIVATE = 0x08000000;

    }

    internal class MouseActivate
    {

        public const int MA_ACTIVATE = 1;

        public const int MA_ACTIVATEANDEAT = 2;

        public const int MA_NOACTIVATE = 3;

        public const int MA_NOACTIVATEANDEAT = 4;

    }

菲利普的回答是正确的。

我必须添加以下内容:

    internal class WindowsExtendedStyles
    {

        public const int WS_EX_DLGMODALFRAME = 0x00000001;

        public const int WS_EX_NOPARENTNOTIFY = 0x00000004;

        public const int WS_EX_TOPMOST = 0x00000008;

        public const int WS_EX_ACCEPTFILES = 0x00000010;

        public const int WS_EX_TRANSPARENT = 0x00000020;

        public const int WS_EX_MDICHILD = 0x00000040;

        public const int WS_EX_TOOLWINDOW = 0x00000080;

        public const int WS_EX_WINDOWEDGE = 0x00000100;

        public const int WS_EX_CLIENTEDGE = 0x00000200;

        public const int WS_EX_CONTEXTHELP = 0x00000400;

        public const int WS_EX_RIGHT = 0x00001000;

        public const int WS_EX_LEFT = 0x00000000;

        public const int WS_EX_RTLREADING = 0x00002000;

        public const int WS_EX_LTRREADING = 0x00000000;

        public const int WS_EX_LEFTSCROLLBAR = 0x00004000;

        public const int WS_EX_RIGHTSCROLLBAR = 0x00000000;

        public const int WS_EX_CONTROLPARENT = 0x00010000;

        public const int WS_EX_STATICEDGE = 0x00020000;

        public const int WS_EX_APPWINDOW = 0x00040000;

        public const int WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE;

        public const int WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;

        public const int WS_EX_LAYERED = 0x00080000;

        public const int WS_EX_NOINHERITLAYOUT = 0x00100000; // Disable inheritence of mirroring by children

        public const int WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring

        public const int WS_EX_COMPOSITED = 0x02000000;

        public const int WS_EX_NOACTIVATE = 0x08000000;

    }

    internal class MouseActivate
    {

        public const int MA_ACTIVATE = 1;

        public const int MA_ACTIVATEANDEAT = 2;

        public const int MA_NOACTIVATE = 3;

        public const int MA_NOACTIVATEANDEAT = 4;

    }
answer4: 回答4:

If this notifications you are looking for need to support user interaction, you may consider showing a popup using the ToolStripDrownDown control and hosting a control in it by the ToolStripControlHost.

Or of they are just supposed to display information, with no user interaction, use a Tooltip (with Balloon = true) control. You may also customize it's visuals by custom drawing it's content.

如果这个通知你正在寻找需要支持用户交互,你可以考虑显示一个弹出窗口使用toolstripdrowndown控制和主机控制在其由ToolStripControlHost。

或者他们只是想显示信息,没有用户交互,使用工具提示(用气球= true)控制。您还可以自定义它的视觉效果的自定义绘制它的内容。

c#  winforms