DisplayMagician/HeliosDisplayManagement/UIForms/ApplyingChangesForm.cs

305 lines
10 KiB
C#
Raw Normal View History

2017-02-26 19:23:31 +00:00
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Diagnostics;
using HeliosPlus.Resources;
2017-02-26 19:23:31 +00:00
using WinFormAnimation;
namespace HeliosPlus.UIForms
2017-02-26 19:23:31 +00:00
{
public sealed partial class ApplyingChangesForm : Form
2017-02-26 19:23:31 +00:00
{
private readonly Action _job;
private readonly Bitmap _progressImage;
private readonly List<Point> _progressPositions = new List<Point>();
private int _countdownCounter;
private readonly int _displayChangeMaxDelta = -1;
private int _displayChangeDelta;
private int _lastCount;
2017-02-26 19:23:31 +00:00
private bool _isClosing;
private int _startCounter;
public ApplyingChangesForm()
2017-02-26 19:23:31 +00:00
{
InitializeComponent();
_progressImage = new Bitmap(progressPanel.Width, progressPanel.Height);
Controls.Remove(progressPanel);
progressPanel.BackColor = BackColor;
progressBar.Invalidated += (sender, args) => Invalidate();
progressPanel.Invalidated += (sender, args) => Invalidate();
}
public ApplyingChangesForm(Action job, int cancellationTimeout = 0, int countdown = 0) : this()
2017-02-26 19:23:31 +00:00
{
_job = job;
_startCounter = cancellationTimeout;
_countdownCounter = countdown; _lastCount = _countdownCounter;
}
public ApplyingChangesForm(Action job, int cancellationTimeout = 0, int countdown = 0, int displayChangeMaxDelta = 5, string state = null) : this(job, cancellationTimeout, countdown)
{
_displayChangeMaxDelta = displayChangeMaxDelta;
if (!string.IsNullOrEmpty(state)) CountdownMessage = state;
2017-02-26 19:23:31 +00:00
}
public string CancellationMessage { get; set; } = Language.Starting_in;
public string CountdownMessage { get; set; } = Language.Please_wait;
protected override void OnKeyDown(KeyEventArgs e)
{
e.Handled = true;
}
protected override void OnPaint(PaintEventArgs e)
{
lock (_progressPositions)
{
progressPanel.DrawToBitmap(_progressImage, new Rectangle(Point.Empty, progressPanel.Size));
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
foreach (var position in _progressPositions)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
e.Graphics.DrawImage(_progressImage, new Rectangle(position, progressPanel.Size));
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
}
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
base.OnPaint(e);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData != Keys.Escape)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
return base.ProcessCmdKey(ref msg, keyData);
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
if (t_start.Enabled)
{
t_start.Stop();
t_countdown.Stop();
DialogResult = DialogResult.Cancel;
Close();
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
return true;
}
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
return true;
}
private void HandleDisplayChangeDelta()
{
if (_displayChangeMaxDelta <= -1) return;
_displayChangeDelta = _lastCount - _countdownCounter;
if (_displayChangeDelta > _displayChangeMaxDelta)
{
Debug.Print("_displayChangeDelta > _displayChangeMaxDelta! " + _displayChangeDelta + " > " + _displayChangeMaxDelta);
DialogResult = DialogResult.OK;
Close();
}
}
2017-02-26 19:23:31 +00:00
private void DoJob()
{
lbl_message.Text = CountdownMessage;
progressBar.ProgressColor = Color.OrangeRed;
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
if (_countdownCounter > 0)
{
progressBar.Text = (progressBar.Value = progressBar.Maximum = _countdownCounter).ToString();
t_countdown.Start();
_job?.Invoke();
}
else
{
progressBar.Style = ProgressBarStyle.Marquee;
progressBar.Text = "";
progressBar.Maximum = 100;
progressBar.Value = 50;
progressBar.Style = ProgressBarStyle.Marquee;
_job?.Invoke();
DialogResult = DialogResult.OK;
Close();
}
HandleDisplayChangeDelta();
2017-02-26 19:23:31 +00:00
}
private void DoTimeout()
{
lbl_message.Text = CancellationMessage;
progressBar.ProgressColor = Color.DodgerBlue;
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
if (_startCounter > 0)
{
progressBar.Text = (progressBar.Value = progressBar.Maximum = _startCounter).ToString();
t_start.Start();
}
else
{
DoJob();
}
HandleDisplayChangeDelta();
2017-02-26 19:23:31 +00:00
}
private void Reposition()
{
lock (_progressPositions)
{
var screens = Screen.AllScreens;
var minX = screens.Select(screen => screen.Bounds.X).Concat(new[] {0}).Min();
var maxX = screens.Select(screen => screen.Bounds.Width + screen.Bounds.X).Concat(new[] {0}).Max();
var minY = screens.Select(screen => screen.Bounds.Y).Concat(new[] {0}).Min();
var maxY = screens.Select(screen => screen.Bounds.Height + screen.Bounds.Y).Concat(new[] {0}).Max();
#if !DEBUG
2017-02-26 19:23:31 +00:00
Size = new Size(maxX + Math.Abs(minX), maxY + Math.Abs(minY));
Location = new Point(minX, minY);
#else
Size = new Size((int)((maxX + Math.Abs(minX)) * 0.8d), (int)((maxY + Math.Abs(minY)) * 0.8d));
Location = new Point(minX + (int)(Size.Width / 8d), minY + (int)(Size.Height / 8d));
#endif
2017-02-26 19:23:31 +00:00
_progressPositions.Clear();
_progressPositions.AddRange(
screens.Select(
screen =>
2018-10-20 00:27:25 +00:00
new Point(screen.Bounds.X - minX + (screen.Bounds.Width - progressPanel.Width) / 2,
screen.Bounds.Y - minY + (screen.Bounds.Height - progressPanel.Height) / 2)));
2017-02-26 19:23:31 +00:00
}
#if !DEBUG
TopMost = true;
Activate();
#endif
2017-02-26 19:23:31 +00:00
Invalidate();
}
private void SplashForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (_isClosing)
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
return;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
_isClosing = true;
e.Cancel = true;
var dialogResult = DialogResult;
new Animator(new Path((float) Opacity, 0, 200))
.Play(new SafeInvoker<float>(f =>
{
try
{
Opacity = f;
}
catch
{
// ignored
}
}, this), new SafeInvoker(() =>
{
DialogResult = dialogResult;
Close();
}, this));
}
private void SplashForm_Reposition(object sender, EventArgs e)
{
Reposition();
}
private void SplashForm_Shown(object sender, EventArgs e)
{
new Animator(new Path((float) Opacity, 0.97f, 200))
.Play(new SafeInvoker<float>(f =>
{
try
{
Opacity = f;
}
catch
{
// ignored
}
}, this), new SafeInvoker(DoTimeout, this));
}
private void t_countdown_Tick(object sender, EventArgs e)
{
if (_countdownCounter < 0)
{
t_countdown.Stop();
DialogResult = DialogResult.OK;
Close();
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
return;
}
2018-10-20 00:27:25 +00:00
HandleDisplayChangeDelta();
2017-02-26 19:23:31 +00:00
progressBar.Value = _countdownCounter;
progressBar.Text = progressBar.Value.ToString();
_countdownCounter--;
Reposition();
}
private void t_start_Tick(object sender, EventArgs e)
{
if (_startCounter < 0)
{
t_start.Stop();
DoJob();
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
return;
}
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
progressBar.Value = _startCounter;
progressBar.Text = progressBar.Value.ToString();
_startCounter--;
Reposition();
}
protected override void WndProc(ref Message m)
{
const int WM_SETTINGCHANGE = 0x001A;
const int SPI_SETWORKAREA = 0x02F;
const int WM_DISPLAYCHANGE = 0x007E;
const int x_bitshift = 0;
const int y_bitshift = 16;
const int xy_mask = 0xFFFF;
bool displayChange = false;
switch (m.Msg)
{
case WM_SETTINGCHANGE:
Debug.Print("Message: " + m.ToString());
Debug.Print("WM_SETTINGCHANGE");
switch ((int)m.WParam)
{
case SPI_SETWORKAREA:
Debug.Print("SPI_SETWORKAREA");
displayChange = true;
break;
}
break;
case WM_DISPLAYCHANGE:
int cxScreen = (xy_mask & ((int)m.LParam) >> x_bitshift);
int cyScreen = (xy_mask & ((int)m.LParam) >> y_bitshift);
Debug.Print("Message: " + m.ToString());
Debug.Print("WM_DISPLAYCHANGE");
Debug.Print("cxScreen: " + cxScreen + " cyScreen: " + cyScreen);
displayChange = true;
break;
}
if (displayChange)
{
_displayChangeDelta = _lastCount - _countdownCounter;
_lastCount = _countdownCounter;
Debug.Print("Display Change Detected at t " + _lastCount + " difference between changes is " + _displayChangeDelta);
}
base.WndProc(ref m);
}
2017-02-26 19:23:31 +00:00
}
}