C#二次显示器边界问题

3

我用C#制作了一个弹跳屏幕保护程序。当只有一个显示器时,它可以完美地工作。然而,当我使用双显示器时,边界不起作用。次要显示器的位置似乎有影响,而且似乎没有正确的右边界(次要屏幕在右侧)。

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();
            }
        }
    }    
}

//屏幕保护程序表单

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();
    }

}

}
1个回答

2
问题在于标签的位置是相对于它所在的监视器而言的,而你要比较的边界是跨越所有监视器的绝对位置。
因此,如果主监视器的边界为Top: 0, Bottom: 900, Left: 0, Right: 1600,那么次要监视器的边界可能是Top: 0, Bottom: 900, Left: 1600, Right: 3200。而标签在次要监视器上的Location将返回其相对于次要监视器的位置,例如Location.X: 200, Location.Y: 300
你需要更改bounce方法,使比较使用仅绝对坐标或仅相对坐标。
下面是已修改为使用标签在监视器上的相对位置进行比较的代码:
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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接