Skip to content

Instantly share code, notes, and snippets.

@rqx110
Created June 20, 2017 02:51
Show Gist options
  • Save rqx110/e711672ed9a4536db181d47f4b4d9eb8 to your computer and use it in GitHub Desktop.
Save rqx110/e711672ed9a4536db181d47f4b4d9eb8 to your computer and use it in GitHub Desktop.
show splash form for winform app
namespace Bootstrap
{
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
public class SplashForm : Form
{
private Bitmap _bitmap;
private int _bitmapOpacity;
private static int _fadeInTime;
private Timer _fadeInTimer;
private static int _fadeOutTime;
private Timer _fadeOutTimer;
private IntPtr _hBitmap = IntPtr.Zero;
private static SplashForm _instance;
private static ManualResetEvent _threadStartEvent = new ManualResetEvent(false);
private const byte AC_SRC_ALPHA = 1;
private const byte AC_SRC_OVER = 0;
private IContainer components;
private const int GWL_STYLE = -16;
private const int NUM_FADE_STEPS = 0x20;
private const byte OPACITY_STEP = 8;
private const int ULW_ALPHA = 2;
private const uint WS_VISIBLE = 0x10000000;
private SplashForm()
{
this.InitializeComponent();
this._bitmap = new Bitmap(this.BackgroundImage);
this._hBitmap = this._bitmap.GetHbitmap(Color.FromArgb(0));
base.ClientSize = this._bitmap.Size;
}
private void _fadeInTimer_Tick(object sender, EventArgs e)
{
if (this._bitmapOpacity < 0xff)
{
this._bitmapOpacity += 8;
this.UpdateBackgroundImage();
}
else
{
this._fadeInTimer.Stop();
}
}
private void _fadeOutTimer_Tick(object sender, EventArgs e)
{
this._bitmapOpacity -= 8;
if (this._bitmapOpacity <= 0)
{
base.Close();
}
else
{
this.UpdateBackgroundImage();
}
}
public static void CloseSplash()
{
Application.Idle -= new EventHandler(SplashForm.OnApplicationIdle);
SplashForm form = _instance;
if (form != null)
{
form.BeginInvoke(new MethodInvoker(form.StartFadeOut));
}
}
[DllImport("gdi32.dll", SetLastError=true, ExactSpelling=true)]
private static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll", SetLastError=true, ExactSpelling=true)]
private static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll", SetLastError=true, ExactSpelling=true)]
private static extern bool DeleteObject(IntPtr hObject);
public static void DisplaySplash(int fadeInTime, int fadeOutTime)
{
if (_fadeInTime < 0)
{
throw new ArgumentOutOfRangeException("fadeInTime");
}
if (_fadeOutTime < 0)
{
throw new ArgumentOutOfRangeException("fadeOutTime");
}
_fadeInTime = fadeInTime;
_fadeOutTime = fadeOutTime;
Application.Idle += new EventHandler(SplashForm.OnApplicationIdle);
Thread thread = new Thread(new ThreadStart(SplashForm.SplashThread));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
_threadStartEvent.WaitOne();
}
protected override void Dispose(bool disposing)
{
if (disposing && (this.components != null))
{
this._bitmap.Dispose();
if (this._hBitmap != IntPtr.Zero)
{
DeleteObject(this._hBitmap);
}
this.components.Dispose();
}
base.Dispose(disposing);
}
private IntPtr FindMainWindow()
{
int id = Process.GetCurrentProcess().Id;
for (IntPtr ptr = GetWindow(_instance.Handle, GetWindowCmd.GW_HWNDNEXT); ptr != IntPtr.Zero; ptr = GetWindow(ptr, GetWindowCmd.GW_HWNDNEXT))
{
uint lpdwProcessId = 0;
GetWindowThreadProcessId(ptr, out lpdwProcessId);
if ((lpdwProcessId == id) && ((GetWindowLong(ptr, -16) & 0x10000000L) == 0x10000000L))
{
return ptr;
}
}
return IntPtr.Zero;
}
[DllImport("user32.dll", SetLastError=true, ExactSpelling=true)]
private static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll", SetLastError=true)]
private static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCmd uCmd);
[DllImport("user32.dll", SetLastError=true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", SetLastError=true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
private void InitializeComponent()
{
this.components = new Container();
this._fadeOutTimer = new Timer(this.components);
this._fadeInTimer = new Timer(this.components);
base.SuspendLayout();
this._fadeOutTimer.Interval = 50;
this._fadeOutTimer.Tick += new EventHandler(this._fadeOutTimer_Tick);
this._fadeInTimer.Interval = 50;
this._fadeInTimer.Tick += new EventHandler(this._fadeInTimer_Tick);
base.AutoScaleDimensions = new SizeF(6f, 13f);
base.AutoScaleMode = AutoScaleMode.Font;
this.BackgroundImage = Resources.Splash;
this.BackgroundImageLayout = ImageLayout.Center;
base.ClientSize = new Size(0x207, 0x98);
this.DoubleBuffered = true;
base.FormBorderStyle = FormBorderStyle.None;
base.Name = "SplashForm";
base.ShowInTaskbar = false;
base.StartPosition = FormStartPosition.CenterScreen;
this.Text = "Splash";
base.TopMost = true;
base.ResumeLayout(false);
}
private static void OnApplicationIdle(object sender, EventArgs e)
{
CloseSplash();
}
protected override void OnClosed(EventArgs e)
{
IntPtr hwnd = this.FindMainWindow();
if (hwnd != IntPtr.Zero)
{
SetForegroundWindow(hwnd);
}
base.OnClosed(e);
_instance = null;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
int num = _fadeInTime / 0x20;
if (num == 0)
{
this._bitmapOpacity = 0xff;
this.UpdateBackgroundImage();
}
else
{
this._fadeInTimer.Interval = num;
this._fadeInTimer.Start();
}
}
[DllImport("user32.dll", ExactSpelling=true)]
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll", ExactSpelling=true)]
private static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
private static extern bool SetForegroundWindow(IntPtr hwnd);
private static void SplashThread()
{
_instance = new SplashForm();
_threadStartEvent.Set();
Application.Run(_instance);
}
private void StartFadeOut()
{
this._fadeInTimer.Stop();
this._fadeOutTimer.Start();
int num = _fadeOutTime / 0x20;
if (num == 0)
{
base.Close();
}
else
{
this._fadeOutTimer.Interval = num;
this._fadeOutTimer.Start();
}
}
private void UpdateBackgroundImage()
{
IntPtr dC = GetDC(IntPtr.Zero);
IntPtr hDC = CreateCompatibleDC(dC);
IntPtr zero = IntPtr.Zero;
zero = SelectObject(hDC, this._hBitmap);
BLENDFUNCTION pblend = new BLENDFUNCTION {
BlendOp = 0,
BlendFlags = 0
};
if (this._bitmapOpacity < 0)
{
pblend.SourceConstantAlpha = 0;
}
else if (this._bitmapOpacity > 0xff)
{
pblend.SourceConstantAlpha = 0xff;
}
else
{
pblend.SourceConstantAlpha = (byte) this._bitmapOpacity;
}
pblend.AlphaFormat = 1;
Size psize = this._bitmap.Size;
Point pptSrc = new Point(0, 0);
Point pptDst = new Point(base.Left, base.Top);
UpdateLayeredWindow(base.Handle, dC, ref pptDst, ref psize, hDC, ref pptSrc, 0, ref pblend, 2);
ReleaseDC(IntPtr.Zero, dC);
if (zero != IntPtr.Zero)
{
SelectObject(hDC, zero);
}
DeleteDC(hDC);
}
[DllImport("user32.dll", SetLastError=true, ExactSpelling=true)]
private static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pptSrc, int crKey, ref BLENDFUNCTION pblend, int dwFlags);
protected override System.Windows.Forms.CreateParams CreateParams
{
get
{
System.Windows.Forms.CreateParams createParams = base.CreateParams;
createParams.ExStyle |= 0x80000;
return createParams;
}
}
[StructLayout(LayoutKind.Sequential, Pack=1)]
private struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
private enum GetWindowCmd : uint
{
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6,
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4
}
}
}
@rqx110
Copy link
Author

rqx110 commented Jun 20, 2017

usage: (in program.cs)
SplashForm.DisplaySplash(1000,1000); Application.Run(new MainForm()); SplashForm.CloseSplash();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment