Да.Я сделал реализацию для нашего приложения WPF до того, как оно было упаковано с .NET 3.5 SP1.
По сути, вы создаете собственное окно Win32 и отображаете образ BMP во время загрузки сборок и инициализации приложения.Вы можете использовать другие форматы изображений, но BMP предпочтительнее, так как требует наименьшего количества загруженных библиотек.
Быстрый гугл для «создания собственного окна-заставки» содержит несколько статей.Самым полным из обнаруженных мной (из быстрого сканирования) был Брэдли Грейнджер: Отображение заставки с C ++ .Статья была написана для WPF, но концепция та же: создать собственное окно, запустить ваше приложение, закрыть окно.
Я посмотрю источник моей реализации завтра на работе и дополню свой ответ примерами.
До тех пор, Google и исследовать множество примеров, уже там, чтобы начать.
ОБНОВЛЕНИЕ
Как и обещано, ниже приведен полный примерреализации заставки (есть немного)
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Windows.Interop;
namespace SplashScreen
{
public class SplashScreenManager
{
static SplashScreen _current = null;
static SplashScreenManager() {}
SplashScreenManager() { }
public static SplashScreen Create(Module module, int resourceID)
{
if (_current != null)
{
_current.Close();
_current.Dispose();
}
_current = new SplashScreen(module, resourceID);
return _current;
}
public static void Close()
{
if (_current == null)
return;
_current.Close();
_current.Dispose();
_current = null;
}
public static SplashScreen Current
{
get { return _current; }
}
}
public class SplashScreen : IDisposable
{
static bool IsClassRegistered = false;
static string WindowClassName = "SplashScreenWindowClass";
IntPtr _bitmapHandle = IntPtr.Zero;
int _bitmapHeight;
int _bitmapWidth;
bool _isClosed;
UnsafeNativeMethods.WndProc _splashWindowProcedureCallback;
IntPtr _windowHandle = IntPtr.Zero;
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
internal SplashScreen(Module module, int resourceID)
{
_bitmapHandle = UnsafeNativeMethods.LoadBitmap(Marshal.GetHINSTANCE(module), new IntPtr(resourceID));
_splashWindowProcedureCallback = new UnsafeNativeMethods.WndProc(SplashWindowProcedure);
}
public void Close()
{
if (_isClosed)
return;
_isClosed = true;
UnsafeNativeMethods.PostMessage(new HandleRef(this, _windowHandle), 0x10, IntPtr.Zero, IntPtr.Zero);
if (_bitmapHandle != IntPtr.Zero)
{
UnsafeNativeMethods.DeleteObject(_bitmapHandle);
_bitmapHandle = IntPtr.Zero;
}
}
public void Close(IntPtr handle)
{
if (_windowHandle != IntPtr.Zero)
UnsafeNativeMethods.SetForegroundWindow(handle);
Close();
}
void CreateWindow()
{
if (!IsClassRegistered)
RegisterClass();
if (IsClassRegistered)
{
CreateWindowInternal();
if (_windowHandle != IntPtr.Zero)
UnsafeNativeMethods.ShowWindow(_windowHandle, 5);
}
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
Close(IntPtr.Zero);
GC.SuppressFinalize(this);
}
void GetBitmapDimensions()
{
int cb = Marshal.SizeOf(typeof(UnsafeNativeMethods.BITMAP));
IntPtr lpvObject = Marshal.AllocCoTaskMem(cb);
UnsafeNativeMethods.GetObject(_bitmapHandle, cb, lpvObject);
UnsafeNativeMethods.BITMAP bitmap = (UnsafeNativeMethods.BITMAP)Marshal.PtrToStructure(lpvObject, typeof(UnsafeNativeMethods.BITMAP));
_bitmapWidth = bitmap.bmWidth;
_bitmapHeight = bitmap.bmHeight;
Marshal.FreeCoTaskMem(lpvObject);
}
void OnPaint(IntPtr hdc)
{
if (_bitmapHandle != IntPtr.Zero)
{
IntPtr ptr = UnsafeNativeMethods.CreateCompatibleDC(hdc);
IntPtr hgdiobj = UnsafeNativeMethods.SelectObject(ptr, _bitmapHandle);
UnsafeNativeMethods.BitBlt(hdc, 0, 0, _bitmapWidth, _bitmapHeight, ptr, 0, 0, 0xcc0020);
UnsafeNativeMethods.SelectObject(ptr, hgdiobj);
UnsafeNativeMethods.DeleteDC(ptr);
}
}
void CreateWindowInternal()
{
int systemMetrics = UnsafeNativeMethods.GetSystemMetrics(0);
int num4 = UnsafeNativeMethods.GetSystemMetrics(1);
uint dwStyle = 0x80000000;
uint dwExStyle = 0x188;
IntPtr moduleHandle = UnsafeNativeMethods.GetModuleHandle(null);
IntPtr desktopWindow = UnsafeNativeMethods.GetDesktopWindow();
_windowHandle = UnsafeNativeMethods.CreateWindowEx(dwExStyle, WindowClassName, "", dwStyle, (systemMetrics - _bitmapWidth) / 2, (num4 - _bitmapHeight) / 2, _bitmapWidth, _bitmapHeight, desktopWindow, IntPtr.Zero, moduleHandle, IntPtr.Zero);
}
void RegisterClass()
{
IntPtr moduleHandle = UnsafeNativeMethods.GetModuleHandle(null);
UnsafeNativeMethods.WNDCLASSEX lpwcx = new UnsafeNativeMethods.WNDCLASSEX();
lpwcx.cbSize = (uint)Marshal.SizeOf(typeof(UnsafeNativeMethods.WNDCLASSEX));
lpwcx.cbClsExtra = 0;
lpwcx.cbWndExtra = 0;
lpwcx.hbrBackground = IntPtr.Zero;
lpwcx.hCursor = IntPtr.Zero;
lpwcx.hIcon = IntPtr.Zero;
lpwcx.hIconSm = IntPtr.Zero;
lpwcx.hInstance = moduleHandle;
lpwcx.lpfnWndProc = _splashWindowProcedureCallback;
lpwcx.lpszClassName = WindowClassName;
lpwcx.lpszMenuName = null;
lpwcx.style = 0;
if (UnsafeNativeMethods.RegisterClassExW(ref lpwcx) != 0)
{
IsClassRegistered = true;
}
}
public void Show()
{
if (_windowHandle == IntPtr.Zero)
{
Thread thread = new Thread(new ThreadStart(ThreadMethod));
thread.IsBackground = true;
thread.Start();
}
}
[SuppressUnmanagedCodeSecurity]
IntPtr SplashWindowProcedure(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
if (msg == 15)
{
UnsafeNativeMethods.PAINTSTRUCT lpPaint = new UnsafeNativeMethods.PAINTSTRUCT();
IntPtr hdc = UnsafeNativeMethods.BeginPaint(hWnd, out lpPaint);
OnPaint(hdc);
UnsafeNativeMethods.EndPaint(hWnd, ref lpPaint);
return IntPtr.Zero;
}
return UnsafeNativeMethods.DefWindowProc(hWnd, msg, wParam, lParam);
}
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
void ThreadMethod()
{
if (_bitmapHandle != IntPtr.Zero)
{
GetBitmapDimensions();
CreateWindow();
MSG msg = new MSG();
while (UnsafeNativeMethods.GetMessage(ref msg, _windowHandle, 0, 0) > 0)
{
UnsafeNativeMethods.TranslateMessage(ref msg);
UnsafeNativeMethods.DispatchMessage(ref msg);
}
_windowHandle = IntPtr.Zero;
GC.KeepAlive(this);
}
}
}
[SuppressUnmanagedCodeSecurity]
internal sealed class UnsafeNativeMethods
{
// Fields
internal const int GWL_EXSTYLE = -20;
public const int LOGPIXELSX = 0x58;
public const int LOGPIXELSY = 90;
internal const uint MB_ICONASTERISK = 0x40;
internal const uint MB_ICONERROR = 0x10;
internal const uint MB_ICONEXCLAMATION = 0x30;
internal const uint MB_ICONHAND = 0x10;
internal const uint MB_ICONINFORMATION = 0x40;
internal const uint MB_ICONQUESTION = 0x20;
internal const uint MB_ICONWARNING = 0x30;
internal const uint MB_OK = 0;
internal const uint MB_OKCANCEL = 1;
internal const uint MB_SETFOREGROUND = 0x10000;
internal const uint MB_YESNO = 4;
internal const uint MB_YESNOCANCEL = 3;
internal const int SM_CXSCREEN = 0;
internal const int SM_CYSCREEN = 1;
public const int SPI_GETWORKAREA = 0x30;
internal const uint SRCCOPY = 0xcc0020;
public const int SW_HIDE = 0;
internal const int SW_SHOW = 5;
public const int SW_SHOWMAXIMIZED = 3;
public const int SW_SHOWMINIMIZED = 2;
public const int SW_SHOWNORMAL = 1;
internal const int WM_CLOSE = 0x10;
internal const uint WS_EX_TOOLWINDOW = 0x80;
internal const uint WS_EX_TOPMOST = 8;
internal const uint WS_EX_TRANSPARENT = 0x20;
internal const uint WS_EX_WINDOWEDGE = 0x100;
internal const uint WS_POPUP = 0x80000000;
UnsafeNativeMethods() {}
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(POINT Point);
[DllImport("user32.dll")]
public static extern IntPtr ChildWindowFromPoint(IntPtr hWndParent, POINT Point);
[DllImport("user32.dll")]
public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
[DllImport("user32.dll")]
internal static extern IntPtr BeginPaint(IntPtr hwnd, out PAINTSTRUCT lpPaint);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("gdi32.dll")]
internal static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);
[DllImport("gdi32.dll")]
internal static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("user32.dll", EntryPoint = "CreateWindowExW", CharSet = CharSet.Unicode)]
internal static extern IntPtr CreateWindowEx(uint dwExStyle, string lpClassName, string lpWindowName, uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);
[DllImport("user32.dll")]
internal static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("gdi32.dll")]
internal static extern bool DeleteDC(IntPtr hdc);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("gdi32.dll")]
internal static extern bool DeleteObject(IntPtr hObject);
[DllImport("user32.dll")]
internal static extern IntPtr DispatchMessage([In] ref MSG lpmsg);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
internal static extern bool EndPaint(IntPtr hWnd, ref PAINTSTRUCT lpPaint);
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
internal static extern IntPtr GetDC(HandleRef hWnd);
[DllImport("user32.dll")]
internal static extern IntPtr GetDesktopWindow();
[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hDC, int index);
[DllImport("user32.dll", EntryPoint = "GetMessageW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static extern int GetMessage([In, Out] ref MSG msg, IntPtr hWnd, int uMsgFilterMin, int uMsgFilterMax);
[DllImport("kernel32.dll", EntryPoint = "GetModuleHandleW", CharSet = CharSet.Unicode)]
internal static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("gdi32.dll")]
internal static extern int GetObject(IntPtr hgdiobj, int cbBuffer, IntPtr lpvObject);
[DllImport("user32.dll")]
internal static extern int GetSystemMetrics(int nIndex);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern int GetWindowLong(IntPtr handle, int index);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
public static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);
[DllImport("user32.dll", EntryPoint = "LoadBitmapW", CharSet = CharSet.Unicode)]
internal static extern IntPtr LoadBitmap(IntPtr hInstance, IntPtr lpBitmapName);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
internal static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[return: MarshalAs(UnmanagedType.U2)]
[DllImport("user32.dll")]
internal static extern short RegisterClassExW([In] ref WNDCLASSEX lpwcx);
[DllImport("user32.dll")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll")]
internal static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
internal static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern int SetWindowLong(IntPtr handle, int index, int dwNewLong);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
public static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
public static extern bool SystemParametersInfo(int nAction, int nParam, ref RECT rc, int nUpdate);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
internal static extern bool TranslateMessage([In] ref MSG lpMsg);
[StructLayout(LayoutKind.Sequential)]
internal struct BITMAP
{
public int bmType;
public int bmWidth;
public int bmHeight;
public int bmWidthBytes;
public ushort bmPlanes;
public ushort bmBitsPixel;
public IntPtr bmBits;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PAINTSTRUCT
{
public IntPtr hdc;
public bool fErase;
public UnsafeNativeMethods.RECT rcPaint;
public bool fRestore;
public bool fIncUpdate;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
public byte[] rgbReserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPLACEMENT
{
public int Length;
public int Flags;
public int ShowCmd;
public UnsafeNativeMethods.POINT MinPosition;
public UnsafeNativeMethods.POINT MaxPosition;
public UnsafeNativeMethods.RECT NormalPosition;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal struct WNDCLASSEX
{
public uint cbSize;
public uint style;
public UnsafeNativeMethods.WndProc lpfnWndProc;
public int cbClsExtra;
public int cbWndExtra;
public IntPtr hInstance;
public IntPtr hIcon;
public IntPtr hCursor;
public IntPtr hbrBackground;
public string lpszMenuName;
public string lpszClassName;
public IntPtr hIconSm;
}
internal delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
}
}