1

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.

Community
  • 1
  • 1
z0mbi3
  • 336
  • 4
  • 14

4 Answers4

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

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.

Philip Stuyck
  • 7,344
  • 3
  • 28
  • 39
  • Thanks Philip for the quick and excellent answer. Anyone who uses it .. please see my post below for additional code. – z0mbi3 May 03 '15 at 19:55
1

@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;

    }
z0mbi3
  • 336
  • 4
  • 14
0

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.

Mehrzad Chehraz
  • 5,092
  • 2
  • 17
  • 28