我在 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();
}
}
}
最佳答案
问题是标签的位置是它相对于它所在的监视器的位置,而您正在比较它的边界也是所有监视器的绝对位置。
所以如果主监视器的边界是 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;
}
关于C# 辅助监视器边界问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9569821/