使用Tao框架,OpenGL / WGL / WinAPI的C#绑定,我试图使空白的WinAPI窗口显示OpenGL图形。此代码似乎不起作用。窗口打开,但是什么也没画。大多数OpenGL / GDI代码都是从Tao的 SimpleOpenGLControl UserControl镜像的。
Tao & Custom Win32 Wrappers
public static string Hello = "Hello";
public static string AppName = "DrawHello Program";
public static string ClassName = "DrawHelloClass";
public static int screenx = 250;
public static int screeny = 250;
public static int width = 640;
public static int height = 480;
public static IntPtr hWnd;
public static IntPtr renderingContext = IntPtr.Zero;
public static IntPtr deviceContext = IntPtr.Zero;
public static byte accumBits = 0; // Accumulation buffer bits
public static byte colorBits = 32; // Color buffer bits
public static byte depthBits = 16; // Depth buffer bits
public static byte stencilBits = 0; // Stencil buffer bits
public static int logScaleX = 96; // DPI Resolution in X dir
public static int logScaleY = 96;
public static void redraw()
{
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glBegin(Gl.GL_QUADS);
Gl.glVertex3f(0.5F, 0.5F, 0.5F); Gl.glVertex3f(-0.5F, 0.5F, 0.5F);
Gl.glVertex3f(-0.5F, -0.5F, 0.5F); Gl.glVertex3f(0.5F, -0.5F, 0.5F);
Gl.glVertex3f(-0.5F, -0.5F, -0.5F); Gl.glVertex3f(-0.5F, 0.5F, -0.5F);
Gl.glVertex3f(0.5F, 0.5F, -0.5F); Gl.glVertex3f(0.5F, -0.5F, -0.5F);
Gl.glVertex3f(0.5F, 0.5F, 0.5F); Gl.glVertex3f(0.5F, 0.5F, -0.5F);
Gl.glVertex3f(-0.5F, 0.5F, -0.5F); Gl.glVertex3f(-0.5F, 0.5F, 0.5F);
Gl.glVertex3f(-0.5F, -0.5F, -0.5F); Gl.glVertex3f(0.5F, -0.5F, -0.5F);
Gl.glVertex3f(0.5F, -0.5F, 0.5F); Gl.glVertex3f(-0.5F, -0.5F, 0.5F);
Gl.glVertex3f(0.5F, 0.5F, 0.5F); Gl.glVertex3f(0.5F, -0.5F, 0.5F);
Gl.glVertex3f(0.5F, -0.5F, -0.5F); Gl.glVertex3f(0.5F, 0.5F, -0.5F);
Gl.glVertex3f(-0.5F, -0.5F, -0.5F); Gl.glVertex3f(-0.5F, -0.5F, 0.5F);
Gl.glVertex3f(-0.5F, 0.5F, 0.5F); Gl.glVertex3f(-0.5F, 0.5F, -0.5F);
Gl.glEnd();
}
[STAThread]
static void Main()
{
Win32.MSG Msg = new Win32.MSG();
int rv;
if (Program.RegisterClass() == 0)
return;
if (Program.Create() == 0)
return;
// Main message loop:
while ((rv = Win32.GetMessage(out Msg, IntPtr.Zero, 0, 0)) > 0)
{
Win32.TranslateMessage(ref Msg);
Win32.DispatchMessage(ref Msg);
}
}
private static int RegisterClass()
{
Win32.WNDCLASSEX wcex = new Win32.WNDCLASSEX();
wcex.style = Win32.ClassStyles.DoubleClicks;
wcex.cbSize = (uint)Marshal.SizeOf(wcex);
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hIcon = Win32.LoadIcon(IntPtr.Zero, (IntPtr)Win32.IDI_APPLICATION);
wcex.hCursor = Win32.LoadCursor(IntPtr.Zero, (int)Win32.IDC_ARROW);
wcex.hIconSm = IntPtr.Zero;
wcex.hbrBackground = (IntPtr)(10);
wcex.lpszMenuName = null;
wcex.lpszClassName = ClassName;
if (Win32.RegisterClassEx(ref wcex) == 0)
{
Win32.MessageBox(IntPtr.Zero, "RegisterClassEx failed", AppName,
(int)(Win32.MB_OK | Win32.MB_ICONEXCLAMATION | Win32.MB_SETFOREGROUND));
return (0);
}
return (1);
}
private static int Create()
{
hWnd = Win32.CreateWindowEx(0, ClassName, AppName, Win32.WS_OVERLAPPEDWINDOW | Win32.WS_VISIBLE,
screenx, screeny, width, height, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
InitializeContexts();
if (hWnd != IntPtr.Zero)
return (1);
Win32.MessageBox(IntPtr.Zero, "CreateWindow failed", AppName,
(int)(Win32.MB_OK | Win32.MB_ICONEXCLAMATION | Win32.MB_SETFOREGROUND));
return (0);
}
private static IntPtr WndProc(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam)
{
switch (message)
{
case Win32.WM_PAINT:
{
IntPtr hDC;
Win32.PAINTSTRUCT ps = new Win32.PAINTSTRUCT();
hDC = Win32.BeginPaint(hWnd, out ps);
redraw();
Gdi.SwapBuffersFast(deviceContext);
Win32.EndPaint(hWnd, ref ps);
return IntPtr.Zero;
}
case Win32.WM_DESTROY:
DestroyContexts();
Win32.PostQuitMessage(0);
return IntPtr.Zero;
//case Win32.WM_CREATE:
// return IntPtr.Zero;
default:
return (Win32.DefWindowProc(hWnd, message, wParam, lParam));
}
}
public static void MakeCurrent()
{
Wgl.wglMakeCurrent(deviceContext, renderingContext);
}
public static void InitializeContexts()
{
int pixelFormat;
Gdi.PIXELFORMATDESCRIPTOR pfd = new Gdi.PIXELFORMATDESCRIPTOR();// The pixel format descriptor
pfd.nSize = (short)Marshal.SizeOf(pfd); // Size of the pixel format descriptor
pfd.nVersion = 1; // Version number (always 1)
pfd.dwFlags = Gdi.PFD_DRAW_TO_WINDOW | // Format must support windowed mode
Gdi.PFD_SUPPORT_OPENGL | // Format must support OpenGL
Gdi.PFD_DOUBLEBUFFER; // Must support double buffering
pfd.iPixelType = (byte)Gdi.PFD_TYPE_RGBA; // Request an RGBA format
pfd.cColorBits = (byte)colorBits; // Select our color depth
pfd.cRedBits = 0; // Individual color bits ignored
pfd.cRedShift = 0;
pfd.cGreenBits = 0;
pfd.cGreenShift = 0;
pfd.cBlueBits = 0;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0; // No alpha buffer
pfd.cAlphaShift = 0; // Alpha shift bit ignored
pfd.cAccumBits = accumBits; // Accumulation buffer
pfd.cAccumRedBits = 0; // Individual accumulation bits ignored
pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = depthBits; // Z-buffer (depth buffer)
pfd.cStencilBits = stencilBits; // No stencil buffer
pfd.cAuxBuffers = 0; // No auxiliary buffer
pfd.iLayerType = (byte)Gdi.PFD_MAIN_PLANE; // Main drawing layer
pfd.bReserved = 0; // Reserved
pfd.dwLayerMask = 0; // Layer masks ignored
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;
deviceContext = User.GetDC(hWnd);
pixelFormat = Gdi.ChoosePixelFormat(deviceContext, ref pfd);
logScaleX = Gdi.GetDeviceCaps(deviceContext, (int)Gdi.DevCaps.LOGPIXELSX);
logScaleY = Gdi.GetDeviceCaps(deviceContext, (int)Gdi.DevCaps.LOGPIXELSY);
renderingContext = Wgl.wglCreateContext(deviceContext);
MakeCurrent();
Kernel.SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
}
public static void DestroyContexts()
{
Wgl.wglMakeCurrent(IntPtr.Zero, IntPtr.Zero);
Wgl.wglDeleteContext(renderingContext);
User.ReleaseDC(hWnd, deviceContext);
renderingContext = IntPtr.Zero;
deviceContext = IntPtr.Zero;
}