我正在尝试使用DllImport
在C#中加载OpenGL和WinApi函数。由于某种原因,尽管OpenGL不会渲染。我尝试使用glGetError
,但是没有错误(在创建glContext之前没有错误1282,但是我敢肯定这是可以预期的)。窗户只是保持白色。我已经使用完全相同的功能在C ++中完成了完全相同的操作,它工作得很好,但是由于某种原因,它在C#中不起作用。
DllImports
for WinApi
public enum ClassStyle
{
OwnDC = 0x0020
}
public enum WindowStyle
{
MinimizeBox = 0x20000,
SystemMenu = 0x80000
}
public enum Pfd
{
SupportOpenGL = 0x00000020,
DrawToWindow = 0x00000004
}
public enum PM
{
Remove = 0x0001
}
public enum WindowMsg
{
Quit = 0x0012,
Destroy = 0x0002
}
public struct WndClassEx
{
public int size;
public int style;
public WndProcD windowProc;
public int clsExtra;
public int windowExtra;
public IntPtr hInstance;
public IntPtr icon;
public IntPtr cursor;
public IntPtr background;
public string menuName;
public string className;
public IntPtr iconSm;
public static int GetSize()
{
return Marshal.SizeOf(typeof(WndClassEx));
}
}
public struct Msg
{
public IntPtr window;
public uint message;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public IntPtr pt;
public uint lPrivate;
}
public struct PixelFormatDescriptor
{
public int size;
public ushort version;
public uint flags;
public byte pixelType;
public byte colorBits;
public byte redBits;
public byte redShift;
public byte greenBits;
public byte greenShift;
public byte blueBits;
public byte blueShift;
public byte alphaBits;
public byte alphaShift;
public byte accumRedBits;
public byte accumGreenBits;
public byte accumBlueBits;
public byte accumAlphaBits;
public byte depthBits;
public byte stencilBits;
public byte auxBuffers;
public byte layerType;
public byte reserved;
public uint layerMask;
public uint visibleMask;
public uint damageMask;
public static int GetSize()
{
return Marshal.SizeOf(typeof(PixelFormatDescriptor));
}
}
public delegate IntPtr WndProcD(IntPtr window, uint msg, IntPtr w, IntPtr l);
[DllImport("user32.dll")]
public static extern IntPtr DefWindowProc(IntPtr window, uint msg, IntPtr w, IntPtr l);
[DllImport("user32.dll")]
public static extern int RegisterClassEx(ref WndClassEx wndClassEx);
[DllImport("user32.dll")]
public static extern IntPtr CreateWindowEx(uint exStyle, string className, string windowName, uint style, int x, int y, int w, int h, IntPtr parent, IntPtr menu, IntPtr hInstance, IntPtr param);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr window, int show);
[DllImport("user32.dll")]
public static extern bool DestroyWindow(IntPtr window);
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr window);
[DllImport("gdi32.dll")]
public static extern int ChoosePixelFormat(IntPtr windowDC, ref PixelFormatDescriptor pfd);
[DllImport("gdi32.dll")]
public static extern bool SetPixelFormat(IntPtr windowDC, int choosenPixelFormat, ref PixelFormatDescriptor pfd);
[DllImport("user32.dll")]
public static extern bool PeekMessage(out Msg msg, IntPtr window, uint filterMin, uint filterMax, uint removeMsg);
[DllImport("user32.dll")]
public static extern bool TranslateMessage(ref Msg msg);
[DllImport("user32.dll")]
public static extern IntPtr DispatchMessage(ref Msg msg);
[DllImport("kernel32.dll")]
public static extern int GetLastError();
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name);
DllImports
for OpenGL
public const uint ColorBufferBit = 0x00004000;
public const uint Quads = 0x007;
[DllImport("opengl32.dll", EntryPoint = "wglCreateContext")]
public static extern IntPtr CreateContext(IntPtr windowDC);
[DllImport("opengl32.dll", EntryPoint = "wglMakeCurrent")]
public static extern IntPtr MakeCurrent(IntPtr windowDC, IntPtr glContext);
[DllImport("opengl32.dll", EntryPoint = "glBegin")]
public static extern void Begin(uint mode);
[DllImport("opengl32.dll", EntryPoint = "glEnd")]
public static extern void End();
[DllImport("opengl32.dll", EntryPoint = "glFlush")]
public static extern void Flush();
[DllImport("opengl32.dll", EntryPoint = "glClear")]
public static extern void Clear(uint mask);
[DllImport("opengl32.dll", EntryPoint = "glClearColor")]
public static extern void ClearColor(float r, float g, float b, float a);
[DllImport("opengl32.dll", EntryPoint = "glBindTexture")]
public static extern void BindTexture(uint mode, uint texture);
[DllImport("opengl32.dll", EntryPoint = "glEnable")]
public static extern void Enable(uint cap);
[DllImport("opengl32.dll", EntryPoint = "glColor3f")]
public static extern void Color3(float r, float g, float b);
[DllImport("opengl32.dll", EntryPoint = "glVertex3f")]
public static extern void Vertex3(float x, float y, float z);
[DllImport("opengl32.dll", EntryPoint = "glVertex3i")]
public static extern void Vertex3(int x, int y, int z);
[DllImport("opengl32.dll", EntryPoint = "glVertex3d")]
public static extern void Vertex3(double x, double y, double z);
[DllImport("opengl32.dll", EntryPoint = "glVertex3s")]
public static extern void Vertex3(short x, short y, short z);
[DllImport("opengl32.dll", EntryPoint = "glVertex2f")]
public static extern void Vertex2(float x, float y);
[DllImport("opengl32.dll", EntryPoint = "glVertex2i")]
public static extern void Vertex2(int x, int y);
[DllImport("opengl32.dll", EntryPoint = "glVertex2d")]
public static extern void Vertex2(double x, double y);
[DllImport("opengl32.dll", EntryPoint = "glVertex2s")]
public static extern void Vertex2(short x, short y);
[DllImport("opengl32.dll", EntryPoint = "glTexCoord3f")]
public static extern void TexCoord3(float x, float y);
[DllImport("opengl32.dll", EntryPoint = "glTexCoord3i")]
public static extern void TexCoord3(int x, int y);
[DllImport("opengl32.dll", EntryPoint = "glTexCoord3d")]
public static extern void TexCoord3(double x, double y);
[DllImport("opengl32.dll", EntryPoint = "glTexCoord3s")]
public static extern void TexCoord3(short x, short y);
[DllImport("opengl32.dll", EntryPoint = "glTexCoord2f")]
public static extern void TexCoord2(float x, float y, float z);
[DllImport("opengl32.dll", EntryPoint = "glTexCoord2i")]
public static extern void TexCoord2(int x, int y, int z);
[DllImport("opengl32.dll", EntryPoint = "glTexCoord2d")]
public static extern void TexCoord2(double x, double y, double z);
[DllImport("opengl32.dll", EntryPoint = "glTexCoord2s")]
public static extern void TexCoord2(short x, short y, short z);
[DllImport("opengl32.dll", EntryPoint = "glGetError")]
public static extern uint GetError();
[DllImport("glu32.dll", EntryPoint = "gluErrorString")]
public static extern string ErrorString(uint code);
主要
static void Main()
{
string name = "TestWin";
Win.WndClassEx windowClass = new Win.WndClassEx();
windowClass.className = name;
windowClass.size = Win.WndClassEx.GetSize();
windowClass.hInstance = Win.GetModuleHandle(null);
windowClass.style = (int)Win.ClassStyle.OwnDC;
windowClass.windowProc = WndProc;
if (Win.RegisterClassEx(ref windowClass) == 0)
{
Console.WriteLine("Failed to register window class!");
Console.WriteLine("Error: " + Win.GetLastError());
Thread.Sleep(3000);
return;
}
IntPtr window = Win.CreateWindowEx(0, name, "TEST", (uint)(Win.WindowStyle.MinimizeBox | Win.WindowStyle.SystemMenu), 160, 160, 640, 640, IntPtr.Zero, IntPtr.Zero, windowClass.hInstance, IntPtr.Zero);
if (window == null)
{
Console.WriteLine("Failed to create window!");
Console.WriteLine("Error: " + Win.GetLastError());
Thread.Sleep(3000);
return;
}
IntPtr windowDC = Win.GetDC(window);
Win.ShowWindow(window, 1);
Win.PixelFormatDescriptor pfd = new Win.PixelFormatDescriptor();
pfd.version = 1;
pfd.size = Win.PixelFormatDescriptor.GetSize();
pfd.flags = (uint)(Win.Pfd.DrawToWindow | Win.Pfd.SupportOpenGL);
pfd.pixelType = 0;
pfd.colorBits = 32;
int choosenPixelFormat = Win.ChoosePixelFormat(windowDC, ref pfd);
if (choosenPixelFormat == 0)
{
Console.WriteLine("Failed to choose pixel format!");
Console.WriteLine("Error: " + Win.GetLastError());
Thread.Sleep(3000);
return;
}
if (!Win.SetPixelFormat(windowDC, choosenPixelFormat, ref pfd))
{
Console.WriteLine("Failed to set pixel format!");
Console.WriteLine("Error: " + Win.GetLastError());
Thread.Sleep(3000);
return;
}
IntPtr glContext = GL.CreateContext(windowDC);
if (glContext == null)
{
Console.WriteLine("Failed to create opengl context!");
Console.WriteLine("Error: " + GL.GetError());
Thread.Sleep(3000);
return;
}
GL.MakeCurrent(windowDC, glContext);
while (true)
{
int frameStart = Environment.TickCount;
Win.Msg msg = new Win.Msg();
while (Win.PeekMessage(out msg, IntPtr.Zero, 0, 0, (uint)Win.PM.Remove))
{
Win.TranslateMessage(ref msg);
Win.DispatchMessage(ref msg);
}
GL.Clear(GL.ColorBufferBit);
GL.Begin(GL.Quads);
GL.Color3(1.0f, 0.0f, 0.0f);
GL.Vertex2(-0.5f, -0.5f);
GL.Vertex2(-0.5f, 0.5f);
GL.Vertex2(0.5f, 0.5f);
GL.Vertex2(0.5f, -0.5f);
GL.End();
GL.Flush();
int frameTime = Environment.TickCount - frameStart;
if (frameTime < 1000 / 60)
Thread.Sleep((1000 / 60) - frameTime);
}
}
static IntPtr WndProc(IntPtr window, uint msg, IntPtr w, IntPtr l)
{
switch (msg)
{
case (uint)Win.WindowMsg.Quit:
Win.DestroyWindow(window);
break;
case (uint)Win.WindowMsg.Destroy:
Environment.Exit(0);
break;
default:
return Win.DefWindowProc(window, msg, w, l);
}
return IntPtr.Zero;
}