C#Secondary Monitor Bounds问题

时间:2012-03-05 16:02:10

标签: c# multiple-monitors bounds

我在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 个答案:

答案 0 :(得分: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;
}