23 #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP && SILICONSTUDIO_PARADOX_GRAPHICS_API_DIRECT3D
25 using System.Globalization;
26 using System.Windows.Forms;
27 using System.Runtime.InteropServices;
31 namespace SiliconStudio.
Paradox.Games
52 internal class WindowsMessageLoop : IDisposable
54 private IntPtr controlHandle;
56 private bool isControlAlive;
57 private bool switchControl;
62 public WindowsMessageLoop() {}
67 public WindowsMessageLoop(
Control control)
85 if(control == value)
return;
88 if(control != null && !switchControl)
90 isControlAlive =
false;
91 control.Disposed -= ControlDisposed;
92 controlHandle = IntPtr.Zero;
95 if (value != null && value.IsDisposed)
97 throw new InvalidOperationException(
"Control is already disposed");
101 switchControl =
true;
111 public bool UseApplicationDoEvents {
get; set; }
117 public bool AllowWindowssKeys {
get; set; }
124 public bool NextFrame()
128 if (switchControl && control != null)
130 controlHandle = control.Handle;
131 control.Disposed += ControlDisposed;
132 isControlAlive =
true;
133 switchControl =
false;
138 if(UseApplicationDoEvents)
143 Application.DoEvents();
147 var gameForm =
Control as GameForm;
149 var localHandle = controlHandle;
150 if (localHandle != IntPtr.Zero)
154 while (Win32Native.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0) != 0)
156 if (Win32Native.GetMessage(out msg, IntPtr.Zero, 0, 0) == -1)
158 throw new InvalidOperationException(
String.Format(CultureInfo.InvariantCulture,
159 "An error happened in rendering loop while processing windows messages. Error: {0}",
160 Marshal.GetLastWin32Error()));
166 isControlAlive =
false;
169 var message =
new Message() { HWnd = msg.handle, LParam = msg.lParam, Msg = (int)msg.msg, WParam = msg.wParam };
179 Win32Native.TranslateMessage(ref msg);
180 Win32Native.DispatchMessage(ref msg);
187 return isControlAlive || switchControl;
190 private void ControlDisposed(
object sender,
EventArgs e)
192 isControlAlive =
false;
198 public void Dispose()
206 public delegate
void RenderCallback();
211 public static void Run(ApplicationContext context, RenderCallback renderCallback)
213 Run(context.MainForm, renderCallback);
225 public static void Run(
Control form, RenderCallback renderCallback,
bool useApplicationDoEvents =
false)
227 if(form == null)
throw new ArgumentNullException(
"form");
228 if(renderCallback == null)
throw new ArgumentNullException(
"renderCallback");
231 using (var renderLoop =
new WindowsMessageLoop(form) { UseApplicationDoEvents = useApplicationDoEvents })
233 while(renderLoop.NextFrame())
246 public static bool IsIdle
251 return (
bool)(Win32Native.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0) == 0);