OpenGLWindow.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /*
  2. * This Code Was Created By Jeff Molofee 2000
  3. * A HUGE Thanks To Fredric Echols For Cleaning Up
  4. * And Optimizing This Code, Making It More Flexible!
  5. * If You've Found This Code Useful, Please Let Me Know.
  6. * Visit My Site At nehe.gamedev.net
  7. */
  8. #include <windows.h> // Header File For Windows
  9. #include <gl\gl.h> // Header File For The OpenGL32 Library
  10. #include <gl\glu.h> // Header File For The GLu32 Library
  11. HDC hDC=NULL; // Private GDI Device Context
  12. HGLRC hRC=NULL; // Permanent Rendering Context
  13. HWND hWnd=NULL; // Holds Our Window Handle
  14. HINSTANCE hInstance; // Holds The Instance Of The Application
  15. int windowWidth = 0, windowHeight = 0;
  16. bool keys[256]; // Array Used For The Keyboard Routine
  17. bool active=TRUE; // Window Active Flag Set To TRUE By Default
  18. bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
  19. static void MessageBoxPrivate( HWND hWnd, const char* pMessage, const char* pTitle, int flags )
  20. {
  21. printf( "%s: %s\n", pTitle, pMessage );
  22. }
  23. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
  24. GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
  25. {
  26. if (height==0) // Prevent A Divide By Zero By
  27. {
  28. height=1; // Making Height Equal One
  29. }
  30. glViewport(0,0,width,height); // Reset The Current Viewport
  31. glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
  32. glLoadIdentity(); // Reset The Projection Matrix
  33. // Calculate The Aspect Ratio Of The Window
  34. gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
  35. glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
  36. glLoadIdentity(); // Reset The Modelview Matrix
  37. }
  38. int InitGL(GLvoid) // All Setup For OpenGL Goes Here
  39. {
  40. glShadeModel(GL_SMOOTH); // Enable Smooth Shading
  41. glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
  42. glClearDepth(1.0f); // Depth Buffer Setup
  43. glEnable(GL_DEPTH_TEST); // Enables Depth Testing
  44. glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
  45. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
  46. return TRUE; // Initialization Went OK
  47. }
  48. int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
  49. {
  50. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
  51. glLoadIdentity(); // Reset The Current Modelview Matrix
  52. return TRUE; // Everything Went OK
  53. }
  54. GLvoid KillGLWindow(GLvoid) // Properly Kill The Window
  55. {
  56. if (fullscreen) // Are We In Fullscreen Mode?
  57. {
  58. ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
  59. ShowCursor(TRUE); // Show Mouse Pointer
  60. }
  61. if (hRC) // Do We Have A Rendering Context?
  62. {
  63. if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
  64. {
  65. MessageBoxPrivate(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
  66. }
  67. if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
  68. {
  69. MessageBoxPrivate(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
  70. }
  71. hRC=NULL; // Set RC To NULL
  72. }
  73. if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
  74. {
  75. MessageBoxPrivate(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
  76. hDC=NULL; // Set DC To NULL
  77. }
  78. if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
  79. {
  80. MessageBoxPrivate(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
  81. hWnd=NULL; // Set hWnd To NULL
  82. }
  83. if (!UnregisterClass((LPCWSTR)L"OpenGL",hInstance)) // Are We Able To Unregister Class
  84. {
  85. MessageBoxPrivate(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
  86. hInstance=NULL; // Set hInstance To NULL
  87. }
  88. }
  89. /* This Code Creates Our OpenGL Window. Parameters Are: *
  90. * title - Title To Appear At The Top Of The Window *
  91. * width - Width Of The GL Window Or Fullscreen Mode *
  92. * height - Height Of The GL Window Or Fullscreen Mode *
  93. * bits - Number Of Bits To Use For Color (8/16/24/32) *
  94. * fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */
  95. BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag, bool hideWindow=true)
  96. {
  97. GLuint PixelFormat; // Holds The Results After Searching For A Match
  98. WNDCLASS wc; // Windows Class Structure
  99. DWORD dwExStyle; // Window Extended Style
  100. DWORD dwStyle; // Window Style
  101. RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
  102. WindowRect.left=(long)0; // Set Left Value To 0
  103. WindowRect.right=(long)width; // Set Right Value To Requested Width
  104. WindowRect.top=(long)0; // Set Top Value To 0
  105. WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height
  106. fullscreen=fullscreenflag; // Set The Global Fullscreen Flag
  107. hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
  108. wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
  109. wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
  110. wc.cbClsExtra = 0; // No Extra Window Data
  111. wc.cbWndExtra = 0; // No Extra Window Data
  112. wc.hInstance = hInstance; // Set The Instance
  113. wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
  114. wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
  115. wc.hbrBackground = NULL; // No Background Required For GL
  116. wc.lpszMenuName = NULL; // We Don't Want A Menu
  117. wc.lpszClassName = L"OpenGL"; // Set The Class Name
  118. if (!RegisterClass(&wc)) // Attempt To Register The Window Class
  119. {
  120. MessageBoxPrivate(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  121. return FALSE; // Return FALSE
  122. }
  123. if (fullscreen) // Attempt Fullscreen Mode?
  124. {
  125. DEVMODE dmScreenSettings; // Device Mode
  126. memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
  127. dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
  128. dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
  129. dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
  130. dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
  131. dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
  132. // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
  133. if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
  134. {
  135. /*
  136. // If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
  137. if (MessageBoxPrivate(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
  138. {
  139. fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
  140. }
  141. else
  142. {
  143. // Pop Up A Message Box Letting User Know The Program Is Closing.
  144. MessageBoxPrivate(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
  145. return FALSE; // Return FALSE
  146. }
  147. */
  148. fullscreen=FALSE;
  149. }
  150. }
  151. if (fullscreen) // Are We Still In Fullscreen Mode?
  152. {
  153. dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
  154. dwStyle=WS_POPUP; // Windows Style
  155. ShowCursor(FALSE); // Hide Mouse Pointer
  156. }
  157. else
  158. {
  159. dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
  160. dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
  161. }
  162. AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
  163. // Create The Window
  164. if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window
  165. L"OpenGL", // Class Name
  166. L"DXTCompress", // Window Title
  167. dwStyle | // Defined Window Style
  168. WS_CLIPSIBLINGS | // Required Window Style
  169. WS_CLIPCHILDREN, // Required Window Style
  170. 0, 0, // Window Position
  171. WindowRect.right-WindowRect.left, // Calculate Window Width
  172. WindowRect.bottom-WindowRect.top, // Calculate Window Height
  173. NULL, // No Parent Window
  174. NULL, // No Menu
  175. hInstance, // Instance
  176. NULL))) // Dont Pass Anything To WM_CREATE
  177. {
  178. KillGLWindow(); // Reset The Display
  179. MessageBoxPrivate(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  180. return FALSE; // Return FALSE
  181. }
  182. static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
  183. {
  184. sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
  185. 1, // Version Number
  186. PFD_DRAW_TO_WINDOW | // Format Must Support Window
  187. PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
  188. PFD_DOUBLEBUFFER, // Must Support Double Buffering
  189. PFD_TYPE_RGBA, // Request An RGBA Format
  190. bits, // Select Our Color Depth
  191. 0, 0, 0, 0, 0, 0, // Color Bits Ignored
  192. 0, // No Alpha Buffer
  193. 0, // Shift Bit Ignored
  194. 0, // No Accumulation Buffer
  195. 0, 0, 0, 0, // Accumulation Bits Ignored
  196. 16, // 16Bit Z-Buffer (Depth Buffer)
  197. 0, // No Stencil Buffer
  198. 0, // No Auxiliary Buffer
  199. PFD_MAIN_PLANE, // Main Drawing Layer
  200. 0, // Reserved
  201. 0, 0, 0 // Layer Masks Ignored
  202. };
  203. if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
  204. {
  205. KillGLWindow(); // Reset The Display
  206. MessageBoxPrivate(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  207. return FALSE; // Return FALSE
  208. }
  209. if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
  210. {
  211. KillGLWindow(); // Reset The Display
  212. MessageBoxPrivate(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  213. return FALSE; // Return FALSE
  214. }
  215. if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
  216. {
  217. KillGLWindow(); // Reset The Display
  218. MessageBoxPrivate(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  219. return FALSE; // Return FALSE
  220. }
  221. if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
  222. {
  223. KillGLWindow(); // Reset The Display
  224. MessageBoxPrivate(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  225. return FALSE; // Return FALSE
  226. }
  227. if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
  228. {
  229. KillGLWindow(); // Reset The Display
  230. MessageBoxPrivate(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  231. return FALSE; // Return FALSE
  232. }
  233. if( hideWindow )
  234. ShowWindow(hWnd,SW_HIDE); // Show The Window
  235. else
  236. ShowWindow(hWnd,SW_SHOW); // Show The Window
  237. SetForegroundWindow(hWnd); // Slightly Higher Priority
  238. SetFocus(hWnd); // Sets Keyboard Focus To The Window
  239. ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen
  240. if (!InitGL()) // Initialize Our Newly Created GL Window
  241. {
  242. KillGLWindow(); // Reset The Display
  243. MessageBoxPrivate(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  244. return FALSE; // Return FALSE
  245. }
  246. return TRUE; // Success
  247. }
  248. LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
  249. UINT uMsg, // Message For This Window
  250. WPARAM wParam, // Additional Message Information
  251. LPARAM lParam) // Additional Message Information
  252. {
  253. switch (uMsg) // Check For Windows Messages
  254. {
  255. case WM_ACTIVATE: // Watch For Window Activate Message
  256. {
  257. if (!HIWORD(wParam)) // Check Minimization State
  258. {
  259. active=TRUE; // Program Is Active
  260. }
  261. else
  262. {
  263. active=FALSE; // Program Is No Longer Active
  264. }
  265. return 0; // Return To The Message Loop
  266. }
  267. case WM_SYSCOMMAND: // Intercept System Commands
  268. {
  269. switch (wParam) // Check System Calls
  270. {
  271. case SC_SCREENSAVE: // Screensaver Trying To Start?
  272. case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
  273. return 0; // Prevent From Happening
  274. }
  275. break; // Exit
  276. }
  277. case WM_CLOSE: // Did We Receive A Close Message?
  278. {
  279. PostQuitMessage(0); // Send A Quit Message
  280. return 0; // Jump Back
  281. }
  282. case WM_KEYDOWN: // Is A Key Being Held Down?
  283. {
  284. keys[wParam] = TRUE; // If So, Mark It As TRUE
  285. return 0; // Jump Back
  286. }
  287. case WM_KEYUP: // Has A Key Been Released?
  288. {
  289. keys[wParam] = FALSE; // If So, Mark It As FALSE
  290. return 0; // Jump Back
  291. }
  292. case WM_SIZE: // Resize The OpenGL Window
  293. {
  294. windowWidth = LOWORD(lParam);
  295. windowHeight = HIWORD(lParam);
  296. ReSizeGLScene(windowWidth, windowHeight); // LoWord=Width, HiWord=Height
  297. return 0; // Jump Back
  298. }
  299. }
  300. // Pass All Unhandled Messages To DefWindowProc
  301. return DefWindowProc(hWnd,uMsg,wParam,lParam);
  302. }
粤ICP备19079148号