Tutorial 2: Win32 - More than
graphics...
by bkenwright@xbdev.net
Text - "Hello Window"
You look at your window, and its not just pretty lines and pictures....
there's writing as well...different sizes and all over the place.. Which
leads us to "FONTS"....yup creating text out. Its not as hard as you might
think...once you get past the how...its will become second nature eventually.
To splash some text on our screen.....be it our window or the desktop...or
any window...all we need is the Handle to the DC...e.g. HDC...which we can get
using the API, GetDC(..) like this:
hdc =
GetDC(hWnd);
... its pretty simple once you have the dc.
DownloadSourceCode
The simple demo will show you how easy it is to add text output to your
simple Win32 application.... we'll use the default Font first, which is the
font that is currently in the HDC, whatever it might be...and we'll render
our mouse position to the window, as you can see from the screen shot on the
right. |
|
// This is our Call Back procedure, where you would put your code...this
gets
// called repeatedly from our windows messaging loop.
LRESULT
CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch(iMessage)
{
case WM_MOUSEMOVE:
{
// NEW ** NEW ** NEW ** NEW **
NEW ** NEW ** NEW ** NEW ** NEW **
HDC hDC = GetDC(hWnd);
int xp = LOWORD(lParam);
int yp = HIWORD(lParam);
// Use the default Font to
display our mouse position on screen
char buf[200];
// Temp text buffer
sprintf(buf, "xpos:%d, ypos:%d", xp, yp);
// +--- HDC, which is our
screen drawing canvas
// | +---+-- x and y
position..where 0,0 is the top left
// | | | +--- Our
string of char's
// | | | |
+------The number of characters to display
// \|/ \|/ \|/ \|/ \|/
// | | | | |
TextOut(hDC, 5, 5, buf, strlen(buf));
ReleaseDC(hWnd, hDC);
}
break;
case WM_CLOSE:
if(MessageBox(hWnd, "Leave? Quit
the our mini window?", "Message", MB_YESNO) == IDYES)
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,
iMessage, wParam, lParam);
}
return 0;
} |
But we'll want to use our own font eventually...maybe arial 10...or time
roman....who knows.. Which will bring us the the CreateFont(..) API, which
is one of the biggest you'll ever come across.....not because its so
powerful...but because it takes so many parameters which you pass to it.
Most of the time you'll just select default values for most
of the parameters shown for the CreateFont(..) API, as you can see below in
our demo, you can create massive fonts.... or italics etc.
Usually you end up making a wrapper function...something called "void
CreateMyFont(..)" which only takes parameters that you think would be
useful. Like font size and type of font.
Once you've used it once or twice you'll soon get the hand of it. |
/* Details for CreateFont(..) from the ms docs.
HFONT CreateFont(
int nHeight, // height of font
int nWidth, // average character width
int nEscapement, // angle of escapement
int nOrientation, // base-line orientation angle
int fnWeight, // font weight
DWORD fdwItalic, // italic attribute option
DWORD fdwUnderline, // underline attribute option
DWORD fdwStrikeOut, // strikeout attribute option
DWORD fdwCharSet, // character set identifier
DWORD fdwOutputPrecision, // output precision
DWORD fdwClipPrecision, // clipping precision
DWORD fdwQuality, // output quality
DWORD fdwPitchAndFamily, // pitch and family
LPCTSTR lpszFace // typeface name
);
*/ |
· That the first parameter is the height can be quite useful to know. A 0
here means "I don't care what the stupid height is just give me the font and
give it now, please" or something like that.
· The next parm is the width, pretty much the same can be said about the width
as I said about the height.
· The next two parameters are called Escapement and Orientation, I mention these
together since for Win95/98 you should set these two to the same value (this is
not the case for WinNT). They want the angle in tenths of degrees that the
textbase should be rotated, 0 here will cause normal text.
· The next parm is the weight, this is the place you specify baldness...no, no
your boldness...ahm, the boldness of the font. Here FW_DONTCARE means "I don't
care what the stupid weight is just give me the font and give it now, please"
and FW_THIN will mean a really, really thin font. FW_NORMAL will mean the same
as FW_REGULAR. FW_BOLD means that the text will be bold, FW_ULTRABOLD means that
you want something more than just bold, you want ultrabold (sorry html only
allows me to make one type of bold). Finally if nothing else helps, you've got
FW_BLACK which is the super-ultra-mega bold or
so-bold-you-can't-get-any-bolder-and-still-be-bold type of bold, if you know
what I mean...(blink, blink)? Yep, that kind of bold!
· The next parm is a boolean you set to true if you want italic text-style.
· The next parm is also a boolean and you set it to true for underlined texts.
· Further on the next parm is set to true for strikeout text-style.
· In the next parm you specify the character set you want to use (ANSI, Chineese),
I prefer DEFAULT_CHARSET and so does the docs.
· The next parm is another non-care, it specifies how close the chosen font must
match the specifications given. Use OUT_DEFAULT_PRECIS for most apps.
· Now comes another boring parm, the clip-precision, use CLIP_DEFAULT_PRECIS or
consult the Win32 docs for more info.
· Yep, there's more, now comes the quality parm. There are only three possible
values: DEFAULT_QUALITY (should be used), DRAFT_QUALITY (less quality),
PROOF_QUALITY (more quality). I won't explain the ins and outs of the different
qualities, if you want to know consult the Win32 docs. Ok, we're almost there,
just two more parms (by now you must have understood why I chosed to create the
function MyCreateFont()).
· Ok the first of the two are called pitch and family. In this the two low-order
bits defines the pitch, which can be: DEFAULT_PITCH (the easy way out ;-),
FIXED_PITCH and VARIABLE_PITCH. Then the four high-order bits should be one of
the following: FF_DECORATIVE, FF_DONTCARE (this is what I use), FF_MODERN,
FF_ROMAN, FF_SCRIPT or FF_SWISS. Try to use different families to see what the
effects are. However the pitch and family are or:ed together, ex: DEFAULT_PITCH
| FF_DONTCARE.
· And finally, the last parm is a string that can contain the name of a font you
want, ex. "New Times Roman" or something like that, it can of course be NULL and
then Windows choses font for you.
If you change something, always put it back to the way you found it! A
rule of thumb for windows programmers. As when we get the Handle to a DC,
if we select a new object into it, well when we've finished with it, we put the
old object back before releasing it. Else if you don't, this can lead to
mini memory leaks which are horrible to track down.... so be a good coder and
save the object your returned when you use "SelectObject(..)" with your new
font.
DownloadSourceCode
A larger font... and we can specify the width..height...italic's
etc...all using our new CreateFont(..) API. |
|
LRESULT
CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch(iMessage)
{
case WM_MOUSEMOVE:
{
HDC hDC = GetDC(hWnd);
int xp = LOWORD(lParam);
int yp = HIWORD(lParam);
// Use the default Font to
display our mouse position on screen
char buf[200];
// Temp text buffer
sprintf(buf, "xpos:%d, ypos:%d", xp, yp);
// NEW ** NEW ** NEW ** NEW **
NEW ** NEW ** NEW ** NEW ** NEW **
HGDIOBJ hObj;
int iWeight = 2;
DWORD dwItalic = 0; // 1 for
italic/ 0 for no itallic
// Create our font! This is
where the magic happens :)
HFONT hNewFont = CreateFont(25, 12, 0, 0, iWeight,
dwItalic, FALSE, FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
NULL);
// Select our new font into our
DC so we can use it.
hObj = SelectObject(hDC, hNewFont);
// +--- HDC, which is our
screen drawing canvas
// | +---+-- x and y
position..where 0,0 is the top left
// | | | +--- Our
string of char's
// | | | |
+------The number of characters to display
// \|/ \|/ \|/ \|/ \|/
// | | | | |
TextOut(hDC, 5, 5, buf, strlen(buf));
SelectObject(hDC, hObj); //
Select our old object back into hDC - always leave
// it
the way you found it as they say.
ReleaseDC(hWnd, hDC);
// NEW ** NEW ** NEW ** NEW **
NEW ** NEW ** NEW ** NEW ** NEW **
DeleteObject(hNewFont);
}
break;
case WM_CLOSE:
if(MessageBox(hWnd, "Leave? Quit
the our mini window?", "Message", MB_YESNO) == IDYES)
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,
iMessage, wParam, lParam);
}
return 0;
} |
You can draw lines....set pixels on the screen with "SetPixel(..)" API...and
even do fancy fonts. Its amazing how easy it is. Remember windows is
your friend..its designed to make things easy for you.
|