Author: Eber Irigoyen
Most people know Delphi as a RAD tool to create database applications, Delphi
programmers know that with Delphi you can do EVERYTHING
Answer:
There's quite some people out there doing great efforts to promote OpenGL and
DirectX technologies with Delphi;
I will mention this, as I got the base code (and fixed it a little bit) from here:
http://nehe.gamedev.net/ http://nehe.gamedev.net/
In this article I will show you the base code to create fast and small
Delphi-OpenGL applications
I would like to comment that graphics programming is not easy, you will need some
knowledge about math and a lot of reading, is like learning a new languaje (a hard
one)
First, we will be using no forms (to make application small) and therefore
obviously no components (we're going to do this as real programmers =o) )
Our application will consist of the "project source" and one unit In our unit we
are just going to create a record to hold some of the application values and some
simple constants that are explained in detail here's the "header" of our unit
(sorry, no classes or objects):
1 type
2 TGLWindow = record
3 Active: Boolean;
4 //Window Active Flag (False is minimized, so we don't draw stuff when
5 minimized)
6 ExitGame: Boolean; //The main loop is based on this variable
7 Keys: array[0..255] of Bool; //Array Used For The Keyboard Routine
8 Fullscreen: Boolean; //Fullscreen Flag
9 MouseLButton: Integer;
10 MouseRButton: Integer; //Left or right buttons pressed? (0 or 1)
11 MouseX: Integer;
12 MouseY: Integer;
13 MouseZ: Integer;
14 //Used when right button is pressed (up and down move in and out in the Z
15 axis)
16 end;
17
18 { All User Variables Here }
19 var
20 GS: TGLWindow;
21
22 const
23 POS_X = 100; //Position of window (only when NOT in fullscren mode)
24 POS_Y = 100;
25 RES_X = 640; //Resolution
26 RES_Y = 480;
27 RES_BITS = 16; //16 bits resolution
28 WIN_TITLE = 'My Game'; //Title for our window
29
30 then from our unit we need to export this function:
31
32 function WinMain(hInstance: HINST; hPrevInstance: HINST; lpCmdLine: PChar; nCmdShow:
33 Integer): integer; stdcall;
34
35 and we will also need these variables (private to our unit, so after
36 implementation):
37
38 var
39 h_RC: HGLRC; //Permanent Rendering Context
40 h_DC: HDC; //Private GDI Device Context
41 h_Wnd: HWND; //Holds Our Window Handle
42
43 This function basically does everything, initializes the window, draws our stuff,
44 process messages, and when you're done destroys the window. Ok, now we need all the
45 procedures to initialize, process messages, etc...
46
47 Here are the functions and some explanations (I'
48 later will put the actual implementation of each one)
49
50 function DrawGLScene(): Bool; { All Rendering Done Here }
51 procedure ReSizeGLScene(const Width: GLsizei; Height: GLsizei);
52 { Resize and Initialize The GL Window }
53 function InitGL(const Width, Height: Glsizei): Bool;
54 { All Setup For OpenGL Goes Here }
55
56 //WndProc handles all the messages coming to our window
57
58 function WndProc(hWnd: HWND; //Handle For The Window
59 message: UINT; //Message For This Window
60 wParam: WPARAM; //Additional Message Information
61 lParam: LPARAM): //Additional Message Information
62 LRESULT; stdcall;
63
64 {in the CreateWindow we do:
65 - Register the class window
66 - Create the window
67 - Get a Device Context (DC)
68 - Create a Rendering Context (RC) }
69
70 function CreateGLWindow(Title: PChar; PosX, PosY: Integer; const Width,
71 Height, Bits: Integer; const FullScreenFlag: Bool): Bool; stdcall;
72
73 {In the KillWindow we do (obviously the opposite of the CreateWindow and in reverse
74 order):
75 - Restore the display settings (we need to do this even if something else fails)
76 - Delete the Rendering Context (RC)
77 - Release the Device Context (DC)
78 - Destroy the Window
79 - Unregister the class window }
80
81 procedure KillGLWindow; { Properly Kill the Window }
82
83 //WinMain is the actual Main Program (gets called from the actual Main.dpr)
84
85 function WinMain(hInstance: HINST; hPrevInstance: HINST; lpCmdLine: PChar;
86 nCmdShow: Integer): integer; stdcall;
87
88 That's all you will need to get started, here's the implementation of these
89 procedures/functions, take a good look at WinMain and WndProc, they show some good
90 stuff even for not graphic applications, you could use them to create small
91 programs that do not require windows...
92
93 oh... and one last thing... the "hello world" program in OpenGL won't even show the
94 words "Hello World" (WHAAAT??)
95 the thing is that outputing text to the screen in OpenGL is a little advanced and I
96 will show it to you in later articles (if you are interested that is). The purpose
97 of this article is to show you the base code and hopefully you will get to
98 understand it and then from there we can concentrate in the OpenGL stuff, so... I
99 will just show you how to create a simple rectangle =o (,but don'
100 as I say OpenGL is not easy and you won't be creating the next QUAKE in the next 3
101 months, first you need to create a rectangle, a triangle... a circle ...and
102 theeeen... eventually you will get there (if you really persist)
103
104 with no more preambule, here'
105
106 //---------------------------------------------------------//
107 // //
108 // Original Copyrights: Daniel Vivas //
109 // daniel@vivas.com.br //
110 // //
111 // Main Game Unit //
112 // Ported To Delhi By: Bryce TeBeest //
113 // Assistance Provided By: JP Krauss //
114 // //
115 // Taken from Jeff Molofi (NEHE) WebSite //
116 // http://nehe.gamedev.net //
117 // //
118 // Some fixes and comments by: EberSys //
119 //---------------------------------------------------------//
120 unit oglMain;
121
122 interface
123
124 uses
125 Classes,
126 Messages,
127 Windows,
128 OpenGL;
129
130 type
131 TGLWindow = record
132 Active: Boolean;
133 //Window Active Flag (False is minimized, so we don't draw stuff when
134 minimized)
135 ExitGame: Boolean; //The main loop is based on this variable
136 Keys: array[0..255] of Bool; //Array Used For The Keyboard Routine
137 Fullscreen: Boolean; //Fullscreen Flag
138 MouseLButton: Integer;
139 MouseRButton: Integer; //Left or right buttons pressed? (0 or 1)
140 MouseX: Integer;
141 MouseY: Integer;
142 MouseZ: Integer;
143 //Used when right button is pressed (up and down move in and out in the Z
144 axis)
145 end;
146
147 { All User Variables Here }
148 var
149 GS: TGLWindow;
150
151 const
152 POS_X = 100; //Position of window (only when NOT in fullscren mode)
153 POS_Y = 100;
154 RES_X = 640; //Resolution
155 RES_Y = 480;
156 RES_BITS = 16; //16 bits resolution
157 WIN_TITLE = 'My Game'; //Title for our window
158
159 {-----------------------------------------------------------}
160 { Public Procedures: }
161
162 function WinMain(hInstance: HINST; hPrevInstance: HINST; lpCmdLine: PChar; nCmdShow:
163 Integer): integer; stdcall;
164 {-----------------------------------------------------------}
165
166 implementation
167
168 var
169 h_RC: HGLRC; //Permanent Rendering Context
170 h_DC: HDC; //Private GDI Device Context
171 h_Wnd: HWND; //Holds Our Window Handle
172 {-----------------------------------------------------------}
173
174 function DrawGLScene(): Bool; { All Rendering Done Here }
175 begin
176 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); //Clear Screen and Depth
177 Buffer
178 glLoadIdentity(); //Reset The View (move to 0, 0, 0)
179
180 glTranslatef(0.0, 0.0, -6.0); // Move Right 1.5 Units And Into The Screen 6.0
181 glColor3f(0.0, 0.5, 0.5);
182 glBegin(GL_QUADS); // Draw A Quad
183 glVertex3f(-0.5, 0.5, 0.0); // Top Left
184 glVertex3f(0.5, 0.5, 0.0); // Top Right
185 glVertex3f(0.5, -0.5, 0.0); // Bottom Right
186 glVertex3f(-0.5, -0.5, 0.0); // Bottom Left
187 glEnd();
188
189 DrawGLScene := True
190 end;
191
192 procedure ReSizeGLScene(const Width: GLsizei; Height: GLsizei);
193 { Resize and Initialize The GL Window }
194 var
195 fWidth, fHeight: GLFloat;
196 begin
197 if (Height = 0) then //Prevent Divide by Zero
198 Height := 1; //Be Setting Height at One
199
200 glViewport(0, 0, Width, Height);
201 //Reset The Current Viewport and Perspective Transformation
202 glMatrixMode(GL_PROJECTION); //Select The Projection Matrix
203 glLoadIdentity(); //Reset The Project Matrix
204 fWidth := Width;
205 fHeight := Height;
206 gluPerspective(45.0, fWidth / fHeight, 0.1, 100);
207 //Calculate the Aspect Ratio of the Window
208 glMatrixMode(GL_MODELVIEW); //Select The ModelView Matrix
209 end;
210
211 { All Setup For OpenGL Goes Here }
212
213 function InitGL(const Width, Height: Glsizei): Bool;
214 var
215 fWidth, fHeight: GLfloat;
216 begin
217 glClearColor(0.0, 0.0, 0.0, 0.0); //Black Background
218 glClearDepth(1.0); //Depth Buffer Setup
219 glDepthFunc(GL_LESS); //Text
220 glEnable(GL_DEPTH_TEST); //Enables Depth Testing
221 glShadeModel(GL_SMOOTH); //Enables Smooth Color Shading
222 glMatrixMode(GL_PROJECTION);
223 glLoadIdentity(); //reset the View (move to 0, 0, 0)
224
225 fWidth := Width;
226 fHeight := Height;
227 gluPerspective(45.0, fWidth / fHeight, 0.1, 100);
228 //Calculate Aspect Ratio Of The Window
229 glMatrixMode(GL_MODELVIEW)
230 end;
231
232 //WndProc handles all the messages coming to our window
233
234 function WndProc(hWnd: HWND; //Handle For The Window
235 message: UINT; //Message For This Window
236 wParam: WPARAM; //Additional Message Information
237 lParam: LPARAM): //Additional Message Information
238 LRESULT; stdcall;
239 begin
240 if message = WM_SYSCOMMAND then
241 case wParam of //Check System Calls
242 SC_SCREENSAVE, SC_MONITORPOWER:
243 //Screensaver Trying To Start, Monitor Trying To Enter Powersave
244 begin
245 Result := 0;
246 exit
247 end
248 end;
249
250 case message of //Tells Windows We Want To Check Message
251 WM_ACTIVATE:
252 begin
253 if (Hiword(wParam) = 0) then //Check Minimization State
254 GS.Active := True
255 else
256 GS.Active := False; //when Active is False we don't draw anything
257 Result := 0;
258 end;
259 WM_CLOSE: //Did we get a close message?
260 begin
261 PostQuitMessage(0); //Send A Quit Message
262 Result := 0; //Return To The Message Loop
263 end;
264 WM_KEYDOWN: //Is A Key Being Held Down?
265 begin
266 GS.Keys[wParam] := True;
267 Result := 0; //Return To The Message Loop
268 end;
269 WM_KEYUP: //Is A Key Being Released?
270 begin
271 GS.Keys[wParam] := False;
272 Result := 0;
273 end;
274 WM_SIZE: //Resize scene
275 begin
276 ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); //LoWord=Width,
277 HighWord=Height
278 Result := 0;
279 end;
280 WM_LBUTTONDOWN: //(mouse) Left button pressed
281 begin
282 ReleaseCapture(); //Need Them Here, Because If Mouse Moves Off
283 SetCapture(h_Wnd); //Window and Returns, It Needs To Reset Status
284 GS.MouseLButton := 1;
285 GS.MouseX := LOWORD(lParam);
286 GS.MouseY := HIWORD(lParam);
287 end;
288 WM_LBUTTONUP: //(mouse) Left button released
289 begin
290 ReleaseCapture();
291 GS.MouseLButton := 0;
292 GS.MouseX := 0;
293 GS.MouseY := 0;
294 Result := 0;
295 end;
296 WM_RBUTTONDOWN: //(mouse) Right button pressed
297 begin
298 ReleaseCapture();
299 SetCapture(h_Wnd);
300 GS.MouseRButton := 1;
301 GS.MouseZ := HIWORD(lParam);
302 Result := 0;
303 end;
304 WM_RBUTTONUP: //(mouse) Right button released
305 begin
306 ReleaseCapture();
307 GS.MouseRButton := 0;
308 Result := 0
309 end
310 else
311 { Pass All Unhandled Messages TO DefWinProc }
312 Result := DefWindowProc(hWnd, message, wParam, lParam)
313 end //case message of
314 end;
315
316 {In the KillWindow we do (obviously the opposite of the CreateWindow and in reverse
317 order):
318 - Restore the display settings (we need to do this even if something else fails)
319 - Delete the Rendering Context (RC)
320 - Release the Device Context (DC)
321 - Destroy the Window
322 - Unregister the class window }
323
324 procedure KillGLWindow; { Properly Kill the Window }
325 begin
326 if (GS.FullScreen) then
327 begin //Are We In FullScreen Mode?
328 ChangeDisplaySettings(devmode(nil^), 0); //Switch Back To The Desktop
329 ShowCursor(True); //Show The Mouse Pointer
330 end;
331
332 if (h_RC <> 0) and not (wglDeleteContext(h_RC)) then //Are We Able To Delete The
333 Rc?
334 begin
335 MessageBox(0, 'Release of Rendering Context failed.', ' Shutdown Error', MB_OK
336 or
337 MB_ICONERROR);
338 h_RC := 0 //Set Rendering Context To Null
339 end;
340 if (h_DC <> 0) and (releaseDC(h_Wnd, h_DC) = 0) then
341 //Are We Able To Release The Device Context?
342 begin
343 MessageBox(0, 'Release of Device Context failed.', ' Shutdown Error', MB_OK or
344 MB_ICONERROR);
345 h_Dc := 0; //Set Dc To Null
346 end;
347 if (h_Wnd <> 0) and not (destroywindow(h_Wnd)) then
348 //Are We Able To Destroy The Window?
349 begin
350 MessageBox(0, 'Could not release hWnd.', ' Shutdown Error', MB_OK or
351 MB_ICONERROR);
352 h_Wnd := 0; //Set hWnd To Null
353 end;
354 UnregisterClass('OpenGL', hInstance)
355 end;
356
357 {in the CreateWindow we do:
358 - Register the class window
359 - Create the window
360 - Get a Device Context (DC)
361 - Create a Rendering Context (RC) }
362
363 function CreateGLWindow(Title: PChar; PosX, PosY: Integer; const Width, Height,
364 Bits:
365 Integer; const FullScreenFlag: Bool): Bool; stdcall;
366 var
367 PixelFormat: GLUint; //Holds The Result After Searching For A Match
368 WC: TWndClass; //Windows Class Structure
369 dwExStyle: DWord; //Extended Windows Style
370 dwStyle: DWord; //Window Style
371 PFD: PixelFormatDescriptor; //Tells Windows How We Want Things To Be
372 dmScreenSettings: DevMode; //Device Mode
373 h_Instance: hInst; //Holds The Instance Of The Application
374 begin
375 h_Instance := GetModuleHandle(nil); //Grab An Instance For Our Window
376 GS.Fullscreen := FullScreenFlag; //Set The Global FullScreen Flag
377
378 with WC do //can't use parentesis on "with" when using packed records
379 begin
380 Style := CS_HREDRAW or CS_VREDRAW or CS_OWNDC;
381 //ReDraw On Size -- Own DC For Window
382 lpfnWndProc := @WndProc; //WndProc Handles The Messages
383 cbClsExtra := 0; //No Extra Window Data
384 cbWndExtra := 0; //No Extra Window Data
385 hInstance := h_Instance; //Set The Instance
386 hIcon := LoadIcon(0, IDI_WINLOGO); //Load The Default Icon
387 hCursor := LoadCursor(0, IDC_ARROW); //Load The Arrow Pointer
388 hbrBackground := 0; //No BackGround Required For OpenGL
389 lpszMenuName := nil; //We Don't Want A Menu
390 lpszClassname := 'OpenGL'; //Set The Class Name
391 end;
392
393 if (RegisterClass(WC) = 0) then //Attempt To Register The Class Window
394 begin
395 MessageBox(0, 'Failed To Register The Window Class.', 'Error', MB_OK or
396 MB_ICONERROR);
397 CreateGLWindow := False;
398 exit
399 end;
400
401 if (GS.FullScreen) then
402 begin
403 ZeroMemory(@dmScreenSettings, SizeOf(dmScreenSettings));
404 //Make Sure Memory's Availiable
405
406 with dmScreenSettings do //don't use parentesis on "with" when using packed
407 records
408 begin
409 dmSize := SizeOf(dmScreenSettings); //Size Of The DevMode Structure
410 dmPelsWidth := Width; //Selected Screen Width
411 dmPelsHeight := Height; //Selected Screen Height
412 dmBitsPerPel := Bits; //Selected Bits Per Pixel
413 dmFields := DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
414 //Try to Set Selected Mode
415 end;
416
417 if (ChangeDisplaySettings(dmScreenSettings, CDS_FULLSCREEN) <>
418 DISP_CHANGE_SUCCESSFUL) then
419 if (MessageBox(0,
420 'This Fullscreen Mode Is Not Supported. Use Windowed Mode Instead?',
421 WIN_TITLE,
422 MB_YESNO or MB_ICONEXCLAMATION) = IDYES) then
423 GS.Fullscreen := False //Select Windowed Mode
424 else
425 begin
426 { Show Message Box To Let User Know Program Is Ending }
427 MessageBox(0, 'Program Will Now Close.', 'Error', MB_OK or MB_ICONERROR);
428 CreateGLWindow := False; //Return False
429 Exit
430 end
431 end;
432
433 if (GS.Fullscreen) then //If Still In FullScreen Mode
434 begin
435 dwExStyle := WS_EX_APPWINDOW; //Entended Window Style
436 dwStyle := WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN; //Window Style
437 ShowCursor(False);
438 PosX := 0; //reset these to zero
439 PosY := 0
440 end
441 else
442 begin
443 dwExStyle := WS_EX_APPWINDOW or WS_EX_WINDOWEDGE; //Extended Window Style
444 dwStyle := WS_OVERLAPPEDWINDOW or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
445 //Windows Style
446 end;
447
448 h_Wnd := CreateWindowEx(dwExStyle, //Extends Style For The Window
449 'OpenGL', //Class Name
450 Title, //Window Title
451 dwStyle, //Window Style
452 PosX, PosY, //Window Position
453 Width, Height, //Selected Width and Height
454 0, //No Parent Window
455 0, //No Menu
456 hInstance, //Instance
457 nil); //Don't Pass Anything To WM_CREATE
458 if (h_Wnd = 0) then
459 begin //If The Window Creation Failed
460 KillGLWindow(); //Reset The Display
461 MessageBox(0, 'Window Creation Error.', 'Error', MB_OK or MB_ICONEXCLAMATION);
462 CreateGLWindow := False;
463 exit;
464 end;
465
466 with PFD do //don't use parentesis on "with" when using packed records
467 begin //Tells Window How We Want Things To Be
468 nSize := SizeOf(PIXELFORMATDESCRIPTOR); //Size Of This Pixel Format Descriptor
469 nVersion := 1; //Version Number (?)
470 dwFlags := PFD_DRAW_TO_WINDOW //Format Must Support Window
471 or PFD_SUPPORT_OPENGL //Format Must Support OpenGL
472 or PFD_DOUBLEBUFFER; //Must Support Double Buffering
473 iPixelType := PFD_TYPE_RGBA; //Request An RGBA Format
474 cColorBits := Bits; //Select Our Color Depth
475 cRedBits := 0; //Color Bits Ignored
476 cRedShift := 0;
477 cGreenBits := 0;
478 cGreenShift := 0;
479 cBlueBits := 0;
480 cBlueShift := 0;
481 cAlphaBits := 0; //No Alpha Buffer
482 cAlphaShift := 0; //Shift Bit Ignored
483 cAccumBits := 0; //No Accumulation Buffer
484 cAccumRedBits := 0; //Accumulation Bits Ignored
485 cAccumGreenBits := 0;
486 cAccumBlueBits := 0;
487 cAccumAlphaBits := 0;
488 cDepthBits := 16; //16 Bit Z-Buffer (Depth Buffer)
489 cStencilBits := 0; //No Stencil Buffer
490 cAuxBuffers := 0; //No Auxilary Buffer
491 iLayerType := PFD_MAIN_PLANE; //Main Drawing Layer
492 bReserved := 0; //Reserved
493 dwLayerMask := 0; //Layer Masks Ignored
494 dwVisibleMask := 0;
495 dwDamageMask := 0;
496 end;
497
498 h_DC := GetDC(h_Wnd); //Try Getting a Device Context
499 if (h_DC = 0) then // Did We Get Device Context For The Window?
500 begin
501 KillGLWindow(); //Reset The Display
502 MessageBox(0, 'Cant''t create a GL device context.', 'Error', MB_OK or
503 MB_ICONEXCLAMATION);
504 CreateGLWindow := False; //Return False
505 exit;
506 end;
507 PixelFormat := ChoosePixelFormat(h_Dc, @pfd);
508 // Finds The Closest Match To The Pixel Format We Set Above
509 if (PixelFormat = 0) then //Did We Find A Matching Pixelformat?
510 begin
511 KillGLWindow(); //Reset The Display
512 MessageBox(0, 'Cant''t Find A Suitable PixelFormat.', 'Error', MB_OK or
513 MB_ICONEXCLAMATION);
514 CreateGLWindow := False; //Return False
515 exit;
516 end;
517 if not (SetPixelFormat(h_Dc, PixelFormat, @pfd)) then
518 begin //Are We Able To Set The Pixelformat?
519 KillGLWindow(); //Reset The Display
520 MessageBox(0, 'Cant''t set PixelFormat.', 'Error', MB_OK or MB_ICONEXCLAMATION);
521 CreateGLWindow := False; //Return False
522 exit;
523 end;
524
525 h_RC := wglCreateContext(h_DC); //Are We Able To create a Rendering Context?
526 if (h_RC = 0) then
527 begin
528 KillGLWindow(); //Reset The Display
529 MessageBox(0, 'Cant''t create a GL rendering context.', 'Error', MB_OK or
530 MB_ICONEXCLAMATION);
531 CreateGLWindow := False; //Return False
532 exit;
533 end;
534
535 if not (wglMakeCurrent(h_DC, h_RC)) then
536 //Are We Able To Activate The Rendering Context?
537 begin
538 KillGLWindow(); //Reset The Display
539 MessageBox(0, 'Cant''t activate the GL rendering context.', 'Error', MB_OK or
540 MB_ICONEXCLAMATION);
541 CreateGLWindow := False; //Return False
542 exit;
543 end;
544
545 ShowWindow(h_Wnd, SW_SHOW); //Show The Window
546 SetForegroundWindow(h_Wnd); //Slightly Higher Priority
547 SetFocus(h_Wnd); //Set Keyboard Focus To The Window
548 ReSizeGLScene(Width, Height); //Set Up Our Perspective Gl Screen
549 if not (InitGl(Width, Height)) then
550 //Do all the initialization here (load textures, etc)
551 begin
552 KillGLWindow(); //Reset The Display
553 MessageBox(0, 'Initialization Failed.', 'Error', MB_OK or MB_ICONEXCLAMATION);
554 CreateGLWindow := False; //Return False
555 exit;
556 end;
557 CreateGLWindow := True //Succes
558 end;
559
560 //WinMain is Main Program (gets called from the actual Main.dpr)
561
562 function WinMain(hInstance: HINST; hPrevInstance: HINST; lpCmdLine: PChar; nCmdShow:
563 Integer): integer; stdcall;
564 var
565 msg: TMsg;
566 begin
567 if MessageBox(0, 'Would You Like To Run In FullScreen Mode?', 'Start FullScreen',
568 MB_YESNO or MB_ICONQUESTION) = idNo then
569 GS.Fullscreen := False
570 else
571 GS.Fullscreen := True;
572
573 if not (CreateGLWindow(WIN_TITLE, POS_X, POS_Y, RES_X, RES_Y, RES_BITS,
574 GS.Fullscreen)) then
575 begin //Could We Create The OpenGL Window?
576 Result := 0;
577 exit
578 end;
579
580 while not (GS.ExitGame) do //Main Game Loop
581 begin
582 if (PeekMessage(msg, 0, 0, 0, PM_REMOVE)) then //Is There A Message?
583 begin
584 if (msg.message = WM_QUIT) then //Have We Received A Quit Message?
585 GS.ExitGame := True
586 else
587 begin
588 TranslateMessage(msg); //Translate Message
589 DispatchMessage(msg); //Dispatch the Message
590 end
591 end
592 else
593 {//No messages, so keep rendering our game} if (GS.Active) and not
594 (DrawGLScene())
595 then //here's where all the fun happens
596 GS.ExitGame := True
597 else
598 SwapBuffers(h_DC); //Not Time To Quit Yet
599
600 //Check for keyboard input here
601 if (GS.Keys[VK_ESCAPE]) then //Time To Quit
602 begin
603 GS.Keys[VK_ESCAPE] := False;
604 GS.ExitGame := True;
605 end
606 else if (GS.Keys[VK_F1]) then //Toggle FullScreen Mode
607 begin
608 GS.Keys[VK_F1] := False;
609 KillGLWindow(); //Kill Our Current Window
610 GS.Fullscreen := not GS.Fullscreen; //Toggle Our Fullscreen Flag
611 //Recreate Our Window
612 if not CreateGLWindow(WIN_TITLE, POS_X, POS_Y, RES_X, RES_Y, RES_BITS,
613 GS.Fullscreen) then
614 Result := 0;
615 end
616 end; //While not GS.ExitGame
617
618 { End of the Game }
619 KillGLWindow(); //Shutdown
620 Result := msg.wParam
621 end;
622
623 end.
624
625 {and here's the code for the "project source"}
626
627 program prjShell;
628
629 uses
630 oglMain in 'oglMain.pas';
631
632 begin
633 GS.Active := True;
634 WinMain(hInstance, hPrevInst, CmdLine, CmdShow);
635 end.
|