2010-06-29 7 views
1

Visual Studio 10 프로젝트의 리소스로 놀고있는 동안 "스플래시 스크린"이라는 빌드 작업을 통해 neat splash screen capabilities of WPF에서이 기사를 찾을 수있었습니다.Forms 응용 프로그램에서 WPF 스타일의 시작 화면을 만들 수 있습니까?

난조 끝에이 making a splash screen in Windows Forms에이 MSDN 기사가 있지만 앱이로드되기 전에 기본 코드를 사용하여 스플래시 화면을로드하는 대신 WinForms 버전이 기본 양식을 초기화하는 동안 간단히 표시합니다.

WinForms 앱에서이 우수한 유형의 초기 화면을 구현할 수있는 방법이 있습니까?

답변

4

예. .NET 3.5 SP1과 함께 제공되기 전에 WPF 응용 프로그램에 대한 구현을 수행했습니다.

기본적으로 네이티브 Win32 창을 만들고 어셈블리를로드하고 응용 프로그램을 초기화하는 동안 BMP 이미지를 표시합니다. 다른 이미지 형식을 사용할 수도 있지만 BMP는 가장 적은 라이브러리로드가 필요하므로 선호됩니다.

"기본 스플래시 창 만들기"에 대한 빠른 google은 여러 기사를 제공했습니다. 내가 (빠른 스캔에서) 발견 한 가장 포괄적 인 것은 Bradley Grainger : Displaying a Splash Screen with C++입니다. 이 기사는 WPF를 염두에두고 작성되었지만 개념은 동일합니다. 기본 창을 만들고 응용 프로그램을 실행하여 응용 프로그램을 닫습니다.

내일 직장에서 구현할 소스를 살펴보고 내 대답을 예제로 업데이트 할 것입니다.

그때까지 Google을 시작하기 전에 이미 많은 예제를 조사해보십시오.

UPDATE 약속대로

는 아래 시작 화면을 구현하는 모든 예이다 (여기에 조금있다).

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); 
    } 

} 
+0

Olson의 reinvention을 참고하십시오 : http://www.olsonsoft.com/blogs/stefanolson/post/A-better-WPF-splash-screen.aspx –

+0

@Tom : 실제로 Olsons 글을 먼저 읽고 링크를 따라 찾습니다. 브래들리의 기사. 나는 나중에 시간을내어 오늘 내 대답을 업데이트 할 것이다. – Dennis

+0

@Tom : 예제로 업데이트되었습니다. – Dennis

0

비 WPF 형식을 사용할 수 있으며 매우 행복하게 작동합니다. 이외에도 VS2008의 기능이었습니다.

관련 문제