flipCode - Tech File - Kurt Miller [an error occurred while processing this directive]
Kurt Miller
Click the name for some bio info

E-Mail: kurt@flipcode.com

   09/09/1999, Interface Design Ramblings

Its my belief that a program's interface should at least try to fit the type of program it is. A spreadsheet should look like a normal grey window, but games and demos need to be a bit more spicy in my humble opinion. I love the look of a good interface in a game or demo. Whether its a fancy dialog box for selecting your d3d driver/device or an in-game menu system such as the menus in the daikatana demo or forsaken, aesthetic appeal is always important. Interestingly enough, I noticed that several good graphics coders that I talk to don't care to know Windows programming any better than they have to and therefore just throw up some shoddy, often just plain ugly, dialog boxes and menus for things like selection screens.

Don't get me wrong. Snazzy interfaces can't and won't make a game or demo, but the more icing on an already-delicious cake, the more people want to gobble it up ;p. So what's my point? Basic interfaces such as jazzed up dialog windows aren't particularly hard to create. In the future I might do an update on in-game interfaces, but in the meantime here's a little something on fancy dialog windows. Yes, I know its largely useless, but I'm sure someone out there has got to be at least slightly interested.

Enhanced Dialog Windows

If you've ever seen mp3 players such as winamp, sonique, or the zillions of others, you probably noticed that you're not going to be seeing a grey box with buttons on it (akin to normal Windows windows). Most of the interfaces for mp3 players these days are highly configurable and sport transparent regions and owner-drawn buttons. So how do you do fancy windows?

Here's a screenshot from an engine I finished sometime last year. As you can tell, I went way way overboard on the dialog design!! That was definitely TOO far over the top, but it makes for a perfect example :) Yes, that's a modeless dialog box, with transparent regions and some owner-drawn buttons, all moveable and clickable. Click on the image for an actual-size version.

Well I've moved on from overly-fancy-yet-highly-useless dialog boxes such as the one in this picture, but lets return to my original point: how to create such a dialog box. Well, for the one pictured, the process I used is actually quite simple.

The main dialog appearance itself is a regular old bitmap with a color for transparency. To get the transparent regions, you can try the following steps.
  • Smack your bitmap onto the background of your dialog box. This can be done from the resource editor if you wish.
  • Remove the border and title bar from the dialog window
  • During the initialization message that your dialog window receives, you need to create a window region (HRGN) that exactly matches the dimensions of your bitmap, including transparent regions.
  • There are numerous ways to do that final step, but one way is using the oh-so-handy CreateRectRegion function and CombineRegion to create your region. You can loop through your image and check if the current pixel that you're at is supposed to be transparent (which means you need to pick a color to serve as your 'transparent' color), and if it isn't, add a tiny rectangular region (a 'pixel' rectangle) to your final region using the two functions I just mentioned.

    If you use CombineRegion's RGN_OR and RGN_XOR parameter options it makes the process much easier to build your complete "map". Make sure you're deleting all the tiny regions that you're creating after you add them to the final region during the loop.

    When your loop is finished, you should have a region that is the exact 'shape' of what you want to be the visible portions of your window, which you can use to set the window region of your window (using SetWindowRgn). You're limited only by your imagination (ie, creating a good background image for the window). Just be certain to clean up everything you allocate otherwise things can get pretty messy. You're on your own there. This entire loop can be quite slow at startup, so if you want you can save the region data to a file, preferably compressed, to eliminate that time consumption, but if your window is small, it probably won't be worth it.

    As for moving the window around (there's no real title bar), that's annoying, but what someone ended up suggesting to me was this: when a left-button mouse message is received, override it by posting WM_NCLBUTTONDOWN which is a non-client region message. That will let you move the window around w/o dragging the graphics up and down. The process I described above isn't the only way to do snazzy dialogs, but its the method I used at the time. For simpler ways to work with regions, check out some of the simpler Windows functions like CreateRoundRectRgn. I believe there is one for convex polygon regions too. My latest engine uses CreateRoundRectRgn for a much simpler but effective design.

    So, why on earth would you want to spend all the trouble to create interfaces like these? Good question. Its just a matter of taste. Adding some kind of style to your work will make it stick out -- more specifically, the people who run it will remember it. As for pratical uses, I can't think of many off-hand, but as a broad example: suppose you were writing a hand-held game emulator. Wouldn't it be much more interesting to have the exact look and shape of the original physical object as a window on your desktop? Anyway, that's where creativity comes in. Good luck.

  • 03/15/2000 - Miscellaneous Jargon
  • 02/20/2000 - Bits And Particles
  • 09/09/1999 - Interface Design Ramblings
  • 08/16/1999 - Lightmapping Revisited (And My (Re)Introduction)

  • This document may not be reproduced in any way without explicit permission from the author and flipCode. All Rights Reserved. Best viewed at a high resolution. The views expressed in this document are the views of the author and NOT neccesarily of anyone else associated with flipCode.

    [an error occurred while processing this directive]