#include <windows.h> //win32的头文件 #include <tchar.h> #include <gl\gl.h> //opengl32.lib 的头文件 #include <gl\glu.h> //glu32.lib 的头文件 HDC hDC = NULL; //全局的设备描述表句柄 HGLRC hRC = NULL; //Rendering Context句柄 HWND hWnd = NULL; //win32程序的窗口句柄 HINSTANCE hInst; //win32程序的实例句柄 bool Fullscreen = false; int Width = 800; int Height = 600; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //声明窗口过程函数 void InitGL(); //初始化OpenGL void ResizeGLScene(int, int); //当窗口大小变化时,调整OpenGL的投影 void DrawGLScene(); //绘制OpenGL内容 //创建windows窗口并绑定OpenGL //未实现全屏判断 BOOL CreateGLWindow(TCHAR *caption, int bits, BOOL fullscreenflag) { GLuint PixelFormat; WNDCLASS wndclass; //窗口类结构 Fullscreen = fullscreenflag; hInst = GetModuleHandle(NULL); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; //HREDRAW,VREDRAW表示该窗口在大小改变时候将发生WM_PAINT消息; //OWNDC表示该窗口将保存自己的设备描述表属性 wndclass.lpfnWndProc = WndProc; //注册窗口过程 wndclass.cbClsExtra = 0; //额外的窗口信息 wndclass.cbWndExtra = 0; //额外的窗口信息 wndclass.hInstance = hInst; //为什么要用这个函数? wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //窗口图标 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //窗口鼠标图标 wndclass.hbrBackground = NULL; //窗口背景画刷( 因为我们用Opengl绘图,不宜再使用GDI提供的画刷;否则如果选用 // GetStockObject(WHITE_BRUSH),你会发现每次拉动窗口大小时候画面将会被该画刷清除!) wndclass.lpszMenuName = NULL; //该窗口没有菜单 wndclass.lpszClassName = TEXT("OpenGL"); //窗口类名字 //注册该窗口类 if(!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("Failed To Register The Window Class."), TEXT("ERROR"), MB_ICONERROR); return false; } if(Fullscreen) { MessageBox(NULL, TEXT("不好意思,没实现全屏窗口."), TEXT("ERROR"), MB_OK); } //创建程序窗口 hWnd = CreateWindow( TEXT("OpenGL"), TEXT("OpenGL Framework"), WS_OVERLAPPEDWINDOW, 0, //窗口x坐标 0, //窗口y坐标 Width, //窗口宽 Height, //窗口高 NULL, //父窗口句柄 NULL, //窗口菜单句柄 hInst, //程序实例句柄 NULL); //创建附带参数 //CreateWindow函数在返回前,会发送WM_CREATE消息 if(!hWnd) { MessageBox(NULL, TEXT("Failed To Create A Window."), TEXT("ERROR"), MB_ICONERROR); return false; } //设置像素格式 PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), //PIXELFORMATDESCRIPTOR结构体的大小 1, //PIXELFORMATDESCRIPTOR结构体的版本号 PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //定义像素缓存的属性 PFD_TYPE_RGBA, //像素数据类型,可以是RGBA或者是COLORINDEX bits, //每个像素点的颜色位数 0, 0, 0, 0, 0, 0, //忽略每个颜色位 0, //无alpha缓存 0, //忽略移位位 0, //无累加缓存 0, 0, 0, 0, //忽略累加位 16, //16位深度缓存 0, //无模板缓存 0, //无辅助缓存 PFD_MAIN_PLANE, //主层 0, //保留 0, 0, 0 //忽略层,可见性和损毁掩模 }; hDC = GetDC(hWnd); //获得设备描述表 //相应的ReleaseDC在DestroyGLWindow中调用 PixelFormat = ChoosePixelFormat(hDC, &pfd); SetPixelFormat(hDC, PixelFormat, &pfd ); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); InitGL(); //我本来想把这个函数放在WM_CREATE消息中处理。 //但实际上,CreateWindow函数返回之前,就可能发送并处理WM_CREATE消息了。 //而此时上面几句OpenGL绑定到设备描述表的还没做呢 return TRUE; } //销毁OpenGL关联的窗口 void DestroyGLWindow() { if(hRC) { wglMakeCurrent(NULL, NULL); wglDeleteContext(hRC); hRC = NULL; } if(hDC) { ReleaseDC(hWnd, hDC); } } //主程序入口 int WINAPI WinMain( HINSTANCE hInstance, //该实例句柄 HINSTANCE hPrevInstance, //上一个实例 LPSTR lpCmdLine, //启动该实例的命令行参数 int iCmdShow) //程序初始显示方法 { MSG msg; //windows消息结构 BOOL quit = FALSE; //用来判断是否跳出循环 BOOL fullscreenflag = true; //全屏标志 float theta = 0.0; if(MessageBox(NULL, TEXT("Would U Like To Run In Fullscreen Mode?"), TEXT("Start Fullscreen?"), MB_YESNO|MB_ICONQUESTION) == IDNO) { fullscreenflag = false; } if(!CreateGLWindow(TEXT("OpenGL Framework"), 16, fullscreenflag)) { return 0; } ShowWindow(hWnd, SW_SHOW); //只是CreateWindow的话,窗口只是在内存中创建好了,只有调用了ShowWindow后才会显示窗口 //ShowWindow函数在显示窗口时,会发送第一个WM_SIZE消息;但具体是在ShowWindow最后返回前还是其他什么时候,我还不知道 //UpdateWindow(hWnd); //UpdateWindow函数会发送WM_PAINT消息来更新窗口客户区 //由于我们用了OpenGL,所以这里可以不需调用UpdateWindow while(!quit) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) //提取消息,如果此时没有消息,则不等待,立即返回false { if(msg.message == WM_QUIT) { quit = TRUE; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } else { DrawGLScene(); SwapBuffers( hDC ); } } DestroyGLWindow(); return msg.wParam; } //窗口过程 LRESULT CALLBACK WndProc( HWND hwnd, //窗口句柄 UINT message, //接收到的消息 WPARAM wParam, //消息的附加参数 LPARAM lParam) //消息的附加参数 { switch(message) { case WM_SIZE: //窗口大小改变,或者第一次显现窗口时(ShowWindow),都将发送该消息 ResizeGLScene(LOWORD(lParam), HIWORD(lParam)); return 0; case WM_DESTROY: PostQuitMessage(0); //发送WM_QUIT消息 return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } //初始化OpenGL一些属性 void InitGL() { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); } //根据窗口大小的变化 void ResizeGLScene(int width, int height) { glViewport(0, 0, (GLsizei)width, (GLsizei)height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); glMatrixMode(GL_MODELVIEW); } //OpenGL绘图 void DrawGLScene() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glLoadIdentity(); gluLookAt( 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glScalef(1.0, 2.0, 1.0); glBegin(GL_TRIANGLES); glVertex3f( 0.0, 1.0, 0.0); glVertex3f(-1.0, -1.0, 0.0); glVertex3f( 1.0, -1.0, 0.0); glEnd(); }