OpenGL---GLUT教程(九) GLUT鼠标/OpenGL(Win32 窗体应用程序框架)


          GLUT
教程
              鼠标
在前几节,我们看了怎么使用GLUT的keyboard函数,来增加一个OpenGL程序的交互性。现在,是时候研究下鼠标了。GLUT的鼠标接口提供一些列的选项来增加鼠标的交互性。也就是检测鼠标单击,和鼠标移动。
 
检测鼠标Clicks
和键盘处理一样,GLUT为你的注册函数(也就是处理鼠标clicks事件的函数)提供了一个方法。函数glutMouseFunc,这个函数一般在程序初始化阶段被调用。函数原型如下:
void glutMouseFunc(void(*func)(int button,int state,int x,int y));
参数:
func:处理鼠标click事件的函数的函数名。
从上面可以看到到,处理鼠标click事件的函数,一定有4个参数。第一个参数表明哪个鼠标键被按下或松开,这个变量可以是下面的三个值中的一个:
GLUT_LEFT_BUTTON
GLUT_MIDDLE_BUTTON
GLUT_RIGHT_BUTTON
第二个参数表明,函数被调用发生时,鼠标的状态,也就是是被按下,或松开,可能取值如下:
GLUT_DOWN
GLUT_UP
当函数被调用时,state的值是GLUT_DOWN,那么程序可能会假定将会有个GLUT_UP事件,甚至鼠标移动到窗口外面,也如此。然而,如果程序调用glutMouseFunc传递NULL作为参数,那么GLUT将不会改变鼠标的状态。
 
剩下的两个参数(x,y)提供了鼠标当前的窗口坐标(以左上角为原点)。
 
检测动作(motion)
GLUT提供鼠标motion检测能力。有两种GLUT处理的motion:active motion和passive motion。Active motion是指鼠标移动并且有一个鼠标键被按下。Passive motion是指当鼠标移动时,并有没鼠标键按下。如果一个程序正在追踪鼠标,那么鼠标移动期间,没一帧将产生一个结果。
 
和以前一样,你必须注册将处理鼠标事件的函数(定义函数)。GLUT让我们可以指定两个不同的函数,一个追踪passive motion,另一个追踪active motion
 
它们的函数原型,如下:
void glutMotionFunc(void(*func)(int x,int y));
void glutPassiveMotionFunc(void (*func)(int x,int y));
参数:
Func:处理各自类型motion的函数名。
处理motion的参数函数的参数(x,y)是鼠标在窗口的坐标。以左上角为原点。
 
检测鼠标进入或离开窗口
GLUT还能检测鼠标鼠标离开,进入窗口区域。一个回调函数可以被定义去处理这两个事件。GLUT里,调用这个函数的是glutEntryFunc,函数原型如下:
void glutEntryFunc(void(*func)(int state));
参数:
Func:处理这些事件的函数名。
上面函数的参数中,state有两个值:
GLUT_LEFT
GLUT_ENTERED
表明,是离开,还是进入窗口。
 
把它们放一起
首先我们要做的是在GLUT里定义哪些函数将负责处理鼠标事件。因此我们将重写我们的main函数,让它包含所有必须的回调注册函数。我们将在程序里描述其他一些教程里没说清楚的地方。
void main(int argc, char **argv) {
         glutInit(&argc, argv);
         glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
         glutInitWindowPosition(100,100);
         glutInitWindowSize(320,320);
         glutCreateWindow("SnowMen");
         glutDisplayFunc(renderScene);
         glutIdleFunc(renderScene);
         glutReshapeFunc(changeSize);
 
         //adding here the mouse processing callbacks
         glutMouseFunc(processMouse);
         glutMotionFunc(processMouseActiveMotion);
         glutPassiveMotionFunc(processMousePassiveMotion);
         glutEntryFunc(processMouseEntry);
         
         glutMainLoop();
}
OK,现在做点有趣的。我们将定义那些将做一些不可思议事件的回调函数。当一个鼠标键和alt键都被按下,我们将改变三角形的颜色。鼠标左键使三角形变成红色,中间的将三角形变成绿色,鼠标右键将三角形变成蓝色。函数如下:
void processMouse(int button, int state, int x, int y) {
 
 
         specialKey = glutGetModifiers();
         // 当鼠标键和alt键都被按下
         if ((state == GLUT_DOWN) && 
                          (specialKey == GLUT_ACTIVE_ALT)) {
 
                 // set the color to pure red for the left button
                 if (button == GLUT_LEFT_BUTTON) {
                          red = 1.0; green = 0.0; blue = 0.0;
                 }
                 // set the color to pure green for the middle button
                 else if (button == GLUT_MIDDLE_BUTTON) {
                          red = 0.0; green = 1.0; blue = 0.0;
                 }
                 // set the color to pure blue for the right button
                 else {
                          red = 0.0; green = 0.0; blue = 1.0;
                 }
         }
}
接下来有一个精细的颜色拾取方法。当一个鼠标键被按下,但alt键被被按下。我们把blue设为0.0,并且让red和green分量的值取决于鼠标在窗口中的位置。。函数如下:
void processMouseActiveMotion(int x, int y) {
 
         // the ALT key was used in the previous function
         if (specialKey != GLUT_ACTIVE_ALT) {
                 // setting red to be relative to the mouse 
                 // position inside the window
                 if (x < 0)
                          red = 0.0;
                 else if (x > width)
                          red = 1.0;
                 else
                          red = ((float) x)/height;
                 // setting green to be relative to the mouse 
                 // position inside the window
                 if (y < 0)
                          green = 0.0;
                 else if (y > width)
                          green = 1.0;
                 else
                          green = ((float) y)/height;
                 // removing the blue component.
                 blue = 0.0;
         }
}
下面给passive motion添加一些动作。当shift键被按下,鼠标将在x轴上有一个旋转。我们不得不修改renderScene函数。函数如下:
float angleX = 0.0;
...
void renderScene(void) {
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         glPushMatrix();
         glRotatef(angle,0.0,1.0,0.0);
         
         // This is the line we added for the
         // rotation on the X axis;
         glRotatef(angleX,1.0,0.0,0.0);
         
         glColor3f(red,green,blue);
 
         glBegin(GL_TRIANGLES);
                 glVertex3f(-0.5,-0.5,0.0);
                 glVertex3f(0.5,0.0,0.0);
                 glVertex3f(0.0,0.5,0.0);
         glEnd();
         glPopMatrix();
         angle++;
         glutSwapBuffers();
}
现在我们的有个函数处理passive motion事件。函数将改变angleX的值。
void processMousePassiveMotion(int x, int y) {
 
         // User must press the SHIFT key to change the 
         // rotation in the X axis
         if (specialKey != GLUT_ACTIVE_SHIFT) {
 
                 // setting the angle to be relative to the mouse 
                 // position inside the window
                 if (x < 0)
                          angleX = 0.0;
                 else if (x > width)
                          angleX = 180.0;
                 else
                          angleX = 180.0 * ((float) x)/height;
         }
}
最后鼠标离开窗口将使动画停止,为了做到这,我们也需要改变函数renderScene。
// initially define the increase of the angle by 1.0;
float deltaAngle = 1.0;
...
void renderScene(void) {
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         glPushMatrix();
         glRotatef(angle,0.0,1.0,0.0);
         glRotatef(angleX,1.0,0.0,0.0);
         glColor3f(red,green,blue);
 
         glBegin(GL_TRIANGLES);
                 glVertex3f(-0.5,-0.5,0.0);
                 glVertex3f(0.5,0.0,0.0);
                 glVertex3f(0.0,0.5,0.0);
         glEnd();
         glPopMatrix();
         // this is the new line
         // previously it was: angle++;
         angle+=deltaAngle;
         glutSwapBuffers();
}
processMouseEntry是最后一个函数。注意,这个在微软操作系统下可能工作的不是很好。
void processMouseEntry(int state) {
         if (state == GLUT_LEFT)
                 deltaAngle = 0.0;
         else
                 deltaAngle = 1.0;
}
VC6.0工程可以在这里下载(glut8.zip)。
 
(到这里位置,键盘,鼠标方面的控制讲完了,下面就是菜单了。)
(原文地址:http://www.lighthouse3d.com/opengl/glut/index.php?9
 

VS2008为例,下面是“核心步骤”截图:

Step 1:

Step 2:

Step 3:

将“Lesson01.cpp”加到当前工程中,Lesson01.cpp内容如下:

 

/*
  *        This Code Was Created By Jeff Molofee 2000
  *        A HUGE Thanks To Fredric Echols For Cleaning Up
  *        And Optimizing This Code, Making It More Flexible!
  *        If You've Found This Code Useful, Please Let Me Know.
  *        Visit My Site At nehe.gamedev.net
  */
 
 #include <windows.h>        // Header File For Windows
  #include <gl\gl.h>            // Header File For The OpenGL32 Library
  #include <gl\glu.h>            // Header File For The GLu32 Library
  #include <gl\glaux.h>        // Header File For The Glaux Library
  
  #pragma comment( lib, "opengl32.lib" )
  #pragma comment( lib, "glu32.lib" )
  #pragma comment( lib, "glaux.lib" )
 
 HDC            hDC=NULL;        // Private GDI Device Context
  HGLRC        hRC=NULL;        // Permanent Rendering Context
  HWND        hWnd=NULL;        // Holds Our Window Handle
  HINSTANCE    hInstance;        // Holds The Instance Of The Application
  
  bool    keys[256];            // Array Used For The Keyboard Routine
  bool    active=TRUE;        // Window Active Flag Set To TRUE By Default
  bool    fullscreen=TRUE;    // Fullscreen Flag Set To Fullscreen Mode By Default
  
 LRESULT    CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);    // Declaration For WndProc
  
 GLvoid ReSizeGLScene(GLsizei width, GLsizei height)        // Resize And Initialize The GL Window
  {
     if (height==0)                                        // Prevent A Divide By Zero By
      {
         height=1;                                        // Making Height Equal One
      }
 
     glViewport(0,0,width,height);                        // Reset The Current Viewport
  
     glMatrixMode(GL_PROJECTION);                        // Select The Projection Matrix
      glLoadIdentity();                                    // Reset The Projection Matrix
 
     // Calculate The Aspect Ratio Of The Window
      gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
 
     glMatrixMode(GL_MODELVIEW);                            // Select The Modelview Matrix
      glLoadIdentity();                                    // Reset The Modelview Matrix
 }
 
 int InitGL(GLvoid)                                        // All Setup For OpenGL Goes Here
 {
     glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
     glClearColor(0.0f, 0.0f, 0.0f, 0.5f);                // Black Background
     glClearDepth(1.0f);                                    // Depth Buffer Setup
     glEnable(GL_DEPTH_TEST);                            // Enables Depth Testing
     glDepthFunc(GL_LEQUAL);                                // The Type Of Depth Testing To Do
     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    // Really Nice Perspective Calculations
     return TRUE;                                        // Initialization Went OK
 }
 
 int DrawGLScene(GLvoid)                                    // Here's Where We Do All The Drawing
 {
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // Clear Screen And Depth Buffer
     glLoadIdentity();                                    // Reset The Current Modelview Matrix
     return TRUE;                                        // Everything Went OK
 }
 
 GLvoid KillGLWindow(GLvoid)                                // Properly Kill The Window
 {
     if (fullscreen)                                        // Are We In Fullscreen Mode?
     {
         ChangeDisplaySettings(NULL,0);                    // If So Switch Back To The Desktop
         ShowCursor(TRUE);                                // Show Mouse Pointer
     }
 
     if (hRC)                                            // Do We Have A Rendering Context?
     {
         if (!wglMakeCurrent(NULL,NULL))                    // Are We Able To Release The DC And RC Contexts?
         {
             MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
         }
 
         if (!wglDeleteContext(hRC))                        // Are We Able To Delete The RC?
         {
             MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
         }
         hRC=NULL;                                        // Set RC To NULL
     }
 
     if (hDC && !ReleaseDC(hWnd,hDC))                    // Are We Able To Release The DC
     {
         MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
         hDC=NULL;                                        // Set DC To NULL
     }
 
     if (hWnd && !DestroyWindow(hWnd))                    // Are We Able To Destroy The Window?
     {
         MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
         hWnd=NULL;                                        // Set hWnd To NULL
     }
 
     if (!UnregisterClass("OpenGL",hInstance))            // Are We Able To Unregister Class
     {
         MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
         hInstance=NULL;                                    // Set hInstance To NULL
     }
 }
 
 /*    This Code Creates Our OpenGL Window.  Parameters Are:                    *
  *    title            - Title To Appear At The Top Of The Window                *
  *    width            - Width Of The GL Window Or Fullscreen Mode                *
  *    height            - Height Of The GL Window Or Fullscreen Mode            *
  *    bits            - Number Of Bits To Use For Color (8/16/24/32)            *
  *    fullscreenflag    - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE)    */
  
 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
 {
     GLuint        PixelFormat;            // Holds The Results After Searching For A Match
     WNDCLASS    wc;                        // Windows Class Structure
     DWORD        dwExStyle;                // Window Extended Style
     DWORD        dwStyle;                // Window Style
     RECT        WindowRect;                // Grabs Rectangle Upper Left / Lower Right Values
     WindowRect.left=(long)0;            // Set Left Value To 0
     WindowRect.right=(long)width;        // Set Right Value To Requested Width
     WindowRect.top=(long)0;                // Set Top Value To 0
     WindowRect.bottom=(long)height;        // Set Bottom Value To Requested Height
 
     fullscreen=fullscreenflag;            // Set The Global Fullscreen Flag
 
     hInstance            = GetModuleHandle(NULL);                // Grab An Instance For Our Window
     wc.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;    // Redraw On Size, And Own DC For Window.
     wc.lpfnWndProc        = (WNDPROC) WndProc;                    // WndProc Handles Messages
     wc.cbClsExtra        = 0;                                    // No Extra Window Data
     wc.cbWndExtra        = 0;                                    // No Extra Window Data
     wc.hInstance        = hInstance;                            // Set The Instance
     wc.hIcon            = LoadIcon(NULL, IDI_WINLOGO);            // Load The Default Icon
     wc.hCursor            = LoadCursor(NULL, IDC_ARROW);            // Load The Arrow Pointer
     wc.hbrBackground    = NULL;                                    // No Background Required For GL
     wc.lpszMenuName        = NULL;                                    // We Don't Want A Menu
     wc.lpszClassName    = "OpenGL";                                // Set The Class Name
 
     if (!RegisterClass(&wc))                                    // Attempt To Register The Window Class
     {
         MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
         return FALSE;                                            // Return FALSE
     }
     
     if (fullscreen)                                                // Attempt Fullscreen Mode?
     {
         DEVMODE dmScreenSettings;                                // Device Mode
         memset(&dmScreenSettings,0,sizeof(dmScreenSettings));    // Makes Sure Memory's Cleared
         dmScreenSettings.dmSize=sizeof(dmScreenSettings);        // Size Of The Devmode Structure
         dmScreenSettings.dmPelsWidth    = width;                // Selected Screen Width
         dmScreenSettings.dmPelsHeight    = height;                // Selected Screen Height
         dmScreenSettings.dmBitsPerPel    = bits;                    // Selected Bits Per Pixel
         dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
 
         // Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
         if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
         {
             // If The Mode Fails, Offer Two Options.  Quit Or Use Windowed Mode.
             if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card.\               Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)162             {
                 fullscreen=FALSE;        // Windowed Mode Selected.  Fullscreen = FALSE
             }
             else
             {
                 // Pop Up A Message Box Letting User Know The Program Is Closing.
                 MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
                 return FALSE;                                    // Return FALSE
             }
         }
     }
 
     if (fullscreen)                                                // Are We Still In Fullscreen Mode?
     {
         dwExStyle=WS_EX_APPWINDOW;                                // Window Extended Style
         dwStyle=WS_POPUP;                                        // Windows Style
         ShowCursor(FALSE);                                        // Hide Mouse Pointer
     }
     else
     {
         dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;            // Window Extended Style
         dwStyle=WS_OVERLAPPEDWINDOW;                            // Windows Style
     }
 
     AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);        // Adjust Window To True Requested Size
 
     // Create The Window
     if (!(hWnd=CreateWindowEx(    dwExStyle,                            // Extended Style For The Window
                                 "OpenGL",                            // Class Name
                                 title,                                // Window Title
                                 dwStyle |                            // Defined Window Style
                                 WS_CLIPSIBLINGS |                    // Required Window Style
                                 WS_CLIPCHILDREN,                    // Required Window Style
                                 0, 0,                                // Window Position
                                 WindowRect.right-WindowRect.left,    // Calculate Window Width
                                 WindowRect.bottom-WindowRect.top,    // Calculate Window Height
                                 NULL,                                // No Parent Window
                                 NULL,                                // No Menu
                                 hInstance,                            // Instance
                                 NULL)))                                // Dont Pass Anything To WM_CREATE
     {
         KillGLWindow();                                // Reset The Display
         MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
         return FALSE;                                // Return FALSE
     }
 
     static    PIXELFORMATDESCRIPTOR pfd=                // pfd Tells Windows How We Want Things To Be
     {
         sizeof(PIXELFORMATDESCRIPTOR),                // Size Of This Pixel Format Descriptor
         1,                                            // Version Number
         PFD_DRAW_TO_WINDOW |                        // Format Must Support Window
         PFD_SUPPORT_OPENGL |                        // Format Must Support OpenGL
         PFD_DOUBLEBUFFER,                            // Must Support Double Buffering
         PFD_TYPE_RGBA,                                // Request An RGBA Format
         bits,                                        // Select Our Color Depth
         0, 0, 0, 0, 0, 0,                            // Color Bits Ignored
         0,                                            // No Alpha Buffer
         0,                                            // Shift Bit Ignored
         0,                                            // No Accumulation Buffer
         0, 0, 0, 0,                                    // Accumulation Bits Ignored
         16,                                            // 16Bit Z-Buffer (Depth Buffer)  
         0,                                            // No Stencil Buffer
         0,                                            // No Auxiliary Buffer
         PFD_MAIN_PLANE,                                // Main Drawing Layer
         0,                                            // Reserved
         0, 0, 0                                        // Layer Masks Ignored
     };
     
     if (!(hDC=GetDC(hWnd)))                            // Did We Get A Device Context?
     {
         KillGLWindow();                                // Reset The Display
         MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
         return FALSE;                                // Return FALSE
     }
 
     if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))    // Did Windows Find A Matching Pixel Format?
     {
         KillGLWindow();                                // Reset The Display
         MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
         return FALSE;                                // Return FALSE
     }
 
     if(!SetPixelFormat(hDC,PixelFormat,&pfd))        // Are We Able To Set The Pixel Format?
     {
         KillGLWindow();                                // Reset The Display
         MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
         return FALSE;                                // Return FALSE
     }
 
     if (!(hRC=wglCreateContext(hDC)))                // Are We Able To Get A Rendering Context?
     {
         KillGLWindow();                                // Reset The Display
         MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
         return FALSE;                                // Return FALSE
     }
 
     if(!wglMakeCurrent(hDC,hRC))                    // Try To Activate The Rendering Context
     {
         KillGLWindow();                                // Reset The Display
         MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
         return FALSE;                                // Return FALSE
     }
 
     ShowWindow(hWnd,SW_SHOW);                        // Show The Window
     SetForegroundWindow(hWnd);                        // Slightly Higher Priority
     SetFocus(hWnd);                                    // Sets Keyboard Focus To The Window
     ReSizeGLScene(width, height);                    // Set Up Our Perspective GL Screen
 
     if (!InitGL())                                    // Initialize Our Newly Created GL Window
     {
         KillGLWindow();                                // Reset The Display
         MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
         return FALSE;                                // Return FALSE
     }
 
     return TRUE;                                    // Success
 }
 
 LRESULT CALLBACK WndProc(    HWND    hWnd,            // Handle For This Window
                             UINT    uMsg,            // Message For This Window
                             WPARAM    wParam,            // Additional Message Information
                             LPARAM    lParam)            // Additional Message Information
 {
     switch (uMsg)                                    // Check For Windows Messages
     {
         case WM_ACTIVATE:                            // Watch For Window Activate Message
         {
             if (!HIWORD(wParam))                    // Check Minimization State
             {
                 active=TRUE;                        // Program Is Active
             }
             else
             {
                 active=FALSE;                        // Program Is No Longer Active
             }
 
             return 0;                                // Return To The Message Loop
         }
 
         case WM_SYSCOMMAND:                            // Intercept System Commands
         {
             switch (wParam)                            // Check System Calls
             {
                 case SC_SCREENSAVE:                    // Screensaver Trying To Start?
                 case SC_MONITORPOWER:                // Monitor Trying To Enter Powersave?
                 return 0;                            // Prevent From Happening
             }
             break;                                    // Exit
         }
 
         case WM_CLOSE:                                // Did We Receive A Close Message?
         {
             PostQuitMessage(0);                        // Send A Quit Message
             return 0;                                // Jump Back
         }
 
         case WM_KEYDOWN:                            // Is A Key Being Held Down?
         {
             keys[wParam] = TRUE;                    // If So, Mark It As TRUE
             return 0;                                // Jump Back
         }
 
         case WM_KEYUP:                                // Has A Key Been Released?
         {
             keys[wParam] = FALSE;                    // If So, Mark It As FALSE
             return 0;                                // Jump Back
         }
 
         case WM_SIZE:                                // Resize The OpenGL Window
         {
             ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));  // LoWord=Width, HiWord=Height
             return 0;                                // Jump Back
         }
     }
 
     // Pass All Unhandled Messages To DefWindowProc
     return DefWindowProc(hWnd,uMsg,wParam,lParam);
 }
 
 int WINAPI WinMain(    HINSTANCE    hInstance,            // Instance
                     HINSTANCE    hPrevInstance,        // Previous Instance
                     LPSTR        lpCmdLine,            // Command Line Parameters
                     int            nCmdShow)            // Window Show State
 {
     MSG        msg;                                    // Windows Message Structure
     BOOL    done=FALSE;                                // Bool Variable To Exit Loop
 
     // Ask The User Which Screen Mode They Prefer
     if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",      MB_YESNO|MB_ICONQUESTION)==IDNO)
     {
         fullscreen=FALSE;                            // Windowed Mode
     }
 
     // Create Our OpenGL Window
     if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
     {
         return 0;                                    // Quit If Window Was Not Created
     }
 
     while(!done)                                    // Loop That Runs While done=FALSE
     {
         if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))    // Is There A Message Waiting?
         {
             if (msg.message==WM_QUIT)                // Have We Received A Quit Message?
             {
                 done=TRUE;                            // If So done=TRUE
             }
             else                                    // If Not, Deal With Window Messages
             {
                 TranslateMessage(&msg);                // Translate The Message
                 DispatchMessage(&msg);                // Dispatch The Message
             }
         }
         else                                        // If There Are No Messages
         {
             // Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()
             if (active)                                // Program Active?
             {
                 if (keys[VK_ESCAPE])                // Was ESC Pressed?
                 {
                     done=TRUE;                        // ESC Signalled A Quit
                 }
                 else                                // Not Time To Quit, Update Screen
                 {
                     DrawGLScene();                    // Draw The Scene
                     SwapBuffers(hDC);                // Swap Buffers (Double Buffering)
                 }
             }
 
             if (keys[VK_F1])                        // Is F1 Being Pressed?
             {
                 keys[VK_F1]=FALSE;                    // If So Make Key FALSE
                 KillGLWindow();                        // Kill Our Current Window
                 fullscreen=!fullscreen;                // Toggle Fullscreen / Windowed Mode
                 // Recreate Our OpenGL Window
                 if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
                 {
                     return 0;                        // Quit If Window Was Not Created
                 }
             }
         }
     }
 
     // Shutdown
     KillGLWindow();                                    // Kill The Window
     return (msg.wParam);                            // Exit The Program
 }

Step 4:

 

设置字符集为“No Set

 

运行结果:


 http://www.cnblogs.com/kekec/archive/2010/07/30/1789058.html
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值