public void Run(INativeWindowStartupInfo startupInfo) { GdiplusStartupInput gdiPlusStartupInput = GdiplusStartupInput.CreateV1(); GdiPlusAPI.CheckStatus(GdiPlusAPI.GdiplusStartup(out var gdiPlusToken, ref gdiPlusStartupInput, out _)); IntPtr hInstance = Win32API.GetModuleHandleW(null); var windowClass = new WNDCLASSEXW(); windowClass.cbSize = (uint)Marshal.SizeOf <WNDCLASSEXW>(); windowClass.lpfnWndProc = WindowProc; windowClass.hInstance = hInstance; windowClass.lpszClassName = WindowClassName; var atom = Win32API.RegisterClassExW(ref windowClass); if (atom == 0) { throw new InvalidOperationException("Failed to register window class."); } try { const int CW_USEDEFAULT = unchecked ((int)0x80000000); IntPtr hwnd = Win32API.CreateWindowExW( 0, WindowClassName, startupInfo.Title, Win32WindowStyle.WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, startupInfo.Width, startupInfo.Height, IntPtr.Zero, IntPtr.Zero, hInstance, IntPtr.Zero ); if (hwnd == IntPtr.Zero) { throw new InvalidOperationException("Failed to create a window."); } var window = new Win32Window(hwnd, startupInfo); windows.Add(hwnd, window); startupInfo.OnCreate(window); try { Win32API.ShowWindow(hwnd, Win32ShowWindowCommand.SW_SHOWNORMAL); MSG msg = new MSG(); int mRet; while ((mRet = Win32API.GetMessageW(ref msg, IntPtr.Zero, 0, 0)) != 0) { if (mRet == -1) { throw new InvalidOperationException("Failed to retrieve a message."); } Win32API.TranslateMessage(ref msg); Win32API.DispatchMessageW(ref msg); } } finally { // usually window will be destroyed before this point, unless error occurs if (Win32API.DestroyWindow(hwnd) == 0) { // todo: log warning ? } } } finally { if (Win32API.UnregisterClassW(WindowClassName, hInstance) == 0) { // todo: log warning } // todo: use separate finally for GDI+ GdiPlusAPI.GdiplusShutdown(gdiPlusToken); } }