If you are a die hard C++ programmer, one of the first things you want to do after you see the galaxy of Win32 functions is try to organize them into classes. This desire is especially strong when you consider all the Windows handles you have to remember to close after you are finished with a handled object like a device context. Once this homework is installed in C++ constructors and destructors, your resulting code looks cleaner and it certainly avoids resource leaks.
Being a wise programmer, you'll look carefully at MFC before rolling your own object-oriented Win32 system. As you look into Microsoft's implementation, you'll begin to wonder if rolling your own wasn't such a good idea in the first place. The decision is not an easy one: MFC has a lot to offer. The problem is that MFC has a little too much to offer, actually. It depends on what you really want to do with your game. I'll try to run through a few arguments for and against the use of MFC in your game. I've certainly been on both sides of the fence myself. I'll be completely honest with you, right now I'm on the "don't bother with MFC" side.
One argument against MFC is its size. Any EXE or DLL that is statically linked to MFC will be nearly one megabyte larger. That might not sound like too much when desktops are sporting many hundreds of megabytes of RAM and many tens of gigabytes of hard drive space, but consider the effect it will have on downloaded games.
|A Tale from the Pixel Mines|| |
I was working with the Microsoft Zone on a project submission and one of the first things they asked me was whether my game required MFC. At that time it did; our game was designed to run in a window, full-screen, or as an ActiveX control on a web page. The Zone folks loved that the game worked well in all those formats, but the added download size turned them off. Many of their customers still used dial-up and the added megabyte was simply too much.
The most compelling argument against using MFC in games is they don't need it. Games generally roll their own custom code for the user interface. The boring grey dialog boxes of standard Windows GDI fare are the antithesis of game interfaces, and, the last time I looked, I didn't see a special windows control for a 3D radar system anyway.
All the other MFC classes that deal with threads, windows, files, and other parts of the Win32 API are wrappers around Win32 objects. If you're curious about their implementation just load up the source code and find out how they did it; it's included with Visual Studio. If you don't want to use all of MFC but you like the implementation of one of their classes, by all means study their implementation and roll your own.
Lately I've been feeling that the naked C Win32 API that I'm so used to is becoming buried under layers of MSDN. Every time I hunt for some documentation regarding a Win32 function I'm assaulted by MFC first. That's annoying. It's almost as if Microsoft doesn't believe that there are programmers out there who use the C functions. Probably the most compelling reason to use MFC are the pre-rolled controls and windows that you can use for rapid development. This is much more likely in code you'll write for internal tools and level editors than in your actual game. I don't know if you've ever tried to write a grid control—an object that sorts rows and columns of data—but it's not for the meek. It's much better to search for one on the Internet and plug your new toy into an MFC-based architecture.
This is especially true of the CHtmlView class. I'd argue against creating your own HTML renderer. The task is mind-numbing and time consuming. At the end of your hard work, you'll have something that might be HTML 1.0 compliant if you're lucky.
|A Tale from the Pixel Mines|| |
You are going to think I'm making this one up. The first Microsoft product I worked on was Microsoft Casino, and the year was 2000—a fact that will become important shortly. The casino game had tons of help text and our plan was to use MFC's CHtmlView class, which was a thin wrapper around the Internet Explorer's HTML renderer. We had it working, sort of, when I got a phone call from the product manager at 'The Soft'. He told me we couldn't use CHtmlView, and that we were going to have to find our own HTML renderer. I was stunned beyond belief that Microsoft couldn't use technology they owned. He explained that the legal status of Microsoft products requiring Internet Explorer was under review from the United States Justice Department and various Attorney Generals at the state level. If I used CHtmlView, Microsoft Casino would require Internet Explorer, or a component of it anyway. I briefly considered using the then open source Netscape renderer, and figured that if I did I'd get a midnight visit from the Microsoft Secret Police. We ended up cobbling our own renderer together in the end. A few versions later, Microsoft engineers handed us an HTML-ish renderer that had nothing to do with Internet Explorer, and we used it. It's very odd to have a bunch of lawyers tell you how to write software.
Another compelling reason to use MFC is that it works. It is also extremely well tested, and is widely understood by many programmers. MFC has been unfairly panned in the game industry as bloated, irrelevant, and designed by crazy people. It turns out that the MFC engineers came up with a great solution strategy for implementing a C++ based windows object.
The problem the engineers had was message handling. They wanted the clarity of implementing member functions like CWnd::OnPaint() and CWnd::OnMouseMove() without the overhead of a truly staggering virtual function table—one VMT entry for each message would be way too big. Their solution implements a class specific jump table with BEGIN_MESSAGE_MAP() and END_MESSAGE_MAP() macros. It's interesting to dig into the MFC source to see how they did it. They essentially implemented a sparse virtual function table!
|A Tale from the Pixel Mines|| |
On the Ultima IX project at Origin Systems, we had the task of creating the Ultima IX editor. This world editor was a complicated tool that imported and organized game assets, built levels, scripted events, and did it all in a completely network aware environment so that multiple people could work on the same map simultaneously. It was a huge project, and we briefly thought about using MFC but decided against it, mostly because of fear. One of the programmers had started a C++ based Windows library called OFC—Origin's Foundation Classes. By the end of the project OFC's source code had many of the same elements and architecture as MFC. If I had to do it over again, I would have used MFC for Ultima IX's editor and spent the extra programming time doing other things.
A good reason to use MFC on your project is to avoid redeveloping something that already exists. There's nothing in MFC that can't be coded using naked Win32 calls and some elbow grease. All the native Windows components and controls like the edit control are available through C calls. You don't need MFC for creating a user interface, but you should be aware that MFC has already done most of the heavy lifting. If you really want to rewrite, re-debug, and retest a bunch of C++ that already exists in a stable and trusted form, by all means be my guest.
You also don't need MFC to fully support UNICODE either, especially now that MFC7 moved its CString class to the ATL string implementation. Your game can be fully UNICODE compliant without MFC. If you're going to be building tons of dialog boxes and other doodads in your resource editor or for an internal tool like a level editor, you might consider MFC. If you are building a game with one window and your home grown user interface there's no reason to feel compelled to use MFC.