简体   繁体   English

C#Secondary Monitor Bounds问题

[英]C# Secondary Monitor Bounds Issue

I have made a bouncing screensaver in C#. 我在C#中制作了一个弹跳屏幕保护程序。 When there is only a single monitor to display it works perfectly. 当只有一台显示器可以显示时,它可以很好地工作。 However, when I have a dual monitor display the bounds do not work properly. 但是,当我有双显示器显示时,边界无法正常工作。 The position of secondary monitor seems to have an effect and there does not seem to be a right bound (secondary screen is on the right side). 辅助监视器的位置似乎有效,并且似乎没有右边界(辅助屏幕位于右侧)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace LIUScreensaver
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            if (args.Length > 0)
            {
                string firstArg = args[0].ToLower().Trim();
                string secondArg = null;

                //handle cases where arguments are separated by colon
                if (firstArg.Length > 2)
                {
                    secondArg = firstArg.Substring(3).Trim();
                    firstArg = firstArg.Substring(0, 2);
                }
                else if (args.Length > 1)
                {
                    secondArg = args[1];
                }

                if (firstArg == "/c")
                {
                    MessageBox.Show("This screensaver does not allow configuration changes");
                }
                else if (firstArg == "/p")
                {
                    if (secondArg == null)
                     {
                        MessageBox.Show("Sorry, but there was an error.", "Screensaver", MessageBoxButtons.OK, 
                            MessageBoxIcon.Error);
                        return;
                    }
                    IntPtr preview = new IntPtr(long.Parse(secondArg));
                    Application.Run(new ScreensaverForm(preview));
                }
                else if (firstArg == "/s")
                {
                    ShowScreenSaver();
                    Application.Run();
                }
                else
                {
                    MessageBox.Show("Invalid command line argument. \"" + firstArg + "\" is not a valid ", "Screensaver",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }

            }
            else
            {
                MessageBox.Show("There has been an error displaying the screensaver.  Please report this issue.");
            }
        }
        public static void ShowScreenSaver()
        {
            //creates form on each display
            int i = 0;
            Screen[] screen = Screen.AllScreens;
            for (i = 0; i < screen.Length; i++)
            {
                ScreensaverForm screensaver = new ScreensaverForm(screen[i].Bounds);
                screensaver.Show();
            }
        }
    }    
}

//Screensaver form //屏幕保护程序表单

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace LIUScreensaver
{
public partial class ScreensaverForm : Form
{

    [DllImport("user32.dll")]
    static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

    [DllImport("user32.dll", SetLastError = true)]
    static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll")]
    static extern bool GetClientRect(IntPtr hWnd, out Rectangle lpRect);

    private Boolean previewMode = false;
    private int mouseX = 0, mouseY = 0;
    private int imgX = 0, imgY = 0;
    private Boolean bot = true, left = true, right = false, top = false;
    Point p;

    //constructor with no arguments
    public ScreensaverForm()
    {
        InitializeComponent();
    }

    //constructor with bound arguments
    public ScreensaverForm(Rectangle Bounds)
    {
        InitializeComponent();
        this.Bounds = Bounds;
    }

    //preview constructor
    public ScreensaverForm(IntPtr preview)
    {
        InitializeComponent();

        SetParent(this.Handle, preview);

        SetWindowLong(this.Handle, -16, new IntPtr(GetWindowLong(this.Handle, -16) | 0x40000000));

        Rectangle parentRec;
        GetClientRect(preview, out parentRec);
        Size = parentRec.Size;
        Location = new Point(0, 0);

        txtLabel.Font = new System.Drawing.Font("Arial", 6);

        previewMode = true;
    }

    //form load
    private void ScreensaverForm_Load(object sender, EventArgs e)
    {
        Cursor.Hide();
        TopMost = true;
        System.Drawing.Color background = System.Drawing.ColorTranslator.FromHtml("#002668");
        this.BackColor = background;

        moveTimer.Interval = 1;
        moveTimer.Tick += new EventHandler(moveTimer_Tick);
        moveTimer.Start();
    }

    //
    //-----------------------------------------------------------------------------------------------------
    //The following code ends the application and exits the screensaver
    private void ScreensaverForm_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (!previewMode)
        {
            Application.Exit();
        }
    }

    private void ScreensaverForm_MouseMove(object sender, MouseEventArgs e)
    {
        if (!previewMode)
        {
            if (mouseX == 0)
            {
                mouseX = e.X;
                mouseY = e.Y;
            }

            if ((mouseX - e.X) > 5 || (mouseY - e.Y) > 5)
            {
                Application.Exit();
            }
        }
    }

    private void ScreensaverForm_MouseClick(object sender, MouseEventArgs e)
    {
        if (!previewMode)
        {
            Application.Exit();
        }
    }

    //
    //
    //timer to bounce the image across the screen
    private void moveTimer_Tick(object sender, System.EventArgs e)
    {
        // Move text to new location
        bounce();
    }

    //function that moves the image
    private void bounce()
    {

        //Checks boundaries
       if (txtLabel.Location.Y + txtLabel.Image.Height - this.Bounds.Bottom>= 0)
       {
           top = true;
           bot = false;
       }
       if (txtLabel.Location.X + txtLabel.Image.Width - this.Bounds.Right >= 0)
       {
           right = false;
           left = true;
       }
       if (txtLabel.Location.X <= this.Bounds.Left)
       {
           right = true;
           left = false;
       }

       if (txtLabel.Location.Y <= this.Bounds.Top)
       {
           top = false;
           bot = true;
       }

        //moves image
        if (bot == true)
        {
            if (right == true)
            {
                ++imgX;
                ++imgY;

                p.X = imgX;
                p.Y = imgY;
                txtLabel.Location = p;
            }
            else if (left == true)
            {
                --imgX;
                ++imgY;

                p.X = imgX;
                p.Y = imgY;
                txtLabel.Location = p;
            }

        }
        if (top == true)
        {
            if (right == true)
            {
                ++imgX;
                --imgY;

                p.X = imgX;
                p.Y = imgY;
                txtLabel.Location = p;
            }
            else if (left == true)
            {
                --imgX;
                --imgY;

                p.X = imgX;
                p.Y = imgY;
                txtLabel.Location = p;
            }
        }

        Invalidate();
    }

}

}

The problem is the label's Location is its position relative to the monitor that it's on while the bounds you are comparing it too are an absolute position across all monitors. 问题是标签的位置是它相对于它所在的监视器的位置,而你比较它的边界也是所有监视器的绝对位置。

So if the bounds of the primary monitor are Top: 0, Bottom: 900, Left: 0, Right: 1600 the bounds of the secondary monitor might be something like Top: 0, Bottom: 900, Left: 1600, Right: 3200 . 因此,如果主监视器的边界是Top: 0, Bottom: 900, Left: 0, Right: 1600 ,则辅助监视器的边界可能类似于Top: 0, Bottom: 900, Left: 1600, Right: 3200 While the Location of the label on the secondary monitor will returning its position relative to the secondary monitor so for example Location.X: 200, Location.Y: 300 . 虽然Location在辅助监视器上的标签的位置将相对于它的返回到辅助监视器所以例如Location.X: 200, Location.Y: 300

You need to change the bounce Method to make the comparsion use either only absolute coordinates or only relative coordinates. 您需要更改bounce方法以使比较仅使用绝对坐标或仅使用相对坐标。

Here is the comparison code modified to use relative position of the label on the monitor; 以下是修改后的比较代码,以使用监视器上标签的相对位置;

if (txtLabel.Location.Y + txtLabel.Image.Height - (this.Bounds.Bottom - this.Bounds.Top) >= 0)
{
    top = true;
    bot = false;
}
if (txtLabel.Location.X + txtLabel.Image.Width - (this.Bounds.Right - this.Bounds.Left) >= 0)
{
    right = false;
    left = true;
}
// in relative coordinates left is always 0
if (txtLabel.Location.X <= 0)
{
    right = true;
    left = false;
}
// in relative coordinates top is always 0
if (txtLabel.Location.Y <= 0)
{
    top = false;
    bot = true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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