简体   繁体   中英

AppBar Multi-Monitor

I've made a simple appBar with just a label on the top of the screen that shrinks the desktop but I'm having trouble making it appear my second monitor. I've been searching around but everything I've found has been for WPF. These are most likely the areas where I've made a mistake but if there is any other code you need to see, just let me know.

private void InitializeComponent()
{
    this.ClientSize = new System.Drawing.Size(SystemInformation.WorkingArea.Width, -1);
    this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
    this.Name = "MainForm";
    this.Text = "AppBar";
    this.Closing += new System.ComponentModel.CancelEventHandler(this.OnClosing);
    this.Load += new System.EventHandler(this.OnLoad);
    this.BackColor = Color.Green;
    this.Padding = new Padding(0, 0, 0, 0);
    Label label1 = new Label();
    label1.Text = "TEXT";
    label1.Width = 270;
    label1.Margin = new Padding(0,0,0,0);
    label1.Padding = new Padding(0,0,0,0);
    label1.TextAlign = ContentAlignment.MiddleCenter;
    label1.ForeColor = Color.White;
    label1.Font = new Font(FontFamily.GenericSansSerif, 12,FontStyle.Regular);
    label1.Location = new Point((SystemInformation.WorkingArea.Width - 270) / 2, 0);
    this.Controls.Add(label1);
}

private void ABSetPos()
{
    APPBARDATA abd = new APPBARDATA();
    abd.cbSize = Marshal.SizeOf(abd);
    abd.hWnd = this.Handle;
    abd.uEdge = (int)ABEdge.ABE_TOP;

    if (abd.uEdge == (int)ABEdge.ABE_LEFT || abd.uEdge == (int)ABEdge.ABE_RIGHT)
    {
        abd.rc.top = 0;
        abd.rc.bottom = SystemInformation.PrimaryMonitorSize.Height;
        if (abd.uEdge == (int)ABEdge.ABE_LEFT)
        {
            abd.rc.left = 0;
            abd.rc.right = Size.Width;
        }
        else
        {
            abd.rc.right = SystemInformation.PrimaryMonitorSize.Width;
            abd.rc.left = abd.rc.right - Size.Width;
        }

    }
    else
    {
        abd.rc.left = 0;
        abd.rc.right = SystemInformation.PrimaryMonitorSize.Width;
        if (abd.uEdge == (int)ABEdge.ABE_TOP)
        {
            abd.rc.top = 0;
            abd.rc.bottom = Size.Height;
        }
        else
        {
            abd.rc.bottom = SystemInformation.PrimaryMonitorSize.Height;
            abd.rc.top = abd.rc.bottom - Size.Height;
        }
    }

You can use a different screen by iterating over the Screen.AllScreens array. For example, here is how you would get the first non-primary monitor:

Screen nonPrimaryScreen = Screen.AllScreens.FirstOrDefault(x => !x.Primary);

Then everywhere you are using SystemInformation.WorkingArea (which always uses the primary screen), you can use:

nonPrimaryScreen.WorkingArea

Assuming nonPrimaryScreen != null ... of course.

EDIT:

Instead of duplicating code, make it all more generic:

public static Rectangle GetWorkingArea() {
    if (UseWantsItOnPrimaryScreen) {
        return SystemInformation.WorkingArea;
    }
    else {
        return Screen.AllScreens.FirstOrDefault(x => !x.Primary).WorkingArea;
    }
}
 #region APPBAR

    [StructLayout(LayoutKind.Sequential)]
    struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    [StructLayout(LayoutKind.Sequential)]
    struct APPBARDATA
    {
        public int cbSize;
        public IntPtr hWnd;
        public int uCallbackMessage;
        public int uEdge;
        public RECT rc;
        public IntPtr lParam;
    }

    enum ABMsg : int
    {
        ABM_NEW = 0,
        ABM_REMOVE = 1,
        ABM_QUERYPOS = 2,
        ABM_SETPOS = 3,
        ABM_GETSTATE = 4,
        ABM_GETTASKBARPOS = 5,
        ABM_ACTIVATE = 6,
        ABM_GETAUTOHIDEBAR = 7,
        ABM_SETAUTOHIDEBAR = 8,
        ABM_WINDOWPOSCHANGED = 9,
        ABM_SETSTATE = 10
    }

    enum ABNotify : int
    {
        ABN_STATECHANGE = 0,
        ABN_POSCHANGED,
        ABN_FULLSCREENAPP,
        ABN_WINDOWARRANGE
    }

    enum ABEdge : int
    {
        ABE_LEFT = 0,
        ABE_TOP,
        ABE_RIGHT,
        ABE_BOTTOM
    }

    private bool fBarRegistered = false;

    [DllImport("SHELL32", CallingConvention = CallingConvention.StdCall)]
    static extern uint SHAppBarMessage(int dwMessage, ref APPBARDATA pData);
    [DllImport("USER32")]
    static extern int GetSystemMetrics(int Index);
    [DllImport("User32.dll", ExactSpelling = true,
        CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern bool MoveWindow
        (IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);
    [DllImport("User32.dll", CharSet = CharSet.Auto)]
    private static extern int RegisterWindowMessage(string msg);
    private int uCallBack;

    private void RegisterBar()
    {
        APPBARDATA abd = new APPBARDATA();
        abd.cbSize = Marshal.SizeOf(abd);
        abd.hWnd = this.Handle;
        if (!fBarRegistered)
        {
            uCallBack = RegisterWindowMessage("AppBarMessage");
            abd.uCallbackMessage = uCallBack;

            uint ret = SHAppBarMessage((int)ABMsg.ABM_NEW, ref abd);
            fBarRegistered = true;

            ABSetPos();
        }
        else
        {
            SHAppBarMessage((int)ABMsg.ABM_REMOVE, ref abd);
            fBarRegistered = false;
        }
    }

    private void ABSetPos()
    {

        APPBARDATA abd = new APPBARDATA();
        abd.cbSize = Marshal.SizeOf(abd);
        abd.hWnd = this.Handle;
        abd.uEdge = (int)ABEdge.ABE_TOP;

        if (abd.uEdge == (int)ABEdge.ABE_LEFT || abd.uEdge == (int)ABEdge.ABE_RIGHT)
        {
            abd.rc.top = this.GetScreenObject(ScreenName).Bounds.Top; //0;
            abd.rc.bottom = this.GetScreenObject(ScreenName).Bounds.Top + this.GetScreenObject(ScreenName).Bounds.Height; //SystemInformation.PrimaryMonitorSize.Height;
            if (abd.uEdge == (int)ABEdge.ABE_LEFT)
            {
                abd.rc.left = this.GetScreenObject(ScreenName).Bounds.Left;//0;
                abd.rc.right = Size.Width;
            }
            else
            {
                abd.rc.right = this.GetScreenObject(ScreenName).Bounds.Left + this.GetScreenObject(ScreenName).Bounds.Width; // SystemInformation.PrimaryMonitorSize.Width;
                abd.rc.left = abd.rc.right - Size.Width;
            }

        }
        else
        {
            abd.rc.left = this.GetScreenObject(ScreenName).Bounds.Left; //0;
            abd.rc.right = this.GetScreenObject(ScreenName).Bounds.Left+this.GetScreenObject(ScreenName).Bounds.Width; //SystemInformation.PrimaryMonitorSize.Width;
            if (abd.uEdge == (int)ABEdge.ABE_TOP)
            {
                abd.rc.top = this.GetScreenObject(ScreenName).Bounds.Top;  //0 nebo -1080                    
                abd.rc.bottom = Size.Height;
            }
            else
            {
                abd.rc.bottom = this.GetScreenObject(ScreenName).Bounds.Top + this.GetScreenObject(ScreenName).Bounds.Height; //SystemInformation.PrimaryMonitorSize.Height;
                abd.rc.top = abd.rc.bottom - Size.Height;
            }
        }

        // Query the system for an approved size and position. 
        SHAppBarMessage((int)ABMsg.ABM_QUERYPOS, ref abd);

        // Adjust the rectangle, depending on the edge to which the 
        // appbar is anchored. 
        switch (abd.uEdge)
        {
            case (int)ABEdge.ABE_LEFT:
                abd.rc.right = abd.rc.left + Size.Width;
                break;
            case (int)ABEdge.ABE_RIGHT:
                abd.rc.left = abd.rc.right - Size.Width;
                break;
            case (int)ABEdge.ABE_TOP:
                abd.rc.bottom = abd.rc.top + Size.Height;
                break;
            case (int)ABEdge.ABE_BOTTOM:
                abd.rc.top = abd.rc.bottom - Size.Height;
                break;
        }

        // Pass the final bounding rectangle to the system. 
        SHAppBarMessage((int)ABMsg.ABM_SETPOS, ref abd);

        // Move and size the appbar so that it conforms to the 
        // bounding rectangle passed to the system. 
        MoveWindow(abd.hWnd, abd.rc.left, abd.rc.top,
            abd.rc.right - abd.rc.left, abd.rc.bottom - abd.rc.top, true);
    }

    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        if (m.Msg == uCallBack)
        {
            switch (m.WParam.ToInt32())
            {
                case (int)ABNotify.ABN_POSCHANGED:
                    ABSetPos();
                    break;
            }
        }

        try
        {
            base.WndProc(ref m);
        }
        catch (Exception E) { }
    }

    protected override System.Windows.Forms.CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.Style &= (~0x00C00000); // WS_CAPTION
            cp.Style &= (~0x00800000); // WS_BORDER
            //cp.ExStyle = 0x00000080 | 0x00000008 | 0x20; // WS_EX_TOOLWINDOW | WS_EX_TOPMOST  
            //cp.ExStyle &= 0x20;
            cp.ExStyle |= 0x00000008 | 0x00000080;
            //cp.ExStyle &= 0x00000080 ; // WS_EX_TOOLWINDOW | WS_EX_TOPMOST  
            return cp;
        }
    }

    private void OnLoad(object sender, System.EventArgs e)
    {
        RegisterBar();
    }

    private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        RegisterBar();
    }

    #endregion
private Screen GetScreenObject(String Name)
{
    logger.Info(GlobalModulename + "@ ScreenList::looking for screen:"+Name);
    if ((Name == "Primary"))
    {
        bool ExpectedParameter = true;
        foreach (var screen in Screen.AllScreens)
        {
            // For each screen, add the screen properties to a list box.
            logger.Info(GlobalModulename + "@ ScreenList::("+screen.DeviceName.ToString()+")Primary Screen: " + screen.Primary.ToString());
            if (screen.Primary==ExpectedParameter)
            {
                return screen;
            }
        }
    }
    if ((Name == "Secondary"))
    {
        bool ExpectedParameter = false;
        foreach (var screen in Screen.AllScreens)
        {
            // For each screen, add the screen properties to a list box.
            logger.Info(GlobalModulename + "@ ScreenList::(" + screen.DeviceName.ToString() + ")Primary Screen: " + screen.Primary.ToString());
            if (screen.Primary == ExpectedParameter)
            {
                return screen;
            }
        }
    }

    // konkretni jmeno obrazovky tak jak je to v systemu
    try
    {
        foreach (var screen in Screen.AllScreens)
        {
            // For each screen, add the screen properties to a list box.
            logger.Info("UEFA_Core @ ScreenList::Device Name: " + screen.DeviceName);
            logger.Info("UEFA_Core @ ScreenList::Bounds: " + screen.Bounds.ToString());
            logger.Info("UEFA_Core @ ScreenList::Type: " + screen.GetType().ToString());
            logger.Info("UEFA_Core @ ScreenList::Working Area: " + screen.WorkingArea.ToString());
            logger.Info("UEFA_Core @ ScreenList::Primary Screen: " + screen.Primary.ToString());
            if (screen.DeviceName == Name) return screen;
        }

    }
    catch { }

    // podobne jmeno obrazovky tak jak je to v systemu
    try
    {
        foreach (var screen in Screen.AllScreens)
        {
            // For each screen, add the screen properties to a list box.
            logger.Info("UEFA_Core @ ScreenList::Device Name: " + screen.DeviceName);
            logger.Info("UEFA_Core @ ScreenList::Bounds: " + screen.Bounds.ToString());
            logger.Info("UEFA_Core @ ScreenList::Type: " + screen.GetType().ToString());
            logger.Info("UEFA_Core @ ScreenList::Working Area: " + screen.WorkingArea.ToString());
            logger.Info("UEFA_Core @ ScreenList::Primary Screen: " + screen.Primary.ToString());
            if (screen.DeviceName.Contains(Name)) return screen;
        }

    }
    catch { }

    logger.Info("UEFA_Core @ ScreenList::No screen found by name");
    return Screen.PrimaryScreen;
}

You can compute correct formula for moving your AppBar to second monitor without using anything other than PrimaryMonitorSize . For example for left side AppBar on second monitor you can use this:

if (abd.uEdge == (int)ABEdge.ABE_LEFT)
{
     abd.rc.left = SystemInformation.PrimaryMonitorSize.Width;
     abd.rc.right = SystemInformation.PrimaryMonitorSize.Width + Size.Width;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM