I'm currently writing custom game engine (for self education) and working on window system. I need to create basic OS window (so I can later link it as a device for DirectX or to create context for OpenGL, etc). I found an example of creating Win32 window with C# so I used it as a prototype (example code is working properly on my machine), but the source was made like a separate program, and I need to implement it as a class, from which i can get an IntPtr to created window.
I wrote my own Win32Window class, implementing all required features. Then, I used another project to test it out (i'm writing this class as a part of my gameengine dll), but it fails to create window. Another questions (on Stackoverflow and other forums) that touch this topic, have different issues that come from using winApi features i don't need (like controls and other stuff) or incorrect order of registering window class and creating window.
As the title says, I found out that the CreateWindowEx returns null.
Marshal.GetLastWin32Error says that CreateWindowEx cannot find registered class.
I tried to use variable string in the place of ClassName, so i dont missprint the name.
I tried to use overloaded version of CreateWindowEx with IntPtr to registered class.
Neither of them worked.
All the managed code for WinApi was taken from Pinvoke.com and MSDN documentation.
The problem is definetly not caused by not giving an actual hInstance pointer to RegisterClassEx and CreateWindowEx instead of IntPtr.Zero.
Here is window class code:
public sealed class Win32Window : NativeWindow // NativeWindow is my engine's window API containing some size, name and pointer properties
{
-- Some properties and fields routine --
//Constructor takes job of registering class
public Win32Window(string WindowName, WndProc CallBack)
{
this.WindowName = WindowName;
this.Callback = CallBack;
this.wc = WNDCLASSEX.Build();
this.wc.style = (int)(CS.HRedraw | CS.VRedraw);
this.wc.lpfnWndProc = this.Callback;
this.wc.hInstance = IntPtr.Zero;
this.wc.hCursor = LoadCursor(IntPtr.Zero, (int)IDC.Arrow);
this.wc.hbrBackground = IntPtr.Zero;
this.wc.lpszClassName = ClassName;
this.wc.cbClsExtra = 0;
this.wc.cbWndExtra = 0;
this.wc.hIcon = LoadIcon(IntPtr.Zero,(IntPtr)IDI_APPLICATION);
this.wc.lpszMenuName = null;
this.wc.hIconSm = IntPtr.Zero;
ClassPtr = (IntPtr)RegisterClassEx(ref this.wc);
Console.WriteLine(ClassPtr); //Outputs negative integer, so i can conclude this part works properly
}
public void Create()
{
this.WindowHandle = CreateWindowEx(0,
ClassName,
this.WindowName,
(uint)WS.OverlappedWindow,
this.PosX,
this.PosY,
this.Width,
this.Height,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero);
Console.WriteLine($"{WindowHandle == IntPtr.Zero} {Marshal.GetLastWin32Error()}"); //Outputs "True 1407"
}
public void Show()
{
ShowWindow(this.WindowHandle, 1);
}
public void Iterate()
{
while (GetMessage(out msg, IntPtr.Zero, 0, 0) > 0)
{
TranslateMessage(ref msg);
DispatchMessage(ref msg);
}
--- Some [DllImport] routine ---
}
Here is TestWindow class code:
public class TestWindow
{
Win32Window.WndProc callback;
Win32Window Window;
private static IntPtr WndProc(IntPtr hWnd, Win32Window.WM message, IntPtr wParam, IntPtr lParam)
{
Console.WriteLine(message);
switch (message)
{
case Win32Window.WM.Destroy:
Win32Window.PostQuitMessage(0);
return IntPtr.Zero;
default:
return (Win32Window.DefWindowProc(hWnd, message, wParam, lParam));
}
}
public TestWindow()
{
callback = WndProc;
Window = new Win32Window("TestWindow", callback);
Window.Create();
Window.Show();
Window.Iterate();
}
}
The Main method of test console app is just creating a new instance of TestWindow.