A while ago I showed you how to access Acknex with C# and C++.
Today I will show you, how you can host your Acknex or Lite-C Application inside a Windows Forms Application.
First at all we need some function from the user32.dll, here are three of them:
Code:
internal static class Win32
{
[DllImport("user32.dll", SetLastError = true)]
public static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
public static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
public const int GWL_STYLE = (-16);
public const int WS_VISIBLE = 0x10000000;
}
SetParent is required to change the MainWindowHandle of Acknex.
SetWindowLong is required to change the Style of the window.
and
MoveWindow is required to move and resize the window.
The next step is to create a new WinForms Control, though a Panel on a Form would be enough as well.
Now we have to start the process and to change its window handle.
First at all we create a new process and start it. Then we wait until our new process enters an idle state and copy the window handle of the process to a IntPtr handle in our class.
The last step is to change the window handle, we call our SetParent function from our user32.dll interface and change it. MoveWindow resizes the window and moves it to a 0,0 position so it is fully visible.
Code:
if (!mCreated)
{
mCreated = true;
mAppWnd = IntPtr.Zero;
Process p = null;
try
{
p = Process.Start("acknex.exe", "work/mandelbrot_pure.c");
p.WaitForInputIdle();
mAppWnd = p.MainWindowHandle;
Win32.SetParent(mAppWnd, this.Handle);
Win32.SetWindowLong(mAppWnd, deWin32.GWL_STYLE, deWin32.WS_VISIBLE);
Win32.MoveWindow(mAppWnd, 0, 0, this.Width, this.Height, true);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Our Application", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
And here a screenshot:
ScreenshotThis works with basically every other application, too.
Michael
edit: I recommend you to add Thread.Sleep(TimeSpan.FromSeconds(1)) after p.WaitForInputIdle() to avoid an engine crash.