One of the first things that you need to know when working with fonts is that not every system that your applications run on will have the same fonts installed. Fonts are specified in files that can be installed and removed from Windows systems with relative ease. Every computer user can customize his system with whatever combination of fonts he wants. If you specify a font that doesn't exist on the system, Windows will choose either the system default font or what the operating system considers to be a reasonably close alternative font.
What you can do instead is ask the operating system what fonts are available. This method allows you to make your own decisions on which font to use or let the user make the decision. When you ask what fonts are available, you can limit the types of fonts that are listed, or you can choose to list them all and select various fonts based on various attributes.
To get a list of all available fonts on a computer, you call a Windows API (Application Programming Interface) function called EnumFontFamiliesEx. This function tells Windows that you want a list of the fonts on the system. Before you start using this function and expecting it to pass you a big list of available fonts, you need to understand how it gives you the list.
One of the key arguments to the EnumFontFamiliesEx function is the address of another function. This second function is what is known as a callback function, which is called by the operating system. For almost every enumeration function in the Windows operating system, you pass the address of a callback function as an argument because the callback function is called once for each of the elements in the enumerated list. In other words, you have to include a function in your application to receive each individual font that is on the system and then build the list of fonts yourself.
When you create this function to receive each font and build your list, you cannot define your callback function in any way you want. All callback functions are already defined in the Windows API. You have to use a specific type of callback function to receive the list of fonts. For getting a list of fonts, the function type is EnumFontFamProc. This function type specifies how your function must be defined, what its arguments must be, and what type of return value it must return. It does not specify what your function should be named or how it needs to work internally. These aspects are left completely up to you.
The EnumFontFamiliesEx function, which you call to request the list of available fonts, takes five arguments. A typical use of this function follows:
// Create a device context variable CClientDC dc (this); // Declare a LOGFONT structure LOGFONT lLogFont; // Specify the character set lLogFont.lfCharSet = DEFAULT_CHARSET; // Specify all fonts lLogFont.lfFaceName[0] = NULL; // Must be zero unless Hebrew or Arabic lLogFont.lfPitchAndFamily = 0; // Enumerate the font families ::EnumFontFamiliesEx((HDC) dc, &lLogFont, (FONTENUMPROC) EnumFontFamProc, (LPARAM) this, 0);
The first argument is a device context, which can be an instance of the CClientDC class. Every application running within the Windows operating system has a device context. The device context provides a lot of necessary information to the operating system about what is available to the application and what is not.
The second argument is a pointer to a LOGFONT structure. This structure contains information about the fonts that you want listed. You can specify in this structure which character set you want to list or whether you want all the fonts in a particular font family. If you want all the fonts on the system, you pass NULL in the place of this argument.
The third argument is the address of the callback function that will be used to build your list of fonts. Passing the address of your callback function is a simple matter of using the function name as the argument. The Visual C++ compiler takes care of replacing the function name with the function address. However, you do need to cast the function as the type of callback function that the function requires.
The fourth argument is a LPARAM value that will be passed to the callback function. This parameter is not used by Windows but provides your callback function with a context in which to build the font list. In the example, the value being passed is a pointer to the window in which the code is being run. This way, the callback function can use this pointer to access any structures it needs to build the list of fonts. This pointer can also be the first node in a linked list of fonts or other such structure.
The fifth and final argument is always 0. This reserved argument may be used in future versions of Windows, but for now, it must be 0 so that your application passes a value that won't cause the function to misbehave.
When you create your callback function, it must be defined as an independent function, not as a member of any C++ class. A typical EnumFontFamProc function declaration follows:
int CALLBACK EnumFontFamProc( LPENUMLOGFONT lpelf, LPNEWTEXTMETRIC lpntm, DWORD nFontType, long lParam) { // Create a pointer to the dialog window CMyDlg* pWnd = (CMyDlg*) lParam; // Add the font name to the list box pWnd->m_ctlFontList.AddString(lpelf->elfLogFont.lfFaceName); // Return 1 to continue font enumeration return 1; }
The first argument to this function is a pointer to an ENUMLOGFONTEX structure. This structure contains information about the logical attributes of the font, including the font name, style, and script. You may have numerous fonts listed with the same name but different styles. You can have one for normal, one for bold, one for italic, and one for bold italic.
The second argument is a pointer to a NEWTEXTMETRICEX structure. This structure contains information about the physical attributes of the font, such as height, width, and space around the font. These values are all relative in nature because they need to scale as the font is made larger or smaller.
The third argument is a flag that specifies the type of font. This value may contain a combination of the following values:
Finally, the fourth argument is the value that was passed into the EnumFontFamiliesEx function. In the example, it was a pointer to the dialog on which the list of fonts is being built. If you cast this value as a pointer to the dialog, the function can access a list box control to add the font names.
The return value from this function determines whether the listing of fonts continues. If 0 is returned from this function, the operating system quits listing the available fonts. If 1 is returned, the operating system continues to list the available fonts.
To use a particular font in an application, you call an instance of the CFont class. By calling the CreateFont method, you can specify the font to be used, along with the size, style, and orientation. Once you've created a font, you can tell a control or window to use the font by calling the object's SetFont method. An example of this process follows:
CFont m_fFont; // The font to be used // Create the font to be used m_fFont.CreateFont(12, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, m_sFontName); // Set the font for the display area m_ctlDisplayText.SetFont(&m_fFont);
TIP: The CFont variable used in the previous code should be declared as a member variable of the class in which this code is placed. In the sample code, it is declared above where it is used to show how it is declared. This variable should not be declared or used as a local variable in a function.
Seems simple enough--just two function calls--but that CreateFont function needs an awful lot of arguments passed to it. It is these arguments that make the CreateFont method a flexible function with a large amount of functionality. Once you create the font, using it is a simple matter of passing the font to the SetFont method, which is a member of the CWnd class and thus available to all window and control classes in Visual C++. This means that you can use this technique on any visible object within a Visual C++ application.
To understand how the CreateFont function works, let's look at the individual arguments that you have to pass to it. The function is defined as
BOOL CreateFont( int nHeight, int nWidth, int nEscapement, int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, LPCTSTR lpszFaceName);
The first of these arguments, nHeight, specifies the height of the font to be used. This logical value is translated into a physical value. If the value is 0, a reasonable default value is used. If the value is greater or less than 0, the absolute height is converted into device units. It is key to understand that height values of 10 and -10 are basically the same.
The second argument, nWidth, specifies the average width of the characters in the font. This logical value is translated into a physical value in much the same way as the height is.
The third argument, nEscapement, determines the angle at which the text will be printed. This value is specified in 0.1-degree units in a counterclockwise pattern. If you want to print vertical text that reads from bottom to top, you supply 900 as the value for this argument. For printing normal horizontal text that flows from left to right, supply 0 as this value.
The fourth argument, nOrientation, determines the angle of each individual character in the font. This works on the same basis as the previous argument, but it controls the output on a character basis, not a line-of-text basis. To print upside-down characters, set this value to 1800. To print characters on their backs, set this value to 900.
The fifth argument, nWeight, specifies the weight, or boldness, of the font. This can be any value from 0 to 1000, with 1000 being heavily bolded. You can use constants defined for this argument to control this value with ease and consistency. These constants are listed in Table 7.1.
Constant | Value |
FW_DONTCARE | 0 |
FW_THIN | 100 |
FW_EXTRALIGHT | 200 |
FW_ULTRALIGHT | 200 |
FW_LIGHT | 300 |
FW_NORMAL | 400 |
FW_REGULAR | 400 |
FW_MEDIUM | 500 |
Constant | Value |
FW_SEMIBOLD | 600 |
FW_DEMIBOLD | 600 |
FW_BOLD | 700 |
FW_EXTRABOLD | 800 |
FW_ULTRABOLD | 800 |
FW_BLACK | 900 |
FW_HEAVY | 900 |
The actual interpretation and availability of these weights depend on the font. Some fonts only have FW_NORMAL, FW_REGULAR, and FW_BOLD weights. If you specify FW_DONTCARE, a default weight is used, just as with most of the rest of the arguments.
The sixth argument, bItalic, specifies whether the font is to be italicized. This is a boolean value; 0 indicates that the font is not italicized, and any other value indicates that the font is italicized.
The seventh argument, bUnderline, specifies whether the font is to be underlined. This is also a boolean value; 0 indicates that the font is not underlined, and any other value indicates that the font is underlined.
The eighth argument, cStrikeOut, specifies whether the characters in the font are displayed with a line through the character. This is another boolean value using a non-zero value as TRUE and 0 as FALSE.
The ninth argument, nCharSet, specifies the font's character set. The available constants for this value are listed in Table 7.2.
Constant | Value |
ANSI_CHARSET | 0 |
DEFAULT_CHARSET | 1 |
SYMBOL_CHARSET | 2 |
SHIFTJIS_CHARSET | 128 |
OEM_CHARSET | 255 |
The system on which your application is running might have other character sets, and the OEM character set is system dependent, making it different for systems from different manufacturers. If you are using one of these character sets, it is risky to try to manipulate the strings to be output, so it's best to just pass along the string to be displayed.
The tenth argument, nOutPrecision, specifies how closely the output must match the requested font's height, width, character orientation, escapement, and pitch. The available values for this argument are
The OUT_DEVICE_PRECIS, OUT_RASTER_PRECIS, and OUT_TT_PRECIS values control which font is chosen if there are multiple fonts with the same name. For instance, if you use the OUT_TT_PRECIS value and specify a font with both a TrueType and raster version, then the TrueType version is used. In fact, the OUT_TT_PRECIS value forces the system to use a TrueType font, even when the specified font does not have a TrueType version.
The eleventh argument, nClipPrecision, specifies how to clip characters that are partially outside of the display area. The values for this argument are
These values can be ORed together to specify a combination of clipping techniques.
The twelfth argument, nQuality, specifies the output quality and how carefully the GDI (Graphics Device Interface) must attempt to match the logical font attributes to the physical font output. The available values for this argument are
The thirteenth argument, nPitchAndFamily, specifies the pitch and family of the font. This value consists of two values that are ORed together to create a combination value. The first set of available values is
This value specifies the pitch to be used with the font. The second set of available values specifies the family of fonts to be used. The available values for this portion of the argument are
The font family describes in a general way the appearance of a font. You can use the font family value to choose an alternative font when a specific font does not exist on a system. The final argument, lpszFacename, is a standard C-style string that contains the name of the font to be used. This font name comes from the font information received by the EnumFontFamProc callback function.
Today you will build an application that allows the user to select from a list of available fonts to be displayed. The user will be able to enter some text to be displayed in the selected font, allowing the user to see what the font looks like.
To begin today's application, follow these steps:
FIGURE 7.1. The main dialog layout.
Object | Property | Setting |
Static Text | ID | IDC_STATIC |
|
Caption | &Enter Some Text: |
Edit Box | ID | IDC_ESAMPTEXT |
Static Text | ID | IDC_STATIC |
|
Caption | &Select a Font |
List Box | ID | IDC_LFONTS |
Group Box | ID | IDC_STATIC |
|
Caption | Font Sample |
Static Text | ID | IDC_DISPLAYTEXT |
(inside group box; size to | Caption | Empty string |
fill the group box) |
|
|
Command Button | ID | IDC_EXIT |
|
Caption | E&xit |
Object | Name | Category | Type |
IDC_DISPLAYTEXT | m_ctlDisplayText | Control | CStatic |
|
m_strDisplayText | Value | CString |
IDC_LFONTS | m_ctlFontList | Control | CListBox |
|
m_strFontName | Value | CString |
IDC_ESAMPTEXT | m_strSampText | Value | CString |
To be able to create your list of fonts, you need to add your callback function to get each font list and add it to the list box that you placed on the dialog window. To do this, edit the Day7Dlg.h header file and add the function declaration in Listing 7.1 near the top of the file. This function cannot be added through any of the tools available in Visual C++. You need to open the file and add it yourself.
1: #if _MSC_VER > 1000 2: #pragma once 3: #endif // _MSC_VER > 1000 4: 5: int CALLBACK EnumFontFamProc(LPENUMLOGFONT lpelf, 6: LPNEWTEXTMETRIC lpntm, DWORD nFontType, long lParam); 7: 8: //////////////////////////////////////////////////////////////////// 9: // CDay7Dlg dialog 10: 11: class CDay7Dlg : public CDialog 12: . 13: .
14: .
Once you add the function declaration to the header file, open the Day7Dlg.cpp source-code file, scroll to the bottom of the file, and add the function definition in Listing 7.2.
1: int CALLBACK EnumFontFamProc(LPENUMLOGFONT lpelf, 2: LPNEWTEXTMETRIC lpntm, DWORD nFontType, long lParam) 3: { 4: // Create a pointer to the dialog window 5: CDay7Dlg* pWnd = (CDay7Dlg*) lParam; 6: 7: // Add the font name to the list box 8: pWnd->m_ctlFontList.AddString(lpelf->elfLogFont.lfFaceName); 9: // Return 1 to continue font enumeration 10: return 1; 11: }
Now that you have the callback function defined, you need to add a function to request the list of fonts from the operating system. To add this function, follow these steps:
1: void CDay7Dlg::FillFontList() 2: { 3: LOGFONT lf; 4: 5: // Initialize the LOGFONT structure 6: lf.lfCharSet = DEFAULT_CHARSET; 7: strcpy(lf.lfFaceName, ""); 8: // Clear the list box 9: m_ctlFontList.ResetContent(); 10: // Create a device context variable 11: CClientDC dc (this); 12: // Enumerate the font families 13: ::EnumFontFamiliesEx((HDC) dc, &lf, 14: (FONTENUMPROC) EnumFontFamProc, (LPARAM) this, 0); 15: }
1: BOOL CDay7Dlg::OnInitDialog() 2: { 3: CDialog::OnInitDialog(); 4: . 5: . 6: . 7: // TODO: Add extra initialization here 8: 9: /////////////////////// 10: // MY CODE STARTS HERE 11: /////////////////////// 12: 13: // Fill the font list box 14: FillFontList(); 15: 16: /////////////////////// 17: // MY CODE ENDS HERE 18: /////////////////////// 19: 20: return TRUE; // return TRUE unless you set the focus to a control 21: }
If you compile and run your application now, you should find that your list box is filled with the names of all the fonts available on the system. However, there's one aspect of this list that you probably don't want in your application. Figure 7.2 shows many duplicate entries in the list of fonts in the list box. It would be nice if you could eliminate these duplicates and have only one line per font.
FIGURE 7.2. Listing all the fonts in the system.
It turns out that the EnumFontFamiliesEx function call is synchronous in nature. This means that it doesn't return until all the fonts in the system are listed in calls to your callback function. You can place code in the FillFontList function to remove all the duplicate entries once the list box is filled. To do this, modify the FillFontList function as in Listing 7.5.
Listing 7.5. The modified FILLFONTLIST function.
1: void CDay7Dlg::FillFontList() 2: { 3: int iCount; // The number of fonts 4: int iCurCount; // The current font 5: CString strCurFont; // The current font name 6: CString strPrevFont = ""; // The previous font name 7: LOGFONT lf; 8: 9: // Initialize the LOGFONT structure 10: lf.lfCharSet = DEFAULT_CHARSET; 11: strcpy(lf.lfFaceName, ""); 12: // Clear the list box 13: m_ctlFontList.ResetContent(); 14: // Create a device context variable 15: CClientDC dc (this); 16: // Enumerate the font families 17: ::EnumFontFamiliesEx((HDC) dc, &lf, 18: (FONTENUMPROC) EnumFontFamProc, (LPARAM) this, 0); 19: // Get the number of fonts in the list box 20: iCount = m_ctlFontList.GetCount(); 21: // Loop from the last entry in the list box to the first, 22: // searching for and deleting the duplicate entries 23: for (iCurCount = iCount; iCurCount > 0; iCurCount--) 24: { 25: // Get the current font name 26: m_ctlFontList.GetText((iCurCount - 1), strCurFont); 27: // Is it the same as the previous font name? 28: if (strCurFont == strPrevFont) 29: { 30: // If yes, then delete it 31: m_ctlFontList.DeleteString((iCurCount - 1)); 32: } 33: // Set the previous font name to the current font name 34: strPrevFont = strCurFont; 35: } 36: }
Notice that the for loop started at the end of the list and worked backward. This allowed you to delete the current entry without worrying about manipulating the loop counter to prevent skipping lines in the list box. If you compile and run your application, there shouldn't be any duplicate entries in the list of available fonts.
Before you can display the font for the user, you need to place some text into the display area. The edit box near the top of the dialog is where the user enters text to be displayed in the font selected. To add the functionality, do the following:
1: BOOL CDay7Dlg::OnInitDialog() 2: { 3: CDialog::OnInitDialog(); 4: . 5: . 6: . 7: // TODO: Add extra initialization here 8: 9: /////////////////////// 10: // MY CODE STARTS HERE 11: /////////////////////// 12: 13: // Fill the font list box 14: FillFontList(); 15: 16: // Initialize the text to be entered 17: m_strSampText = "Testing"; 18: // Copy the text to the font sample area 19: m_strDisplayText = m_strSampText; 20: // Update the dialog 21: UpdateData(FALSE); 22: 23: /////////////////////// 24: // MY CODE ENDS HERE 25: /////////////////////// 26: 27: return TRUE; // return TRUE unless you set the focus to a control 28: }
1: void CDay7Dlg::OnChangeEsamptext()
2: { 3: // TODO: If this is a RICHEDIT control, the control will not 4: // send this notification unless you override the ÂCDialog::OnInitialUpdate() 5: // function and call CRichEditCrtl().SetEventMask() 6: // with the EN_CHANGE flag ORed into the mask. 7: 8: // TODO: Add your control notification handler code here 9: 10: /////////////////////// 11: // MY CODE STARTS HERE 12: /////////////////////// 13: 14: // Update the variables with the dialog controls 15: UpdateData(TRUE); 16: 17: // Copy the current text to the font sample 18: m_strDisplayText = m_strSampText; 19: 20: // Update the dialog with the variables 21: UpdateData(FALSE); 22: 23: /////////////////////// 24: // MY CODE ENDS HERE 25: /////////////////////// 26: }
If you compile and run your application, you should be able to type text into the edit box and see it change in the font display area in the group box below.
Before you can start changing the font for the display area, you'll need to have a CFont member variable of the dialog class that you can use to set and change the display font. To add this variable, follow these steps:
When adding the code to use the selected font, you'll add it as a separate function that is not attached to a control. Why you do this will become clear as you proceed further through building and running today's application. To add the function to display and use the selected font, follow these steps:
1: void CDay7Dlg::SetMyFont() 2: { 3: CRect rRect; // The rectangle of the display area 4: int iHeight; // The height of the display area 5: 6: // Has a font been selected? 7: if (m_strFontName != "") 8: { 9: // Get the dimensions of the font sample display area 10: m_ctlDisplayText.GetWindowRect(&rRect); 11: // Calculate the area height 12: iHeight = rRect.top - rRect.bottom; 13: // Make sure the height is positive 14: if (iHeight < 0) 15: iHeight = 0 - iHeight; 16: // Release the current font 17: m_fSampFont.Detach(); 18: // Create the font to be used 19: m_fSampFont.CreateFont((iHeight - 5), 0, 0, 0, FW_NORMAL, 20: 0, 0, 0, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, 21: CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | 22: FF_DONTCARE, m_strFontName); 23: 24: // Set the font for the sample display area 25: m_ctlDisplayText.SetFont(&m_fSampFont); 26: } 27: }
1: void CDay7Dlg::OnSelchangeLfonts() 2: { 3: // TODO: Add your control notification handler code here 4: 5: /////////////////////// 6: // MY CODE STARTS HERE
7: ///////////////////////
8: 9: // Update the variables with the dialog controls 10: UpdateData(TRUE); 11: 12: // Set the font for the sample 13: SetMyFont(); 14: 15: /////////////////////// 16: // MY CODE ENDS HERE 17: /////////////////////// 18: }
In the SetMyFont function, you first checked to make sure that a font had been selected. Next, you retrieved the area of the static text control that will be used to display the font. This enables you to specify a font height just slightly smaller than the height of the area you have available to display the font in. After you calculated the height of the static text control and made sure that it is a positive value, you created the selected font and told the static text control to use the newly created font.
In the OnSelchangeLfonts function, you copy the control values to the attached variables and then call the SetMyFont function to use the selected font. If you compile and run your application, you should be able to select a font and see it displayed in the sample static text control, as in Figure 7.3.
FIGURE 7.3. Displaying the selected font.
Today you learned how to use fonts in Visual C++ applications. You learned how to get a list of the available fonts that are loaded on the system and then how to create a font for use on a display object. You learned how you can create and use callback functions to get a list of resources from the Windows operating system. You also learned how you can access controls from the callback function using a window pointer that you passed to the function requesting the resource list.
1: void CDay7Dlg::SetMyFont() 2: { 3: 4: // Has a font been selected? 5: if (m_strFontName != "") 6: { 7: // Assume that the font size has already been initialized in the 8: // m_lLogFont structure. This allows you to only have to specify 9: // the font name. 10: tcscpy(m_lLogFont.lfFaceName, m_strFontName); 11: // Create the font to be used 12: m_fSampFont.CreateFontIndirect(&m_lLogFont); 13: 14: // Set the font for the sample display area 15: m_ctlDisplayText.SetFont(&m_fSampFont); 16: } 17: }
int CALLBACK EnumFontFamProc(LPENUMLOGFONT lpelf, LPNEWTEXTMETRIC lpntm, DWORD nFontType, long lParam) { // Create a pointer to the dialog window CDay7Dlg* pWnd = (CDay7Dlg*) lParam; // Limit the list to TrueType fonts if ((nFontType & TRUETYPE_FONTTYPE) == TRUETYPE_FONTTYPE) { // Add the font name to the list box pWnd->m_ctlFontList.AddString( lpelf->elfLogFont.lfFaceName); } // Return 1 to continue font enumeration return 1; }
The Workshop provides quiz questions to help you solidify your understanding of the material covered and exercises to provide you with experience in using what you've learned. The answers to the quiz questions and exercises are provided in Appendix B, "Answers."
FIGURE 7.4. Displaying the selected font with the font name.
FIGURE 7.5. Displaying the selected font in italics.
Well, you've made it through the first week. By this point, you've gotten a good taste for what's possible when building applications with Visual C++. Now it's time to look back over what's been covered and what you should have learned up to this point.
What you might want to do at this point, to cement your understanding of how you can use these elements in your own applications, is to try designing and building a couple of simple applications of your own. You can use a variety of controls and add some additional dialogs, just so you can make sure that you do understand and are comfortable with these topics. In fact, you might want to try out all the topics that I've covered up to this point in small applications of your own design. That's the true test of your understanding of how the concepts work. You might also want to dive into the MFC documentation to learn a little about some of the more advanced functionality that I haven't covered to see if you can figure out how you can use and incorporate it into your applications.
One of the most important things that you should understand at this point is how you can use controls and dialog windows in your applications to get and display information to the user. This is an important part of any Windows application because just about every application interacts with the user in some way. You should be able to place any of the standard controls on a dialog in your application and be able to incorporate them into your application without any problem. Likewise, you should be comfortable with using the standard message box and dialog windows provided to your application by the Windows operating system. You should also be able to create and incorporate your own custom dialog windows into any application you might want to build. If you don't feel comfortable with any of these topics, you might want to go back and review Day 2 to get a better understanding of how you can use controls and Day 5 to understand how you can incorporate standard and custom dialog windows into your applications.
Another key skill that you will be using in the majority of your applications is the ability to build and incorporate menus into your applications. You need to have a firm understanding of how to design a good menu, how to make sure that there are no conflicting mnemonics, and how you can attach application functionality to the menu selections. At this point, you should be able to create your own customized menus, with entries for each of the various functions that your application performs, and integrate it with your application with no problems. If you aren't 100% comfortable with this topic, you might want to go back and study Day 6 a little more.
You will find that there are various situations in which you need to have some means of triggering actions on a regular basis or in which you need to keep track of how long some process has been running. For both of these situations, as well as numerous others, you'll often find yourself turning to the use of timers in your application. If you are even slightly foggy on how you can integrate timers into your applications, you will definitely want to go back and review Day 4.
Understanding how you can use text and fonts in your applications will allow you to build more flexibility into the appearance of your applications--to give your users the ability to customize the appearance as they want. You will be able to examine the available fonts on the computer on which your application is running and, if a font that you want to use in your application isn't available, choose another font that is close to use instead. If you still have any questions on how the font infrastructure in Windows works and how you can use it in your applications, you'll want to go back and review Day 7 once more.
Depending on the nature of your application, being able to capture and track mouse and keyboard actions by the user can be very important. If you are building a drawing application, this is crucial information. If you are building an application that needs to include drag-and-drop capabilities, this is important once again. There are any number of situations in which you'll want to include this functionality into your applications. By this point, you should understand how you can capture the various mouse events and determine which mouse buttons are involved in the event. You should also be able to capture keyboard events in situations where the keyboard input isn't captured by any controls that are on the window. If you don't feel like you have a complete grasp of this, you should take another look at Day 3.
Finally, you should be familiar with the Visual C++ development environment, the Developer Studio. You should have a good understanding of what each area of the environment is for and how you can use the various tools and utilities in building your applications. You should be comfortable with using the workspace pane to navigate around your application project, locating and bringing into the various editors and designers any part of your application. You should be comfortable with locating and redesigning the icon that will be displayed to represent your application and with finding any member functions or variables in any of your application's classes.
By now you should be getting fairly comfortable working with Visual C++. If you feel like you understand all the topics that I've covered so far, you are ready to continue forward, learning more about the various things that you can do, and functionality that you can build, using Visual C++ as your programming tool. With that said, it's on to the second week...
© Copyright, Macmillan Computer Publishing. All rights reserved.