Created
June 20, 2017 02:51
-
-
Save rqx110/e711672ed9a4536db181d47f4b4d9eb8 to your computer and use it in GitHub Desktop.
show splash form for winform app
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
usage: (in program.cs)
SplashForm.DisplaySplash(1000,1000); Application.Run(new MainForm()); SplashForm.CloseSplash();