OpenGL显示汉字

 

//

// 汉字类

//

//GLFont.h文件
#include <windows.h>
#include "gl/gl.h"
#pragma warning(disable:4244)
//OpenGL汉字显示类
class GLfont
    {
  HFONT hFont;
  COLORREF cl;
public:
 GLfont();
 virtual ~GLfont();
 void SetTextColor(COLORREF textcolor);//字体颜色设置
 void CreateFont(char *facename, int height, int weight, bool italic,bool underline,bool strikeout);
 void ShowText(int x, int y, LPCTSTR lpszText);//显示图象2D汉字
 void Show2DText(char *str);//显示图形2D汉字
 void Show3DText(unsigned char *str);//显示图形3D汉字
};

GLfont::GLfont()
   {
 cl=RGB(255,255,255);
}
GLfont::~GLfont()
   {
 if(hFont) DeleteObject(hFont);
}

//只有关闭光照和纹理才能正确显示颜色
void GLfont::SetTextColor(COLORREF textcolor)//字体颜色设置
   {
 cl=textcolor;
}
void GLfont::CreateFont(char *facename, int height, int weight, bool italic,bool underline,bool strikeout)
   {
 LOGFONT lf;
 lf.lfHeight = height;
 lf.lfWidth = 0;
 lf.lfEscapement = 0;
 lf.lfOrientation = 0;
 lf.lfWeight = weight;
 lf.lfItalic = italic;
 lf.lfUnderline = underline;
 lf.lfStrikeOut = strikeout;
 lf.lfCharSet = DEFAULT_CHARSET;
 lf.lfOutPrecision = OUT_TT_PRECIS;
 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
 lf.lfQuality = PROOF_QUALITY;
 lf.lfPitchAndFamily = VARIABLE_PITCH | TMPF_TRUETYPE | FF_MODERN;
 strcpy(lf.lfFaceName,facename);
 // 创建字体
 hFont = CreateFontIndirect(&lf);
}

//2D图像汉字只与屏幕相联系,与具体的变换矩阵无关,也就是说不能缩放旋转。
//x,y是2D图像汉字距屏幕左下角(注意不是左上角)的横向和纵向距离。
void GLfont::ShowText(int x, int y, LPCTSTR lpszText)
   {
 // 保存原投影矩阵,将投影矩阵设为平行投影
 glMatrixMode( GL_PROJECTION );
 glPushMatrix();
 glLoadIdentity();
 glOrtho( 0, 640, 0, 480, -1, 1 );
 // 保存原模型变换矩阵,平移至( x, y )
 glMatrixMode( GL_MODELVIEW );
 glPushMatrix();
 glLoadIdentity();
 RECT rect;
 GetClientRect(GetActiveWindow(),&rect);
 glTranslatef((float)x,(float)y,0);
 HBITMAP hbitmap;
 BITMAP bm;
 SIZE size;
 UCHAR* pBmpBits;
 HFONT hOldFont;
 HDC hdc = wglGetCurrentDC();
 hOldFont = (HFONT)SelectObject(hdc, hFont);
 ::GetTextExtentPoint32(hdc, lpszText, strlen(lpszText), &size);
 hbitmap = CreateBitmap(size.cx, size.cy,1, 1, NULL);
 HDC hMemDC = ::CreateCompatibleDC(hdc);
 if(hMemDC)
     {
   HBITMAP hPrevBmp = (HBITMAP)SelectObject(hMemDC,hbitmap);
   HFONT hPrevFont = (HFONT)SelectObject(hMemDC, hFont);
   SetBkColor(hMemDC, RGB(0, 0, 0));
   ::SetTextColor(hMemDC,RGB(255,255,255));
   SetBkMode(hMemDC, OPAQUE);
   TextOut(hMemDC, 0, 0, lpszText, strlen(lpszText));
   //把GDI位图复制到DIB
   SelectObject(hdc,hbitmap);
   GetObject(hbitmap, sizeof(bm), &bm);
   size.cx = (bm.bmWidth + 31) & (~31);
   size.cy = bm.bmHeight;
   int bufsize = size.cy * (((bm.bmWidth + 31) & (~31)) /8);
   pBmpBits = new UCHAR[bufsize];
   memset(pBmpBits, 0, sizeof(UCHAR)*bufsize);
   struct
       {
     BITMAPINFOHEADER bih;
     RGBQUAD col[2];
   }
   bic;
   BITMAPINFO *binf = (BITMAPINFO *)&bic;
   binf->bmiHeader.biSize = sizeof(binf->bmiHeader);
   binf->bmiHeader.biWidth = bm.bmWidth;
   binf->bmiHeader.biHeight = bm.bmHeight;
   binf->bmiHeader.biPlanes = 1;
   binf->bmiHeader.biBitCount = 1;
   binf->bmiHeader.biCompression = BI_RGB;
   binf->bmiHeader.biSizeImage = bufsize;
   binf->bmiHeader.biXPelsPerMeter = 1;
   binf->bmiHeader.biYPelsPerMeter = 1;
   binf->bmiHeader.biClrUsed = 0;
   binf->bmiHeader.biClrImportant = 0;
   ::GetDIBits(hdc, hbitmap, 0, bm.bmHeight, pBmpBits, binf,DIB_RGB_COLORS);
   SelectObject(hMemDC,hPrevBmp);
 }
 ::DeleteDC(hMemDC);
 SelectObject(hdc, hOldFont);

 //显示文字
 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 glColor3f(GetRValue(cl)/255.0,GetGValue(cl)/255.0,GetBValue(cl)/255.0);
 glRasterPos2i(x,y);
 glBitmap(size.cx, size.cy, 0.0, 2.0, size.cx+2.0f, 0.0, pBmpBits);
 delete pBmpBits;
 // 恢复投影矩阵和模型变换矩阵
 glMatrixMode(GL_PROJECTION);
 glPopMatrix();
 glMatrixMode(GL_MODELVIEW);
 glPopMatrix();
 glColor3f(1.0,1.0,1.0);
}

void GLfont::Show2DText(char *str)
   {
 char FTextList[255];
 GLYPHMETRICSFLOAT gmf[256];
 int m_iCount=strlen(str);   
 GLuint m_listbase;
 HDC hDC=wglGetCurrentDC();
 glPushMatrix();

 SelectObject(hDC,hFont);
 int  i=0;
 int  j=0;
 int ich,cch;
 m_listbase = glGenLists(256);
 glColor3f(GetRValue(cl)/255.0,GetGValue(cl)/255.0,GetBValue(cl)/255.0);
 while(i<m_iCount)
     {
   if(IsDBCSLeadByte(str[i]))
       {
     //判断是否为双字节
     ich=str[i];
     ich=(ich<<8)+256; /**/256为汉字内码“偏移量”
     ich=ich+str[i+1];
     i++;i++;
     wglUseFontOutlines(hDC,//字体轮廓设备联系DC
      ich, //要转换为显示列表的第一个字符
      1, //要转换为显示列表的字符数
      m_listbase+j,//显示列表的基数
      1.0f, //指定与实际轮廓的最大偏移量
      0,//0.15f, //在Z轴负方向的值
      WGL_FONT_POLYGONS, //指定显示列表线段或多边形
      &gmf[j]); //接受字符的地址
     FTextList[j]=j;
     j++;

   }
   else
       {
     cch=str[i];
     i++;
     wglUseFontOutlines(hDC, //字体轮廓设备联系DC
      cch,//要转换为显示列表的第一个字符
      1,//要转换为显示列表的字符数
      m_listbase+j,//显示列表的基数
      0.0f,//指定与实际轮廓的最大偏移量
      0.0,//0.15f,//在Z轴负方向的值
      WGL_FONT_POLYGONS, //指定显示列表线段或多边形
      &gmf[j]);//接受字符的地址
     FTextList[j]=j;
     j++;
   }
 }

 glPushAttrib(GL_LIST_BIT);
    {
  glListBase(m_listbase);
  glCallLists(m_iCount, GL_UNSIGNED_BYTE, &FTextList);
 }
 glPopAttrib();
 glPopMatrix();
 glColor3f(1.0,1.0,1.0);
}
void GLfont::Show3DText(unsigned char *str)
   {
 glPushMatrix();
 GLYPHMETRICSFLOAT pgmf[1];

 HDC hDC=wglGetCurrentDC();
 //设置当前字体
 SelectObject(wglGetCurrentDC(),hFont);

 DWORD dwChar;
 int ListNum;
 for(size_t i=0;i<strlen((char *)str);i++)
     {
   if(IsDBCSLeadByte(str[i]))
       {
     dwChar=(DWORD)((str[i]<<8)|str[i+1]);
     i++;
   }
   else
    dwChar=str[i];
   ListNum=glGenLists(1);
   glColor3f(GetRValue(cl)/255.0,GetGValue(cl)/255.0,GetBValue(cl)/255.0);
   wglUseFontOutlines(hDC,dwChar,1,ListNum,0.0,0.1f,WGL_FONT_POLYGONS,pgmf);
   glCallList(ListNum);
   glDeleteLists(ListNum,1);
 }
 glPopMatrix();
 glColor3f(1.0,1.0,1.0);
}

 

 

 

 

//

// 完整代码

//

 

#include <windows.h>        // Windows的头文件
#include <GL/gl.h>        // 包含最新的gl.h,glu.h库
#include <GL/glu.h>        // 包含OpenGL实用库
#include <GL/glaux.h>
#include <stdio.h>         // 标准输入/输出库的头文件
#include <math.h>
#define D_PI 3.141592653       
#include "GLFont.h"      //引入OpenGL汉字显示类文件
#pragma warning(disable:4305)
#pragma warning(disable:4244)

HDC            hDC=NULL;        // 窗口着色描述表句柄
HGLRC        hRC=NULL;        // OpenGL渲染描述表句柄
HWND        hWnd=NULL;        // 保存我们的窗口句柄
HINSTANCE    hInstance;        // 保存程序的实例

bool keys[256];            // 保存键盘按键的数组
bool active=TRUE;        // 窗口的活动标志,缺省为TRUE
bool fullscreen=TRUE;    // 全屏标志缺省,缺省设定成全屏模式
LRESULT    CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);    // WndProc的定义

BOOL light;                                    // 光源的开/关
bool lp;
GLfloat LightAmbient[]= {0.5f,0.5f,0.5f,1.0f};
GLfloat LightDiffuse[]= {1.0f,1.0f,1.0f,1.0f};
GLfloat LightPosition[]= {0.0f,0.0f,2.0f,1.0f};
GLuint    texture[3];
GLfont f;
AUX_RGBImageRec *LoadBMP(char *Filename)                    // 载入位图图象
 {
 FILE *File=NULL;                            // 文件句柄
 if(!Filename)                                // 确保文件名已提供
   {
   return NULL;                            // 如果没提供,返回 NULL
 }
 File=fopen(Filename,"r");                        // 尝试打开文件
 if(File)                                // 文件存在么?
   {
   fclose(File);                            // 关闭句柄
   return auxDIBImageLoad(Filename);                // 载入位图并返回指针
 }
 return NULL;                                // 如果载入失败,返回 NULL
}
int LoadGLTextures()                                // 载入位图(调用上面的代码)并转换成纹理
 {
 int Status=FALSE;                            // 状态指示器
 AUX_RGBImageRec *TextureImage[1];                    // 创建纹理的存储空间
 memset(TextureImage,0,sizeof(void *)*1);                // 将指针设为 NULL
 // 载入位图,检查有无错误,如果位图没找到则退出
 if(TextureImage[0]=LoadBMP("Data/NeHe.bmp"))
   {
   Status=TRUE;                            // 将 Status 设为 TRUE
   glGenTextures(3, &texture[0]);                    // 创建纹理

   // 创建 Nearest 滤波贴图
   glBindTexture(GL_TEXTURE_2D, texture[0]);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
   glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
   // 创建线性滤波纹理
   glBindTexture(GL_TEXTURE_2D, texture[1]);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
   // 创建 MipMapped 纹理
   glBindTexture(GL_TEXTURE_2D, texture[2]);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
   gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
 }
 if (TextureImage[0])                            // 纹理是否存在
   {
   if (TextureImage[0]->data)                    // 纹理图像是否存在
     {
     free(TextureImage[0]->data);                // 释放纹理图像占用的内存
   }       
   free(TextureImage[0]);                        // 释放图像结构
 }
 return Status;                                // 返回 Status
}


GLvoid ReSizeGLScene(GLsizei width, GLsizei height)        // 重置OpenGL窗口大小
 {
 if (height==0)                                        // 防止被零除
   {
   height=1;                                        // 将Height设为1
 }

 glViewport(0,0,width,height);                        // 重置当前的视口

 glMatrixMode(GL_PROJECTION);                        // 选择投影矩阵
 glLoadIdentity();                                    // 重置投影矩阵

 // 设置视口的大小
 gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

 glMatrixMode(GL_MODELVIEW);                            // 选择模型观察矩阵
 glLoadIdentity();                                    // 重置模型观察矩阵
}

GLfloat mat_ambient[]=  { 0.8, 0.8, 0.8, 1.0 };
GLfloat mat_diffuse[]=  { 0.8, 0.0, 0.8, 1.0 };/**//* 紫色 */
GLfloat mat_specular[] =  { 1.0, 0.0, 1.0, 1.0 };
GLfloat mat_shininess[] =  { 100.0 };

int InitGL(GLvoid)                                    // 此处开始对OpenGL进行所有设置
 {
 //glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); //启用双面光照
 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);   
 glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
 glEnable(GL_LIGHT1);

 f.CreateFont("隶书",80,80,0,0,0);   
 if(!LoadGLTextures())
 {
   return false;
 }
 glEnable(GL_TEXTURE_2D);

 glShadeModel(GL_SMOOTH);                            // 启用阴影平滑

 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);                // 黑色背景
 glClearDepth(1.0f);                                    // 设置深度缓存
 glEnable(GL_DEPTH_TEST);                            // 启用深度测试
 glDepthFunc(GL_LEQUAL);                                // 所作深度测试的类型
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    // 告诉系统对透视进行修正

 //glPolygonMode( GL_BACK, GL_LINE);            // 后表面完全填充
 //glPolygonMode( GL_FRONT, GL_FILL);            // 前表面使用线条绘制
 return TRUE;                                        // 初始化 OK
}

int DrawGLScene(GLvoid)                                    // 从这里开始进行所有的绘制
 {
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // 清除屏幕和深度缓存

 glLoadIdentity();

 glTranslatef(0,0,-6.0);

 static float rz=0.0;
 glRotatef(rz,0.0,1.0,0.0);//旋转显示
 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);

 glEnable(GL_TEXTURE_GEN_S);                // 使用自动生成纹理
 glEnable(GL_TEXTURE_GEN_T);   

 /**///字体显示的各种方法///
 //图像文字效果
 glPushMatrix();
 glDisable(GL_TEXTURE_2D);
 glDisable(GL_LIGHTING);
 f.SetTextColor(RGB(255,255,0));
 f.ShowText(100,100,"我爱OpenGL!");
 glEnable(GL_LIGHTING);
 glEnable(GL_TEXTURE_2D);
 glPopMatrix();

 //带材质的2D文字效果
 glPushMatrix();
 glDisable(GL_TEXTURE_2D);
 glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
 glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
 glTranslatef(-3,1.5,0);
 glRotatef(30,1,1,0);
 f.Show2DText("我爱OpenGL!");
 glEnable(GL_TEXTURE_2D);
 glPopMatrix();

 //带纹理的3D文字效果
 glPushMatrix();
 //glDisable(GL_TEXTURE_2D);
 //glDisable(GL_LIGHTING);
 glTranslatef(-3,0.5,0);
 glRotatef(30,1,1,0);
 f.SetTextColor(RGB(255,0,0));
 f.Show3DText((unsigned char*)"我爱OpenGL!");
 //glEnable(GL_LIGHTING);
 //glEnable(GL_TEXTURE_2D);
 glPopMatrix();

 //超酷的金属质感纹理效果
 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
 glPushMatrix();
 //glDisable(GL_TEXTURE_2D);
 //glDisable(GL_LIGHTING);
 glTranslatef(-3,-0.5,0);
 glRotatef(30,1,1,0);
 f.SetTextColor(RGB(255,0,0));
 f.Show3DText((unsigned char*)"我爱OpenGL!");
 //glEnable(GL_LIGHTING);
 //glEnable(GL_TEXTURE_2D);
 glPopMatrix();

 rz+=1.0;
 //Sleep(20);
 return TRUE;                                        // 一切 OK
}

GLvoid KillGLWindow(GLvoid)                                // 正常销毁窗口
 {
 if (fullscreen)                                        // 我们处于全屏模式吗?
   {
   ChangeDisplaySettings(NULL,0);                    // 是的话,切换回桌面
   ShowCursor(TRUE);                                // 显示鼠标指针
 }

 if(hRC)                                            //我们拥有OpenGL描述表吗?
   {
   if(!wglMakeCurrent(NULL,NULL))                    // 我们能否释放DC和RC描述表?
     {
     MessageBox(NULL,"释放DC或RC失败。","关闭错误",MB_OK | MB_ICONINFORMATION);
   }

   if(!wglDeleteContext(hRC))                        // 我们能否删除RC?
     {
     MessageBox(NULL,"释放RC失败。","关闭错误",MB_OK | MB_ICONINFORMATION);
   }
   hRC=NULL;                                        // 将RC设为 NULL
 }

 if(hDC&&!ReleaseDC(hWnd,hDC))                    // 我们能否释放 DC?
   {
   MessageBox(NULL,"释放DC失败。","关闭错误",MB_OK | MB_ICONINFORMATION);
   hDC=NULL;                                        // 将 DC 设为 NULL
 }

 if(hWnd && !DestroyWindow(hWnd))                    // 能否销毁窗口?
   {
   MessageBox(NULL,"释放窗口句柄失败。","关闭错误",MB_OK | MB_ICONINFORMATION);
   hWnd=NULL;                                        // 将 hWnd 设为 NULL
 }

 if (!UnregisterClass("OpenG",hInstance))            // 能否注销类?
   {
   MessageBox(NULL,"不能注销窗口类。","关闭错误",MB_OK | MB_ICONINFORMATION);
   hInstance=NULL;                                    // 将 hInstance 设为 NULL
 }
}

/**//*    这个函数创建我们OpenGL窗口,参数为:                                    *
 *    title            - 窗口标题                                                *
 *    width            - 窗口宽度                                                *
 *    height            - 窗口高度                                                *
 *    bits            - 颜色的位深(8/16/32)                                    *
 *    fullscreenflag    - 是否使用全屏模式,全屏模式(TRUE),窗口模式(FALSE)        */

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
 {
 GLuint        PixelFormat;            // 保存查找匹配的结果
 WNDCLASS    wc;                        // 窗口类结构
 DWORD        dwExStyle;                // 扩展窗口风格
 DWORD        dwStyle;                // 窗口风格
 RECT        WindowRect;                // 取得矩形的左上角和右下角的坐标值
 WindowRect.left=(long)0;            // 将Left   设为 0
 WindowRect.right=(long)width;        // 将Right  设为要求的宽度
 WindowRect.top=(long)0;                // 将Top    设为 0
 WindowRect.bottom=(long)height;        // 将Bottom 设为要求的高度

 fullscreen=fullscreenflag;            // 设置全局全屏标志

 hInstance            = GetModuleHandle(NULL);                // 取得我们窗口的实例
 wc.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;    // 移动时重画,并为窗口取得DC
 wc.lpfnWndProc        = (WNDPROC) WndProc;                    // WndProc处理消息
 wc.cbClsExtra        = 0;                                    // 无额外窗口数据
 wc.cbWndExtra        = 0;                                    // 无额外窗口数据
 wc.hInstance        = hInstance;                            // 设置实例
 wc.hIcon            = LoadIcon(NULL, IDI_WINLOGO);            // 装入缺省图标
 wc.hCursor            = LoadCursor(NULL, IDC_ARROW);            // 装入鼠标指针
 wc.hbrBackground    = NULL;                                    // GL不需要背景
 wc.lpszMenuName        = NULL;                                    // 不需要菜单
 wc.lpszClassName    = "OpenG";                                // 设定类名字

 if (!RegisterClass(&wc))                                    // 尝试注册窗口类
   {
   MessageBox(NULL,"注册窗口失败","错误",MB_OK|MB_ICONEXCLAMATION);
   return FALSE;                                    // 退出并返回FALSE
 }

 if (fullscreen)                                            // 要尝试全屏模式吗?
   {
   DEVMODE dmScreenSettings;                                // 设备模式
   memset(&dmScreenSettings,0,sizeof(dmScreenSettings));    // 确保内存清空为零
   dmScreenSettings.dmSize=sizeof(dmScreenSettings);        // Devmode 结构的大小
   dmScreenSettings.dmPelsWidth    = width;                // 所选屏幕宽度
   dmScreenSettings.dmPelsHeight    = height;                // 所选屏幕高度
   dmScreenSettings.dmBitsPerPel    = bits;                    // 每象素所选的色彩深度
   dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

   // 尝试设置显示模式并返回结果。注: CDS_FULLSCREEN 移去了状态条
   if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
     {
     // 若模式失败,提供两个选项:退出或在窗口内运行。
     if (MessageBox(NULL,"全屏模式在当前显卡上设置失败!使用窗口模式?","NeHe G",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
       {
       //如果用户选择窗口模式,变量fullscreen 的值变为FALSE,程序继续运行
       fullscreen=FALSE;        // 选择窗口模式(Fullscreen=FALSE)
     }
     else
       {
       //如果用户选择退出,弹出消息窗口告知用户程序将结束。并返回FALSE告诉程序窗口未能成功创建。程序退出。
       MessageBox(NULL,"程序将被关闭","错误",MB_OK|MB_ICONSTOP);
       return FALSE;                                    // 退出并返回 FALSE
     }
   }
 }

 if (fullscreen)                                                // 仍处于全屏模式吗?
   {
   dwExStyle=WS_EX_APPWINDOW;                                // 扩展窗体风格
   dwStyle=WS_POPUP;                                        // 窗体风格
   ShowCursor(FALSE);                                        // 隐藏鼠标指针
 }
 else
   {
   dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;            // 扩展窗体风格
   dwStyle=WS_OVERLAPPEDWINDOW;                            // 窗体风格
 }

 AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);        // 调整窗口达到真正要求的大小

 // 创建窗口
 if (!(hWnd=CreateWindowEx(    dwExStyle,                            // 扩展窗体风格
  "OpenG",                            // 类名字
  title,                                // 窗口标题
  dwStyle |                            // 必须的窗体风格属性
  WS_CLIPSIBLINGS |                    // 必须的窗体风格属性
  WS_CLIPCHILDREN,                    // 必须的窗体风格属性
  0, 0,                                // 窗口位置
  WindowRect.right-WindowRect.left,    // 计算调整好的窗口宽度
  WindowRect.bottom-WindowRect.top,    // 计算调整好的窗口高度
  NULL,                                // 无父窗口
  NULL,                                // 无菜单
  hInstance,                            // 实例
  NULL)))                                // 不向WM_CREATE传递任何东东
   {
   KillGLWindow();                                // 重置显示区
   MessageBox(NULL,"窗口创建错误","错误",MB_OK|MB_ICONEXCLAMATION);
   return FALSE;                                // 返回 FALSE
 }

 static    PIXELFORMATDESCRIPTOR pfd=                //pfd 告诉窗口我们所希望的东东,即窗口使用的像素格式
   {
   sizeof(PIXELFORMATDESCRIPTOR),                // 上述格式描述符的大小
    1,                                            // 版本号
    PFD_DRAW_TO_WINDOW |                        // 格式支持窗口
    PFD_SUPPORT_OPENGL |                        // 格式必须支持OpenGL
    PFD_DOUBLEBUFFER,                            // 必须支持双缓冲
    PFD_TYPE_RGBA,                                // 申请 RGBA 格式
    bits,                                        // 选定色彩深度
    0, 0, 0, 0, 0, 0,                            // 忽略的色彩位
    0,                                            // 无Alpha缓存
    0,                                            // 忽略Shift Bit
    0,                                            // 无累加缓存
    0, 0, 0, 0,                                    // 忽略聚集位
    16,                                            // 16位 Z-缓存 (深度缓存)
    0,                                            // 无蒙板缓存
    0,                                            // 无辅助缓存
    PFD_MAIN_PLANE,                                // 主绘图层
    0,                                            // 不使用重叠层
    0, 0, 0                                        // 忽略层遮罩
 };

 if (!(hDC=GetDC(hWnd)))                            // 取得设备描述表了么?
   {
   KillGLWindow();                                // 重置显示区
   MessageBox(NULL,"不能创建一个窗口设备描述表","错误",MB_OK|MB_ICONEXCLAMATION);
   return FALSE;                                // 返回 FALSE
 }

 if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))    // Windows 找到相应的象素格式了吗?
   {
   KillGLWindow();                                // 重置显示区
   MessageBox(NULL,"不能创建一种相匹配的像素格式","错误",MB_OK|MB_ICONEXCLAMATION);
   return FALSE;                                // 返回 FALSE
 }

 if(!SetPixelFormat(hDC,PixelFormat,&pfd))        // 能够设置象素格式么?
   {
   KillGLWindow();                                // 重置显示区
   MessageBox(NULL,"不能设置像素格式","错误",MB_OK|MB_ICONEXCLAMATION);
   return FALSE;                                // 返回 FALSE
 }

 if (!(hRC=wglCreateContext(hDC)))                // 能否取得OpenGL渲染描述表?
   {
   KillGLWindow();                                // 重置显示区
   MessageBox(NULL,"不能创建OpenGL渲染描述表","错误",MB_OK|MB_ICONEXCLAMATION);
   return FALSE;                                // 返回 FALSE
 }

 if(!wglMakeCurrent(hDC,hRC))                    // 尝试激活着色描述表
   {
   KillGLWindow();                                // 重置显示区
   MessageBox(NULL,"不能激活当前的OpenGL渲然描述表","错误",MB_OK|MB_ICONEXCLAMATION);
   return FALSE;                                // 返回 FALSE
 }

 ShowWindow(hWnd,SW_SHOW);                        // 显示窗口
 SetForegroundWindow(hWnd);                        // 略略提高优先级
 SetFocus(hWnd);                                    // 设置键盘的焦点至此窗口
 ReSizeGLScene(width, height);                    // 设置透视 GL 屏幕

 if (!InitGL())                                    // 初始化新建的GL窗口
   {
   KillGLWindow();                                // 重置显示区
   MessageBox(NULL,"初始化失败","错误",MB_OK|MB_ICONEXCLAMATION);
   return FALSE;                                // 返回 FALSE
 }

 return TRUE;                                    // 成功
}

LRESULT CALLBACK WndProc(    HWND    hWnd,            // 窗口的句柄   
       UINT    uMsg,            // 窗口的消息
       WPARAM    wParam,            // 附加的消息内容
       LPARAM    lParam)            // 附加的消息内容
        {
        switch (uMsg)                                    // 检查Windows消息
          {
  case WM_ACTIVATE:                            // 监视窗口激活消息
    {
    if (!HIWORD(wParam))                    // 检查最小化状态
      {
      active=TRUE;                        // 程序处于激活状态
    }
    else
      {
      active=FALSE;                        // 程序不再激活
    }

    return 0;                                // 返回消息循环
   }

  case WM_SYSCOMMAND:                            // 系统中断命令
    {
    switch (wParam)                            // 检查系统调用
      {
  case SC_SCREENSAVE:                    // 屏保要运行?
  case SC_MONITORPOWER:                // 显示器要进入节电模式?
   return 0;                            // 阻止发生
    }
    break;                                    // 退出
   }

  case WM_CLOSE:                                // 收到Close消息?
    {
    PostQuitMessage(0);                        // 发出退出消息
    return 0;                                // 返回
   }

  case WM_KEYDOWN:                            // 有键按下么?
    {
    keys[wParam] = TRUE;                    // 如果是,设为TRUE
    return 0;                                // 返回
   }

  case WM_KEYUP:                                // 有键放开么?
    {
    keys[wParam] = FALSE;                    // 如果是,设为FALSE
    return 0;                                // 返回
   }

  case WM_SIZE:                                // 调整OpenGL窗口大小
    {
    ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));  // LoWord=Width,HiWord=Height
    return 0;                                // 返回
   }
        }

        // 向 DefWindowProc传递所有未处理的消息。
        return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

int WINAPI WinMain(HINSTANCE    hInstance,            // 当前窗口实例
       HINSTANCE    hPrevInstance,        // 前一个窗口实例
       LPSTR        lpCmdLine,            // 命令行参数
       int            nCmdShow)            // 窗口显示状态
        {
        MSG        msg;                                    // Windowsx消息结构
        BOOL    done=FALSE;                                // 用来退出循环的Bool 变量

        // 提示用户选择运行模式
        if (MessageBox(NULL,"你想在全屏模式下运行么?", "设置全屏模式",MB_YESNO|MB_ICONQUESTION)==IDNO)
          {
          fullscreen=FALSE;                            // FALSE为窗口模式
        }

        // 创建OpenGL窗口
        if (!CreateGLWindow("NeHe's OpenGL 程序框架",640,480,16,fullscreen))
          {
          return 0;                                    // 失败退出
        }

        while(!done)                                    // 保持循环直到 done=TRUE
          {
          if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))    // 有消息在等待吗?
            {
            if (msg.message==WM_QUIT)                // 收到退出消息?
              {
              done=TRUE;                            // 是,则done=TRUE
            }
            else                                    // 不是,处理窗口消息
              {
              TranslateMessage(&msg);                // 翻译消息
              DispatchMessage(&msg);                // 发送消息
            }
          }
          else                                        // 如果没有消息
            {
            // 绘制场景。监视ESC键和来自DrawGLScene()的退出消息
            if (active)                                // 程序激活的么?
              {
              if (keys[VK_ESCAPE])                // ESC 按下了么?
                {
                done=TRUE;                        // ESC 发出退出信号
              }
              else                                // 不是退出的时候,刷新屏幕
                {
                DrawGLScene();                    // 绘制场景
                SwapBuffers(hDC);                // 交换缓存 (双缓存)
                if (keys['L'] && !lp)                // L 键已按下并且松开了?
                  {
                  lp=TRUE;                // lp 设为 TRUE
                  light=!light;                // 切换光源的 TRUE/FALSE
                  if (!light)                // 如果没有光源
                    {
                    glDisable(GL_LIGHTING);        // 禁用光源
                  }
                  else                    // 否则
                    {
                    glEnable(GL_LIGHTING);        // 启用光源
                  }
                }
                if (!keys['L'])                    // L键松开了么?
                  {
                  lp=FALSE;                // 若是,则将lp设为FALSE
                }
              }
            }

            if (keys[VK_F1])                        // F1键按下了么?
              {
              keys[VK_F1]=FALSE;                    // 若是,使对应的Key数组中的值为 FALSE
              KillGLWindow();                        // 销毁当前的窗口
              fullscreen=!fullscreen;                // 切换 全屏 / 窗口 模式
              // 重建 OpenGL 窗口
              if (!CreateGLWindow("NeHe's OpenGL 程序框架",640,480,16,fullscreen))
                {
                return 0;                // 如果窗口未能创建,程序退出
              }
            }
          }
        }

        // 关闭程序
        KillGLWindow();                                    // 销毁窗口
        return (msg.wParam);                            // 退出程序
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值