OpenLiveWriter/src/managed/OpenLiveWriter.CoreServices/SplashScreen.cs

284 lines
11 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.
using System;
using System.Drawing.Imaging;
using System.Globalization;
using System.Threading;
using System.Drawing;
using System.Windows.Forms;
using OpenLiveWriter.Interop.Windows;
using OpenLiveWriter.Localization;
using OpenLiveWriter.Localization.Bidi;
using System.Diagnostics;
namespace OpenLiveWriter.CoreServices
{
/// <summary>
/// Summary description for SplashScreen.
/// </summary>
public class SplashScreen : BaseForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
private Label labelStatus;
private Bitmap _logoBitmap;
private PictureBox pictureBoxLogo;
private Bitmap _fdnLogoBitmap;
private PictureBox pictureBoxFdnLogo;
private System.Windows.Forms.Timer timerAnimation;
private int _ticks = 0;
public SplashScreen()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
DisplayHelper.Scale(this);
// Turn on double buffered painting.
//SetStyle(ControlStyles.UserPaint, true);
//SetStyle(ControlStyles.DoubleBuffer, true);
//if (!BidiHelper.IsRightToLeft)
// SetStyle(ControlStyles.AllPaintingInWmPaint, true);
//if (SystemInformation.HighContrast)
//{
// ImageHelper.ConvertToHighContrast(_backgroundImage);
// ImageHelper.ConvertToHighContrast(_logoImage);
//}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
LoadScaledImages();
// Create the timer
timerAnimation = new System.Windows.Forms.Timer();
timerAnimation.Interval = 17; // 60 FPS rounded up
timerAnimation.Tick += new EventHandler(AnimationTick);
timerAnimation.Enabled = true;
timerAnimation.Start();
}
private void LoadScaledImages()
{
const float scaleFactor = 2f; // Assume logos are already at 2x scaling
var fdnLogoBmp = new Bitmap(this.GetType(), "Images.NetFoundationLogo.png");
var logoBmp = new Bitmap(this.GetType(), "Images.SplashScreenLogo.png");
var fdnLogoSize = new Size(
(int)Math.Ceiling(fdnLogoBmp.Width * (DisplayHelper.ScalingFactorX / scaleFactor)),
(int)Math.Ceiling(fdnLogoBmp.Height * (DisplayHelper.ScalingFactorY / scaleFactor)));
_fdnLogoBitmap = new Bitmap(fdnLogoBmp, fdnLogoSize);
pictureBoxFdnLogo.Image = _fdnLogoBitmap;
pictureBoxFdnLogo.Size = _fdnLogoBitmap.Size;
var logoBmpSize = new Size(
(int)Math.Ceiling(logoBmp.Width * (DisplayHelper.ScalingFactorX / scaleFactor)),
(int)Math.Ceiling(logoBmp.Height * (DisplayHelper.ScalingFactorY / scaleFactor)));
_logoBitmap = new Bitmap(logoBmp, logoBmpSize);
pictureBoxLogo.Image = _logoBitmap;
pictureBoxLogo.Size = _logoBitmap.Size;
}
public void ShowSplashScreen()
{
Thread thread = new Thread(() =>
{
ShowDialog();
});
thread.Name = "Splash Screen Animation Thread";
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.labelStatus = new System.Windows.Forms.Label();
this.pictureBoxFdnLogo = new System.Windows.Forms.PictureBox();
this.pictureBoxLogo = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxFdnLogo)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxLogo)).BeginInit();
this.SuspendLayout();
//
// labelStatus
//
this.labelStatus.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.labelStatus.AutoSize = true;
this.labelStatus.ForeColor = System.Drawing.Color.White;
this.labelStatus.Location = new System.Drawing.Point(19, 214);
this.labelStatus.Margin = new System.Windows.Forms.Padding(10, 0, 0, 10);
this.labelStatus.Name = "labelStatus";
this.labelStatus.Size = new System.Drawing.Size(57, 15);
this.labelStatus.TabIndex = 1;
this.labelStatus.Text = "Starting...";
//
// pictureBoxFdnLogo
//
this.pictureBoxFdnLogo.ErrorImage = null;
this.pictureBoxFdnLogo.InitialImage = null;
this.pictureBoxFdnLogo.Location = new System.Drawing.Point(20, 20);
this.pictureBoxFdnLogo.Name = "pictureBoxFdnLogo";
this.pictureBoxFdnLogo.Size = new System.Drawing.Size(20, 20);
this.pictureBoxFdnLogo.TabIndex = 2;
this.pictureBoxFdnLogo.TabStop = false;
//
// pictureBoxLogo
//
this.pictureBoxLogo.ErrorImage = null;
this.pictureBoxLogo.InitialImage = null;
this.pictureBoxLogo.Location = new System.Drawing.Point(20, 92);
this.pictureBoxLogo.Name = "pictureBoxLogo";
this.pictureBoxLogo.Size = new System.Drawing.Size(20, 20);
this.pictureBoxLogo.TabIndex = 3;
this.pictureBoxLogo.TabStop = false;
this.pictureBoxLogo.Visible = false;
//
// SplashScreen
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(162)))), ((int)(((byte)(93)))), ((int)(((byte)(162)))));
this.ClientSize = new System.Drawing.Size(439, 248);
this.Controls.Add(this.pictureBoxLogo);
this.Controls.Add(this.pictureBoxFdnLogo);
this.Controls.Add(this.labelStatus);
this.Cursor = System.Windows.Forms.Cursors.AppStarting;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Name = "SplashScreen";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
((System.ComponentModel.ISupportInitialize)(this.pictureBoxFdnLogo)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxLogo)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private void Label1_Click(object sender, EventArgs e)
{
}
private void AnimationTick(object sender, EventArgs e)
{
// .NET Foundation Logo linear slide animation
const int fdnLogoAnimTicks = 10;
const int fdnLogoAnimTarget = 20;
pictureBoxFdnLogo.Left = (int)Math.Min(DisplayHelper.ScalingFactorX * _ticks * ((float)fdnLogoAnimTarget / fdnLogoAnimTicks), DisplayHelper.ScalingFactorX * fdnLogoAnimTarget);
pictureBoxFdnLogo.Image = ChangeOpacity(_fdnLogoBitmap, (float)Math.Min((float)_ticks / fdnLogoAnimTicks, 1.0));
const int logoAnimStart = 10;
const int logoAnimEnd = logoAnimStart + 20;
int logoAnimBegin = (Width / 2) - (pictureBoxLogo.Width / 2) - (int)(40 * DisplayHelper.ScalingFactorX);
int logoAnimTarget = (Width / 2) - (pictureBoxLogo.Width / 2);
if(_ticks > logoAnimStart)
{
pictureBoxLogo.Visible = true;
double x = Math.Min((float)(_ticks - logoAnimStart) / (logoAnimEnd - logoAnimStart) +.1, 1.0);
pictureBoxLogo.Left = (int)Math.Min(logoAnimBegin + (Math.Pow(Math.Log10(x), 10) * (logoAnimTarget - logoAnimBegin) * DisplayHelper.ScalingFactorX), logoAnimTarget);
// Set logo transparency (float)Math.Min((float)(_ticks - logoAnimStart) / (logoAnimEnd - logoAnimStart), 1.0)
pictureBoxLogo.Image = ChangeOpacity(_logoBitmap, (float)x);
} else
{
pictureBoxLogo.Visible = false;
}
Update();
_ticks++;
}
private static Bitmap ChangeOpacity(Image img, float opacityvalue)
{
// Example from https://www.codeproject.com/Tips/201129/Change-Opacity-of-Image-in-C
Bitmap bmp = new Bitmap(img.Width, img.Height); // Determining Width and Height of Source Image
Graphics graphics = Graphics.FromImage(bmp);
ColorMatrix colormatrix = new ColorMatrix();
colormatrix.Matrix33 = opacityvalue;
ImageAttributes imgAttribute = new ImageAttributes();
imgAttribute.SetColorMatrix(colormatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
graphics.DrawImage(img, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imgAttribute);
graphics.Dispose(); // Releasing all resource used by graphics
return bmp;
}
}
/// <summary>
/// Implementation of a splash screen connected to a form
/// </summary>
public class FormSplashScreen : IDisposable
{
public FormSplashScreen(Form form)
{
this.form = form;
}
public Form Form
{
get { return form; }
}
/// <summary>
/// Close the form (do it only once and defend against exceptions
/// occurring during close/dispose)
/// </summary>
public void Dispose()
{
if (form != null)
{
if (form.InvokeRequired)
{
form.BeginInvoke(new ThreadStart(Dispose));
}
else
{
try
{
form.Close();
form.Dispose();
}
finally
{
form = null;
}
}
}
}
/// <summary>
/// Form instance
/// </summary>
private Form form;
}
}