Borland Online And The Cobb Group Present:


January, 1996 - Vol. 3 No. 1

Windows graphics programming - Implementing WinG in C++

by John De Goes

Microsoft Windows has traditionally been a graphically slow operating system. Even the fastest graphics accelerators often fall behind the demands of multimedia and game applications. With the release of WinG and the DirectDraw SDK, however, speed is no longer a problem. In this article, we'll explain the fundamentals of the WinG library and provide source code for a compiler-independent set of C++ classes that allows you to fully exploit the power of the WinG library with minimal effort.

Gee whiz, it's WinG

Microsoft developed WinG (pronounced win-gee) solely to lure game and multi-media developers from the clutches of DOS, an operating system few others could rival in terms of raw graphic speed. Though not a complete graphics library, WinG does provide programmers with necessary functions such as palette manipulation and screen blitting, and it allows the use of the standard GDI functions as well. (Blitting is the process of transferring an image or bitmap directly to the screen.) While blitting may seem like a relatively trivial task, it's the speed of this process that ultimately determines an operating system's graphical limit (though drawing lines and polygons can also substantially affect overall speed).

If you've ever tried writing (or in fact, using) a full-screen, video-based application under the Windows GDI, you've probably discovered you could measure the frames-per-second (the number of times the image is updated per second) using a stopwatch! This situation was obviously unacceptable, so Microsoft released WinG to the world, enabling developers everywhere to write graphical applications that perform as quickly as their DOS counterparts.

The WinG class menagerie

WinG works optimally with 256-color bitmaps, so that's what we'll support in our set of classes. The 256 individual colors can be represented with a type unsigned char, which conveniently holds one of 256 distinct values. In order to provide support for future libraries (including DirectDraw, Microsoft's newest library for fast Windows graphics), we'll create a base class that will embody many of the aspects of a graphic window. Listing A contains the source for this base class.


Listing A: GRAPHWIN.HPP

// Description: Base class for the WinG 
// window class
//
// References: WinG help file, Game 
// Developer Magazine

#include <Windows.H>

struct BitmapInfoHeader {
BITMAPINFOHEADER Header;
RGBQUAD ColorTable [ 256 ];
};

class GraphWin {
protected:
// Protected data:
BitmapInfoHeader BufInfo;

unsigned char *WinBuffer;
long BufWidth, WinHeight, WinWidth;
public:
// Public data:
unsigned char *GetBuff () { return WinBuffer; };

long GetBufWidth () { return BufWidth; };
long GetWinWidth () { return WinWidth; };
long GetWinHeight () { return WinHeight; };

// A function to display the buffer 
// (pure virtual):
virtual void DispBuffer () = 0;
};

This class is fairly straightforward and requires only a bit of explanation. The GetBuff() function returns a pointer to the window's buffer. DispBuffer() copies the buffer's contents to the window. The WinWidth and WinHeight variables are just what you'd expect­­the width and height of the output window. The BufWidth variable is the width of the buffer, expressed in pixels. The width of the buffer will differ from the width of the window if the window's width is not an even number. The declaration of the derived class, dubbed WinGWindow, is shown in Listing B.


Listing B: WING.HPP

// Description: Base class for the WinG 
// window class
//
// References: WinG help file, Game 
// Developer Magazine

#include <WinG.H>
#include <Windows.H>

#include "GraphWin.HPP"

class WinGWindow : public GraphWin {
protected:
// Protected data:
HDC BufDC;
HBITMAP BufBitmap;
HBITMAP OldMonoBitmap;
void InitWinG ( HWND ActiveWindow );
public:
// Public data:
void DispBuffer ();
void DispBuffer ( HWND ActiveWindow );

// Constructor and Destructor:
WinGWindow ();
WinGWindow ( HWND ActiveWindow );
~WinGWindow ();
};

This class's constructor optionally accepts the handle of an application window. We've provided an overloaded function, DispBuffer(), for much the same purpose. With no arguments supplied to either function, each will use the application's active window by default.

As a side note, WinG can create two types of windows: bottom-up and top-down. On some machines, bottom-up bitmaps are faster than top-downs, and on other machines, the reverse is true. The source code for the WinGWindow class is shown in Listing C.

To give you an idea of how the buffer works in relation to the window, try setting the first element of the WinBuffer array to 1 and calling DispBuffer(). Doing so will put a blue pixel in the upper-right corner of the window (for top-down windows), or in the lower-right corner (for bottom-up windows).

To obtain your own copy of the WinG library (which you'll need if you want to use the code presented in this article), log onto CompuServe and type GO WINMM at any "!" prompt. Doing so will bring you to the Windows MultiMedia forum, from which you can download the library. This file, WING.DLL, comes with an excellent WinG help reference containing ample source code and full descriptions for each of the WinG library functions.

An impish LIB

Borland C++ can't recognize the non-standard format that the WinG library uses, so you must use the utility IMPLIB.EXE, which resides in the BC4\BIN directory. To create a library compatible with Borland C++, go to the DLL directory off the main WinG directory and type the following:

Implib MyLib.LIB WinG32.DLL

At this point, you'll be able to add MYLIB.LIB to your project and use the WinG library's functions.

Conclusion

If you're writing an application that needs to display high-speed graphics, you'll want to take a close look at the WinG library, even if you're not writing a game. By using the WinGWindow class we've demonstrated here, you can take advantage of the WinG graphics routines quickly and easily.

John De Goes is an independent consultant and game programmer. You can contact John via CompuServe at 75404,2752.

Return to the Borland C++ Developer's Journal index

Subscribe to the Borland C++ Developer's Journal


Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.