JavaScript EditorFree JavaScript Editor     Ajax Editor 



Main Page
  Previous Section Next Section

Getting Information

In the movie, Wall Street, Gordon Gekko once said: "Why don't you stop sending me information and start getting some?" These words are appropriate for this circumstance and many other things. Information about the system your game is running on is vital to making your game take advantage of all the resources that a system has to offer. As you would expect, Windows is full of information retrieval functions that acquire a myriad of details about Windows settings and the hardware itself.

Win32 supports a number of Get*() functions and DirectX supports a number of GetCaps*() functions. I'm only going to cover a few of the Win32 functions that I use from time to time. In the next part of the book you'll see more of the information retrieval functions that DirectX supports. Those functions are more geared toward the multimedia end of the spectrum.

The following paragraphs describe three functions that I like to use from time to time. (There are many more.) Basically, anything you want to know about Windows is there and can be queried with a "Get" class function. Simply type "get" into the Win32 SDK Search engine within your compiler Help and you should find whatever you need. We'll take a look at these three functions just to get a feel for using them.

The first function we'll look at is called GetSystemInfo(). It basically returns everything you would ever want to know about the processing hardware you're running on—things like the type of processor, how many processors, and so forth. Here's the function prototype:

VOID GetSystemInfo(
     LPSYSTEM_INFO lpSystemInfo);
    // address of system information structure

The function simply takes a pointer to a SYSTEM_INFO structure and fills in all the fields. Here's what a SYSTEM_INFO structure looks like:

typedef struct _SYSTEM_INFO
{ // sinf
union {
      DWORD dwOemId;
      struct {
             WORD wProcessorArchitecture;
             WORD wReserved;
             };
      };
DWORD  dwPageSize;
LPVOID lpMinimumApplicationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD  dwActiveProcessorMask;
DWORD  dwNumberOfProcessors;
DWORD  dwProcessorType;
DWORD  dwAllocationGranularity;
WORD   wProcessorLevel;
WORD   wProcessorRevision;
} SYSTEM_INFO;

The details of all these fields are pages long and we don't have room to cover them, but obviously there are some interesting fields. For example, dwNumberOfProcessors is the number of processors on the motherboard of the PC. dwProcessorType is the actual type of the processor, which can be one of the following:

Value
PROCESSOR_INTEL_386
PROCESSOR_INTEL_486
PROCESSOR_INTEL_PENTIUM

The other fields are all self-explanatory—just take a look at the Win32 SDK for details. This is an amazing function, however, if you think about it. Can you imagine how hard it is to determine the type of processor installed, let alone how many of them? Where would you even start?

You would start by writing a very complex detection algorithm that knows things about 486s, Pentiums, Pentium IIs, and so on, and it would poke and pry with writes and reads until it figured out what processor was on the machine. Of course, Pentium class processors have ID strings and machine flags, but 486s are a lot harder to figure out. The point is that this is a great function to get system-level information.

The next function I want to show you is very general and can retrieve all kinds of cool information about Windows and the Desktop. It's called GetSystemMetrics():

int GetSystemMetrics(int nIndex); // system metric or configuration setting to retrieve

GetSystemMetrics() is very powerful. What you do is send it the index of the data you want retrieved, as shown in Table 4.7, and it is returned. By the way, Table 4.7 is the longest table in the book. I really hate looking it up in the Help, so I'm going to break down and add it to the book for your convenience <BG>.

Table 4.7. System Metric Constants for GetSystemMetrics()
Value Description
SM_ARRANGE Flags specifying how the system arranged minimized windows. For more information about minimized windows, see the following Remarks section.
SM_CLEANBOOT

Value that specifies how the system was started:

0 Normal boot

1 Fail-safe boot

2 Fail-safe with network boot

SM_CMOUSEBUTTONS Number of buttons on mouse, or zero if no mouse is installed.
SM_CXBORDER, SM_CYBORDER The width and height, in pixels, of a window border. This is equivalent to the SM_CXEDGE value for windows with the 3-D look.
SM_CXCURSOR, SM_CYCURSOR Width and height, in pixels, of a cursor. These are the cursor dimensions supported by the current display driver. The system cannot create cursors of other sizes.
SM_CXDOUBLECLK, SM_CYDOUBLECLK Width and height, in pixels, of the rectangle around the location of a first click in a double-click sequence. The second click must occur within this rectangle for the system to consider the two clicks a double-click. (The two clicks must also occur within a specified time.)
SM_CXDRAG, SM_CYDRAG Width and height, in pixels, of a rectangle centered on a drag point to allow for limited movement of the mouse pointer before a drag operation begins. This enables the user to click and release the mouse button easily without unintentionally starting a drag operation.
SM_CXEDGE, SM_CYEDGE Dimensions, in pixels, of a 3-D border. These are the 3-D counterparts of SM_CXBORDER and SM_CYBORDER.
SM_CXFIXEDFRAME, SM_CYFIXEDFRAME Thickness, in pixels, of the frame around the perimeter of a window that has a caption but is not sizable. SM_CXFIXEDFRAME is the width of the horizontal border and SM_CYFIXEDFRAME is the height of the vertical border.
SM_CXFULLSCREEN, SM_CYFULLSCREEN Width and height of the client area for a full-screen window. To get the coordinates of the portion of the screen not obscured by the tray, call the SystemParametersInfo function with the SPI_GETWORKAREA value.
SM_CXHSCROLL, SM_CYHSCROLL Width, in pixels, of the arrow bitmap on a horizontal scroll bar; and height, in pixels, of a horizontal scroll bar.
SM_CXHTHUMB Width, in pixels, of the thumb box in a horizontal scroll bar.
SM_CXICON, SM_CYICON The default width and height, in pixels, of an icon. These values are typically 32x32, but can vary depending on the installed display hardware.
SM_CXICONSPACING, SM_CYICONSPACING Dimensions, in pixels, of a grid cell for items in large icon view. Each item fits into a rectangle of this size when arranged. These values are always greater than or equal to SM_CXICON and SM_CYICON.
SM_CXMAXIMIZED, SM_CYMAXIMIZED Default dimensions, in pixels, of a maximized top-level window.
SM_CXMAXTRACK, SM_CYMAXTRACK Default maximum dimensions, in pixels, of a window that has a caption and sizing borders. The user cannot drag the window frame to a size larger than these dimensions. A window can override these values by processing the WM_GETMINMAXINFO message.
SM_CXMENUCHECK, SM_CYMENUCHECK Dimensions, in pixels, of the default menu check mark bitmap.
SM_CXMENUSIZE, SM_CYMENUSIZE Dimensions, in pixels, of menu bar buttons, such as multiple document (MDI) child close.
SM_CXMIN, SM_CYMIN Minimum width and height, in pixels, of a window.
SM_CXMINIMIZED, SM_CYMINIMIZED Dimensions, in pixels, of a normal minimized window.
SM_CXMINSPACING, SM_CYMINSPACING Dimensions, in pixels, of a grid cell for minimized windows. Each minimized window fits into a rectangle this size when arranged. These values are always greater than or equal to SM_CXMINIMIZED and SM_CYMINIMIZED.
SM_CXMINTRACK, SM_CYMINTRACK Minimum tracking width and height, in pixels, of a window. The user cannot drag the window frame to a size smaller than these dimensions. A window can override these values by processing the WM_GETMINMAXINFO message.
SM_CXSCREEN, SM_CYSCREEN Width and height, in pixels, of the screen.
SM_CXSIZE, SM_CYSIZE Width and height, in pixels, of a button in a window's caption or title bar.
SM_CXSIZEFRAME, SM_CYSIZEFRAME Thickness, in pixels, of the sizing border around the perimeter of a window that can be resized. SM_CXSIZEFRAME is the width of the horizontal border and SM_CYSIZEFRAME is the height of the vertical border.
SM_CXSMICON, SM_CYSMICON Recommended dimensions, in pixels, of a small icon. Small icons typically appear in window captions and in small icon view.
SM_CXSMSIZE, SM_CYSMSIZE Dimensions, in pixels, of small caption buttons.
SM_CXVSCROLL, SM_CYVSCROLL Width, in pixels, of a vertical scroll bar; and height, in pixels, of the arrow bitmap on a vertical scroll bar.
SM_CYCAPTION Height, in pixels, of the normal caption area.
SM_CYKANJIWINDOW For double-byte character set versions of Windows, height, in pixels, of the Kanji window at the bottom of the screen.
SM_CYMENU Height, in pixels, of single-line menu bar.
SM_CYSMCAPTION Height, in pixels, of a small caption.
SM_CYVTHUMB Height, in pixels, of the thumb box in a vertical scroll bar.
SM_DBCSENABLED TRUE or nonzero if the double-byte character set (DBCS) version of USER.EXE is installed; FALSE or zero otherwise.
SM_DEBUG TRUE or nonzero if the debugging version of USER.EXE is installed; FALSE or zero otherwise.
SM_MENUDROPALIGNMENT TRUE or nonzero if drop-down menus are right-aligned relative to the corresponding menu-bar item; FALSE or zero if they are left-aligned.
SM_MIDEASTENABLED TRUE if the system is enabled for Hebrew/Arabic languages.
SM_MOUSEPRESENT TRUE or nonzero if a mouse is installed; FALSE or zero otherwise.
SM_MOUSEWHEELPRESENT Windows NT only: TRUE or nonzero if a mouse with a wheel is installed; FALSE or zero otherwise.
SM_NETWORK The least significant bit is set if a network is present; otherwise, it is cleared. The other bits are reserved for future use.
SM_PENWINDOWS TRUE or nonzero if the Microsoft Windows for Pen computing extensions are installed; zero or FALSE otherwise.
SM_SECURE TRUE if security is present FALSE otherwise.
SM_SHOWSOUNDS TRUE or nonzero if the user requires an application to present information visually in situations where it would otherwise present the information only in audible form; FALSE or zero otherwise.
SM_SLOWMACHINE TRUE if the computer has a low-end (slow) processor; FALSE otherwise.
SM_SWAPBUTTON TRUE or nonzero if the meanings of the left and right mouse buttons are swapped; FALSE or zero otherwise.

If it isn't in Table 4.7, you don't need to know! As an example, here's a cool way to create a window that's as large as the screen display:

// create the window
if (!(hwnd = CreateWindowEx(NULL,     // extended style
                WINDOW_CLASS_NAME,   // class
                "Button Demo",       // title
                WS_POPUP | WS_VISIBLE,
                0,0,      // initial x,y
                GetSystemMetrics(SM_CXSCREEN), // initial width
                GetSystemMetrics(SM_CYSCREEN), // initial height
                NULL,      // handle to parent
                NULL,      // handle to menu
                hinstance,    // instance of this application
                NULL)))      // extra creation parms
                return(0);

NOTE

Notice the use of the WS_POPUP window style rather than the WM_OVERLAPPEDWINDOW. This creates a window without any borders or controls, resulting in a blank screen—the effect you would want for a full-screen game application.


As another example, you could use the following code to test for a mouse:

if (GetSystemMetrics(SM_MOUSEPRESENT))
   {
   // there's a mouse
   } // end if
else
   {
   // no mouse
   } // end else

Finally, when you're drawing text, you might want to know about the font that GDI is using—for example, how wide each character is and other related metrics. If you write some code to draw text and you know the font, you can position the text with some reasonable accuracy. The name of the function that retrieves text metrics is called GetTextMetrics():

BOOL GetTextMetrics(HDC hdc,  // handle of device context
   LPTEXTMETRIC lptm ); // address of text metrics structure

You may be wondering why the hdc is needed—it's because you may have multiple dc's with different fonts selected, so you have to tell the function which one to compute the metrics on. Smart little function! Anyway, lptm is a pointer to a TEXTMETRIC structure that is filled with the information. It looks like this:

typedef struct tagTEXTMETRIC {
  LONG tmHeight;          // the height of the font
  LONG tmAscent;          // the ascent of the font
  LONG tmDescent;         // the descent of the font
  LONG tmInternalLeading; // the internal leading
  LONG tmExternalLeading; // the external leading
  LONG tmAveCharWidth;  // the average width
  LONG tmMaxCharWidth;  // the maximum width
  LONG tmWeight;          // the weight of the font
  LONG tmOverhang;        // the overhang of the font
  LONG tmDigitizedAspectX; // the designed for x-aspect
  LONG tmDigitizedAspectY; // the designed for y-aspect
  BCHAR tmFirstChar;   // first character font defines
  BCHAR tmLastChar;    // last character font defines
  BCHAR tmDefaultChar; // char used when desired not in set
  BCHAR tmBreakChar;   // the break character
  BYTE tmItalic;       // is this an italic font
  BYTE tmUnderlined;   // is this an underlined font
  BYTE tmStruckOut;    // is this a strikeout font
  BYTE tmPitchAndFamily; //family and tech,truetype..
  BYTE tmCharSet;        // what is the character set
} TEXTMETRIC;

Because most of us haven't worked with a printing press our whole lives, a number of these fields are meaningless, but I have highlighted the ones that should make some sense. Take a look at the following list of terms and refer to Figure 4.13; it might help with some of the terminology.

Figure 4.13. The makeup of a character.

graphics/04fig13.gif

  • Height— This is the total height in pixels of the character.

  • Baseline— This is a reference point, usually the bottom of an uppercase character.

  • Ascen— This is the number of pixels from the baseline to the top of where an accent mark might be.

  • Descen— This is the number of pixels from the baseline to the bottom of lower case extensions.

  • Internal leadin— This is the number of pixels to allow for accent marks.

  • External leadin— This is the number of pixels to allow for other characters above the character, so they don't run on top of each other.

Here's an example of how you would center some text:

TEXTMETRIC tm; // holds the textmetric data

// get the textmetrics
GetTextMetrics(hdc,&tm);

// used tm data to center a string given the horizontal width
// assume width of window is WINDOW_WIDTH
int x_pos = WINDOW_WIDTH -
    strlen("Center This String")*tm.tmAveCharWidth/2;

// print the text at the centered position
TextOut(hdc,x_pos,0,"Center This String",
        strlen("Center This String"));

No matter what the font size is, this code will always center it.

      Previous Section Next Section
    



    JavaScript EditorAjax Editor     JavaScript Editor