private void DestroyResources() { if (_dt != null) { _dt.Stop(); _dt = null; } if (_hwnd != IntPtr.Zero) { HandleRef hwnd = new HandleRef(null, _hwnd); if (UnsafeNativeMethods.IsWindow(hwnd)) { UnsafeNativeMethods.IntDestroyWindow(hwnd); } _hwnd = IntPtr.Zero; } if (_hBitmap != null && !_hBitmap.IsClosed) { UnsafeNativeMethods.DeleteObject(_hBitmap.MakeHandleRef(null).Handle); _hBitmap.Close(); _hBitmap = null; } if (_wndClass != 0) { // Attempt to unregister the window class. If the application has a second // splash screen which is still open this call will fail. That's OK. if (UnsafeNativeMethods.IntUnregisterClass(new IntPtr(_wndClass), _hInstance) != 0) { _defWndProc = null; // Can safely release the wndproc delegate when there are no more splash screen instances } _wndClass = 0; } if (_resourceManager != null) { _resourceManager.ReleaseAllResources(); } }
private IntPtr CreateWindow(NativeMethods.BitmapHandle hBitmap, int width, int height, bool topMost) { if (_defWndProc == null) { _defWndProc = new MS.Win32.NativeMethods.WndProc(UnsafeNativeMethods.DefWindowProc); } MS.Win32.NativeMethods.WNDCLASSEX_D wndClass = new MS.Win32.NativeMethods.WNDCLASSEX_D(); wndClass.cbSize = Marshal.SizeOf(typeof(MS.Win32.NativeMethods.WNDCLASSEX_D)); wndClass.style = 3; /* CS_HREDRAW | CS_VREDRAW */ wndClass.lpfnWndProc = null; wndClass.hInstance = _hInstance; wndClass.hCursor = IntPtr.Zero; wndClass.lpszClassName = CLASSNAME; wndClass.lpszMenuName = string.Empty; wndClass.lpfnWndProc = _defWndProc; // We chose to ignore re-registration errors in RegisterClassEx on the off chance that the user // wants to open multiple splash screens. _wndClass = MS.Win32.UnsafeNativeMethods.IntRegisterClassEx(wndClass); if (_wndClass == 0) { if (Marshal.GetLastWin32Error() != 0x582) /* class already registered */ { throw new Win32Exception(); } } int screenWidth = MS.Win32.UnsafeNativeMethods.GetSystemMetrics(SM.CXSCREEN); int screenHeight = MS.Win32.UnsafeNativeMethods.GetSystemMetrics(SM.CYSCREEN); int x = (screenWidth - width) / 2; int y = (screenHeight - height) / 2; HandleRef nullHandle = new HandleRef(null, IntPtr.Zero); int windowCreateFlags = (int)NativeMethods.WS_EX_WINDOWEDGE | NativeMethods.WS_EX_TOOLWINDOW | NativeMethods.WS_EX_LAYERED | (topMost ? NativeMethods.WS_EX_TOPMOST : 0); // CreateWindowEx will either succeed or throw IntPtr hWnd = MS.Win32.UnsafeNativeMethods.CreateWindowEx( windowCreateFlags, CLASSNAME, SR.Get(SRID.SplashScreenIsLoading), MS.Win32.NativeMethods.WS_POPUP | MS.Win32.NativeMethods.WS_VISIBLE, x, y, width, height, nullHandle, nullHandle, new HandleRef(null, _hInstance), IntPtr.Zero); // Display the image on the window IntPtr hScreenDC = UnsafeNativeMethods.GetDC(new HandleRef()); IntPtr memDC = UnsafeNativeMethods.CreateCompatibleDC(new HandleRef(null, hScreenDC)); IntPtr hOldBitmap = UnsafeNativeMethods.SelectObject(new HandleRef(null, memDC), hBitmap.MakeHandleRef(null).Handle); NativeMethods.POINT newSize = new NativeMethods.POINT(width, height); NativeMethods.POINT newLocation = new NativeMethods.POINT(x, y); NativeMethods.POINT sourceLocation = new NativeMethods.POINT(0, 0); _blendFunc = new NativeMethods.BLENDFUNCTION(); _blendFunc.BlendOp = NativeMethods.AC_SRC_OVER; _blendFunc.BlendFlags = 0; _blendFunc.SourceConstantAlpha = 255; _blendFunc.AlphaFormat = 1; /*AC_SRC_ALPHA*/ bool result = UnsafeNativeMethods.UpdateLayeredWindow(hWnd, hScreenDC, newLocation, newSize, memDC, sourceLocation, 0, ref _blendFunc, NativeMethods.ULW_ALPHA); UnsafeNativeMethods.SelectObject(new HandleRef(null, memDC), hOldBitmap); UnsafeNativeMethods.ReleaseDC(new HandleRef(), new HandleRef(null, memDC)); UnsafeNativeMethods.ReleaseDC(new HandleRef(), new HandleRef(null, hScreenDC)); if (result == false) { UnsafeNativeMethods.HRESULT.Check(Marshal.GetHRForLastWin32Error()); } return(hWnd); }