Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateCC sharp
CalculatoareCorel drawDot netExcelFox proFrontpageHardware
HtmlInternetJavaLinuxMatlabMs dosPascal
PhpPower pointRetele calculatoareSqlTutorialsWebdesignWindows
WordXml

AspAutocadCDot netExcelFox proHtmlJava
LinuxMathcadPhotoshopPhpSqlVisual studioWindowsXml

The Visual C++ Development Environment

c



+ Font mai mare | - Font mai mic



The Visual C++ Development Environment

* The Output Pane



* The Editor Area

* Menu Bars

* Rearranging the Developer Studio Environment

* Starting Your First Project

* Creating the Project Workspace

* Using the Application Wizard to Create the Application Shell

* Designing Your Application Window

* Adding Code to Your Application

* Finishing Touches

* Creating the Dialog Box Icon

* Adding Maximize and Minimize Buttons

* Summary

* Q&A

* Workshop

* Quiz

* Exercise

Welcome to Sams Teach Yourself Visual C++ 6 in 21 Days. Over the next three weeks, you will learn how to build a wide variety of applications with Microsoft's Visual C++. What's even better is that you will learn how to create these types of applications by actually building them yourself. As you read this book, you will be gaining actual programming experience using Visual C++. So let's get started!

Today, your focus will be on learning about the Visual C++ development environment and some of the tools that it provides for building applications. Although Visual C++ provides more tools than you would probably use in any one application development effort--even more than you could possibly learn to use in a single day--I limit the focus to the primary tools that you will use throughout this book, as well as in just about every application you build with Visual C++. Today, you'll learn about the following:

* The primary areas of the Visual C++ development environment

* The Application Wizard--how you can use it to build the basic infrastructure for your applications

* The Dialog Painter--how you can use it to paint dialog windows, much in the same way that you can build windows with Visual Basic, PowerBuilder, or Delphi

* The Class Wizard--how you can use it to attach functionality to your application windows

The Visual C++ Development Environment

Before you begin your quick tour around the Visual C++ development environment, you should start Visual C++ on your computer so that you can see firsthand how each of the areas are arranged and how you can change and alter that arrangement yourself.

After Developer Studio (the Microsoft Visual development environment) starts, you see a window that looks like Figure 1.1. Each of the areas has a specific purpose in the Developer Studio environment. You can rearrange these areas to customize the Developer Studio environment so that it suits your particular development needs.

The Workspace

When you start Visual C++ for the first time, an area on the left side of Developer Studio looks like it is taking up a lot of real estate and providing little to show for it. This area is known as the workspace, and it is your key to navigating the various pieces and parts of your development projects. The workspace allows you to view the parts of your application in three different ways:

* Class View allows you to navigate and manipulate your source code on a C++ class level.

* Resource View allows you to find and edit each of the various resources in your application, including dialog window designs, icons, and menus.

* File View allows you to view and navigate all the files that make up your appli-cation.

FIGURE 1.1. The Visual C++ opening screen.

The Output Pane

The Output pane might not be visible when you start Visual C++ for the first time. After you compile your first application, it appears at the bottom of the Developer Studio environment and remains open until you choose to close it. The Output pane is where Developer Studio provides any information that it needs to give you; where you see all the compiler progress statements, warnings, and error messages; and where the Visual C++ debugger displays all the variables with their current values as you step through your code. After you close the Output pane, it reopens itself when Visual C++ has any message that it needs to display for you.

The Editor Area

The area on the right side of the Developer Studio environment is the editor area. This is the area where you perform all your editing when using Visual C++, where the code editor windows display when you edit C++ source code, and where the window painter displays when you design a dialog box. The editor area is even where the icon painter displays when you design the icons for use in your applications. The editor area is basically the entire Developer Studio area that is not otherwise occupied by panes, menus, or toolbars.

Menu Bars

The first time you run Visual C++, three toolbars display just below the menu bar. Many other toolbars are available in Visual C++, and you can customize and create your own toolbars to accommodate how you best work. The three toolbars that are initially open are the following:

* The Standard toolbar contains most of the standard tools for opening and saving files, cutting, copying, pasting, and a variety of other commands that you are likely to find useful.

The WizardBar toolbar enables you to perform a number of Class Wizard actions without opening the Class Wizard.

* The Build minibar provides you with the build and run commands that you are most likely to use as you develop and test your applications. The full Build toolbar also lets you switch between multiple build configurations (such as between the Debug and Release build configurations).

Rearranging the Developer Studio Environment

The Developer Studio provides two easy ways to rearrange your development environment. The first is by right-clicking your mouse over the toolbar area. This action opens the pop-up menu shown in Figure 1.2, allowing you to turn on and off various toolbars and panes.

FIGURE 1.2. Toolbar on and off menu.

Another way that you can easily rearrange your development environment is to grab the double bars at the left end of any of the toolbars or panes with the mouse. You can drag the toolbars away from where they are currently docked, making them floating toolbars, as in Figure 1.3. You can drag these toolbars (and panes) to any other edge of the Developer Studio to dock them in a new spot. Even when the toolbars are docked, you can use the double bars to drag the toolbar left and right to place the toolbar where you want it to be located.

FIGURE 1.3. Example of a floating minibar.

NOTE: On the workspace and Output panes, the double bars that you can use to drag the pane around the Developer Studio environment might appear on the top of the pane or on the left side, depending on how and where the pane is docked.

Starting Your First Project

For your first Visual C++ application, you are going to create a simple application that presents the user with two buttons, as in Figure 1.4. The first button will present the user with a simple greeting message, shown in Figure 1.5, and the second button will close the application. In building this application, you will need to do the following things:

1. Create a new project workspace.

2. Use the Application Wizard to create the application framework.

3. Rearrange the dialog that is automatically created by the Application Wizard to resemble how you want the application to look.

4. Add the C++ code to show the greeting to the user.

5. Create a new icon for the application.

FIGURE 1.4. Your first Visual C++ application.

FIGURE 1.5. If the user clicks the first button, a simple greeting is shown.

Creating the Project Workspace

Every application development project needs its own project workspace in Visual C++. The workspace includes the directories where the application source code is kept, as well as the directories where the various build configuration files are located. You can create a new project workspace by following these steps:

1. Select File | New. This opens the New Wizard shown in Figure 1.6.

FIGURE 1.6. The New Wizard.

2. On the Projects tab, select MFC AppWizard (exe).

3. Type a name for your project, such as Hello, in the Project Name field.

4. Click OK. This causes the New Wizard to do two things: create a project directory (specified in the Location field) and then start the AppWizard.

Using the Application Wizard to Create the Application Shell

The AppWizard asks you a series of questions about what type of application you are building and what features and functionality you need. It uses this information to create a shell of an application that you can immediately compile and run. This shell provides you with the basic infrastructure that you need to build your application around. You will see how this works as you follow these steps:

1. In Step 1 of the AppWizard, specify that you want to create a Dialog-based application. Click Next at the bottom of the wizard.

2. In Step 2 of the AppWizard, the wizard asks you about a number of features that you can include in your application. You can uncheck the option for including support for ActiveX controls if you will not be using any ActiveX controls in your application. Because you won't be using any ActiveX controls in today's application, go ahead and uncheck this box.

3. In the field near the bottom of the wizard, delete the project name (Hello) and type in the title that you want to appear in the title bar of the main application window, such as My First Visual C++ Application. Click Next at the bottom of the wizard.

4. In Step 3 of the AppWizard, leave the defaults for including source file comments and using the MFC library as a DLL. Click Next at the bottom of the wizard to proceed to the final AppWizard step.

5. The final step of the AppWizard shows you the C++ classes that the AppWizard will create for your application. Click Finish to let AppWizard generate your application shell.

6. Before AppWizard creates your application shell, it presents you with a list of what it is going to put into the application shell, as shown in Figure 1.7, based on the options you selected when going through the AppWizard. Click OK and AppWizard generates your application.

FIGURE 1.7. The New Project Information screen.

* 7. After the AppWizard generates your application shell, you are returned to the Developer Studio environment. You will notice that the workspace pane now presents you with a tree view of the classes in your application shell, as in Figure 1.8. You might also be presented with the main dialog window in the editor area of the Developer Studio area.

8. Select Build | Build Hello.exe to compile your application.

9. As the Visual C++ compiler builds your application, you see progress and other compiler messages scroll by in the Output pane. After your application is built, the Output pane should display a message telling you that there were no errors or warnings, as in Figure 1.9.

FIGURE 1.8. Your workspace with a tree view of the project's classes.

FIGURE 1.9. The Output pane displays any compiler errors.

10. Select Build | Execute Hello.exe to run your application.

11. Your application presents a dialog with a TODO message and OK and Cancel buttons, as shown in Figure 1.10. You can click either button to close the application.

FIGURE 1.10. The unmodified application shell.

Designing Your Application Window

Now that you have a running application shell, you need to turn your focus to the window layout of your application. Even though the main dialog window may already be available for painting in the editor area, you should still navigate to find the dialog window in the workspace so that you can easily find the window in subsequent develop-ment efforts. To redesign the layout of your application dialog, follow these steps:

1. Select the Resource View tab in the workspace pane, as in Figure 1.11.

FIGURE 1.11. The Resource View tab in the workspace pane.

2. Expand the resources tree to display the available dialogs. At this point, you can double-click the IDD_DAY1_DIALOG dialog to open the window in the Developer Studio editor area.

3. Select the text displayed in the dialog and delete it using the Delete key.

4. Select the Cancel button, drag it down to the bottom of the dialog, and resize it so that it is the full width of the layout area of the window, as in Figure 1.12.

FIGURE 1.12. Positioning the Cancel button.

5. Right-click the mouse over the Cancel button, opening the pop-up menu in Figure 1.13. Select Properties from the menu, and the properties dialog in Figure 1.14 opens.

FIGURE 1.13. Right-clicking the mouse to open a pop-up menu.

FIGURE 1.14. The Cancel button properties dialog.

6. Change the value in the Caption field to &Close. Close the properties dialog by clicking the Close icon in the upper-right corner of the dialog.

7. Move and resize the OK button to around the middle of the window, as in Figure 1.15.

FIGURE 1.15. Positioning the OK button.

8. On the OK button properties dialog, change the ID value to IDHELLO and the caption to &Hello.

9. Now when you compile and run your application, it will look like what you've just designed, as shown in Figure 1.16.

FIGURE 1.16. Running your redesigned application.

NOTE: If you play with your application, you will notice that the Close button still closes the application. However, the Hello button no longer does anything because you changed the ID of the button. MFC applications contain a series of macros in the source code that determine which functions to call based on the ID and event message of each control in the application. Because you changed the ID of the Hello button, these macros no longer know which function to call when the button is clicked.

Adding Code to Your Application

You can attach code to your dialog through the Visual C++ Class Wizard. You can use the Class Wizard to build the table of Windows messages that the application might receive, including the functions they should be passed to for processing, that the MFC macros use for attaching functionality to window controls. You can attach the functionality for this first application by following these steps:

1. To attach some functionality to the Hello button, right-click over the button and select Class Wizard from the pop-up menu.

2. If you had the Hello button selected when you opened the Class Wizard, it is already selected in the list of available Object IDs, as in Figure 1.17.

FIGURE 1.17. The Class Wizard.

3. With IDHELLO selected in the Object ID list, select BN_CLICKED in the list of messages and click Add Function. This opens the Add Member Function dialog shown in Figure 1.18. This dialog contains a suggestion for the function name. Click OK to create the function and add it to the message map.

FIGURE 1.18. The Class Wizard Add Member Function dialog.

4. After the function is added for the click message on the Hello button, select the OnHello function in the list of available functions, as in Figure 1.19. Click the Edit Code button so that your cursor is positioned in the source code for the function, right at the position where you should add your functionality.

FIGURE 1.19. The list of available functions in the Class Wizard.

5. Add the code in Listing 1.1 just below the TODO comment line, as shown in Figure 1.20.

FIGURE 1.20. Source code view where you insert Listing 1.1.

LISTING 1.1.HELLODLG.CPP--THE OnHello FUNCTION.

1: Void CHelloDlg::OnHello()

2:

6. When you compile and run your application, the Hello button should display the message shown in Figure 1.21.

FIGURE 1.21. Now your application will say hello to you.

Finishing Touches

Now that your application is functionally complete, you can still add a few details to finish off the project. Those finishing touches include

* Creating the dialog box icon

* Adding maximize and minimize buttons

Creating the Dialog Box Icon

If you noticed the icon in the top-left corner of your application window, you saw three blocks with the letters M, F, and C. What does MFC have to do with your application? MFC stands for Microsoft Foundation Classes. Technically, it's the C++ class library that your application is built with, but do you want to broadcast that to every user who sees your application? Most likely not. You need to edit the application icon to display an image that you do want to represent your application. Let's get busy!

1. In the tree view of your application resources in the workspace pane, expand the icon branch and select the IDR_MAINFRAME icon, as in Figure 1.22. This brings the application icon into the editor area of the Developer Studio.

FIGURE 1.22. The standard MFC icon.

2. Using the painting tools provided, repaint the icon to display an image that you want to use to represent your application, as in Figure 1.23.

FIGURE 1.23. Your own custom icon for your application.

3. When you compile and run your application, you will notice your custom icon in the top-left corner of your application window. Click the icon and select About Hello from the drop-down menu.

4. On the About dialog that Visual C++ created for you, you can see a large version of your custom icon in all its glory, as shown in Figure 1.24.

FIGURE 1.24. Your application's About window.

NOTE: When you open an application icon in the icon designer, the icon is sized by default at 32x32. You can also select a 16x16 size icon from the drop-down list box just above where you are drawing the icon. You should draw both of these icons because there are some instances in which the large icon will be displayed and some instance in which the small icon will be shown. You will want both icons to show the same image to represent your application.

Adding Maximize and Minimize Buttons

In the dialog editor, where you design your application window, you can add the minimize and maximize buttons to the title bar of your application window by following these steps:

1. Select the dialog window itself as if you were going to resize the window.

2. Using the pop-up menu (from right-clicking the mouse), select the dialog properties.

3. Select the Styles tab, as shown in Figure 1.25.

FIGURE 1.25. Turning the minimize and maximize buttons on and off.

4. After you turn on the minimize and maximize boxes, you can compile and run your application. The minimize and maximize buttons appear on the title bar, as in Figure 1.26.

FIGURE 1.26. The application window with the minimize and maximize buttons.

Summary

Today you got your first taste of building applications using Visual C++. You learned about the different areas of the Visual C++ Developer Studio and what function each of these areas serves. You also learned how you can rearrange the Developer Studio environment to suit the way you work. You also learned how you can use the Visual C++ wizards to create an application shell and then attach functionality to the visual components that you place on your application windows.

Q&A

Q How can I change the title on the message box, instead of using the application name?

A By default, the message box window uses the application name as the window title. You can change this by adding a second text string to the MessageBox function call. The first string is always the message to be displayed, and the second string is used as the window title. For example, the OnHello function would look like

// Say hello to the user

MessageBox('Hello. This is my first Visual C++ Application!',

'My First Application');

Q Can I change the text on the About window to give my company name and more detailed copyright information?

A Yes, the About window is in the Dialogs folder in the Resources View   tab of the workspace pane. If you double-click the IDD_ABOUTBOX dialog, the About box will be opened in the dialog designer, where you can redesign it however you want.

Workshop

The Workshop provides quiz questions to help 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.'

Quiz

1. How do you change the caption on a button?

2. What can you do with the Visual C++ AppWizard?

3. How do you attach functionality to the click of a button?

Exercise

Add a second button to the About window in your application. Have the button display a different message from the one on the first window.

Teach Yourself Visual C++ 6 in 21 Days -- Ch 2 --

Teach Yourself Visual C++ 6 in 21 Days -- Ch 3 -- Allowing User Interaction--Integrating the Mouse and Keyboard in Your Application

Teach Yourself Visual C++ 6 in 21 Days

Allowing User Interaction--Integrating the Mouse and Keyboard in Your Application

* Understanding Mouse Events

* Drawing with the Mouse

* Improving the Drawing Program

* Adding the Finishing Touches

* Capturing Keyboard Events

* Changing the Drawing Cursor

* Making the Change Stick

* Summary

* Q&A

* Workshop

* Quiz

* Exercises

Depending on the type of application you are creating, you might need to notice what the user is doing with the mouse. You need to know when and where the mouse was clicked, which button was clicked, and when the button was released. You also need to know what the user did while the mouse button was being held down.

Another thing that you might need to do is read the keyboard events. As with the mouse, you might need to know when a key was pressed, how long it was held down, and when it was released.

Today you are going to learn

* What mouse events are available for use and how to determine which one is appropriate for your application's needs.

* How you can listen to mouse events and how to react to them in your Visual C++ application.

* What keyboard events are available for use and what actions will trigger each of these events.

* How to capture keyboard events and take action based on what the user pressed.

Understanding Mouse Events

As you learned yesterday, when you are working with most controls, you are limited to a select number of events that are available in the Class Wizard. When it comes to mouse events, you are limited for the most part to click and double-click events. Just looking at your mouse tells you that there must be more to capturing mouse events than recognizing these two. What about the right mouse button? How can you tell if it has been pressed? And what about drawing programs? How can they follow where you drag the mouse?

If you open the Class Wizard in one of your projects, select the dialog in the list of object IDs, and then scroll through the list of messages that are available, you will find a number of mouse-related events, which are also listed in Table 3.1. These event messages enable you to perform any task that might be required by your application.

TABLE 3.1. MOUSE EVENT MESSAGES.

Message  Description

WM_LBUTTONDOWN The left mouse button has been pressed.

WM_LBUTTONUP The left mouse button has been released.

WM_LBUTTONDBLCLK The left mouse button has been double-clicked.

WM_RBUTTONDOWN The right mouse button has been pressed.

WM_RBUTTONUP The right mouse button has been released.

WM_RBUTTONDBLCLK The right mouse button has been double-clicked.

WM_MOUSEMOVE The mouse is being moved across the application window space.

WM_MOUSEWHEEL The mouse wheel is being moved.

Drawing with the Mouse

Today you are going to build a simple drawing program that uses some of the available mouse events to let the user draw simple figures on a dialog window. This application depends mostly on the WM_MOUSEMOVE event message, which signals that the mouse is being moved. You will look at how you can tell within this event function whether the left mouse button is down or up. You will also learn how you can tell where the mouse is on the window. Sound's fairly straight ahead, so let's get going by following these steps:

1. Create a new MFC AppWizard workspace project, calling the project Mouse.

2. Specify that this project will be a dialog-based application in the first AppWizard step.

3. Use the default settings in the AppWizard. In the second step, specify a suitable dialog title, such as Mouse and Keyboard.

4. After the application shell is created, remove all controls from the dialog window. This provides the entire dialog window surface for drawing. This step is also necessary for your application to capture any keyboard events.

NOTE: If there are any controls on a dialog, all keyboard events are directed to the control that currently has input focus--the control that is highlighted or has the cursor visible in it. To capture any keyboard events in a dialog, you have to remove all controls from the dialog.

5. Open the Class Wizard. Select WM_MOUSEMOVE from the list of messages, and add a function by clicking the Add Function button. Click the OK button to accept the suggested function name.

6. Click the Edit Code button to edit the OnMouseMove function you just created, adding the code in Listing 3.1.

LISTING 3.1. THE OnMouseMove FUNCTION.

1: void CMouseDlg::OnMouseMove(UINT nFlags, CPoint point)

2:

///////////////////////

// MY CODE ENDS HERE

///////////////////////

CDialog::OnMouseMove(nFlags, point);

Look at the function definition at the top of the listing. You will notice that two arguments are passed into this function. The first of these arguments is a set of flags that can be used to determine whether a mouse button is depressed (and which one). This determination is made in the first line of your code with the if statement:

if ((nFlags & MK_LBUTTON) == MK_LBUTTON)

In the first half of the condition being evaluated, the flags are filtered down to the one that indicates that the left mouse button is down. In the second half, the filtered flags are compared to the flag that indicates that the left mouse button is down. If the two match, then the left mouse button is down.

The second argument to this function is the location of the mouse. This argument gives you the coordinates on the screen where the mouse currently is. You can use this information to draw a spot on the dialog window.

Before you can draw any spots on the dialog window, you need to get the device context for the dialog window. This is done by declaring a new instance of the CClientDC class. This class encapsulates the device context and most of the operations that can be performed on it, including all the screen drawing operations. In a sense, the device context is the canvas upon which you can draw with your application. Until you have a canvas, you cannot do any drawing or painting. After the device context object is created, you can call its SetPixel function, which colors the pixel at the location specified in the first two arguments with the color specified in the third argument. If you compile and run your program, you can see how it allows you to draw on the window surface with the mouse, as shown in Figure 3.1.

FIGURE 3.1. Drawing on the window with the mouse.

NOTE: In Windows, colors are specified as a single number that is a combination of three numbers. The three numbers are the brightness levels for the red, green, and blue pixels in your computer display. The RGB function in your code is a macro that combines these three separate values into the single number that must be passed to the SetPixel function or to any other function that requires a color value. These three numbers can be any value between and including 0 and 255.

Using the AND and OR Binaries

If you are new to C++, you need to understand how the different types of AND and OR work. The two categories of ANDs and ORs are logical and binary. The logical ANDs and ORs are used in logical or conditional statements, such as an if or while statement that is controlling the logic flow. The binary ANDs and ORs are used to combine two values on a binary level.

The ampersand character (&) is used to denote AND. A single ampersand (&) is a binary AND, and a double ampersand (&&) is a logical AND. A logical AND works much like the word AND in Visual Basic or PowerBuilder. It can be used in an if statement to say 'if this condition AND this other condition' where both conditions must be true before the entire statement is true. A binary AND is used to set or unset bits. When two values are binary ANDed, only the bits that are set to 1 in both values remain as 1; all the rest of the bits are set to 0. To understand how this works, start with two 8-bit values such as the following:

Value 1 01011001

Value 2 00101001

If you binary AND these two values together, you wind up with the following value:

ANDed Value 00001001

All the bits that had 1 in one of the values, but not in the other value, were set to 0. All the bits that were 1 in both values remained set to 1. All the bits that were 0 in both values remained 0.

OR is represented by the pipe character (|), and as with AND, a single pipe (|) is a binary OR, whereas a double pipe (||) is a logical OR. As with AND, a logical OR can be used in conditional statements such as if or while statements to control the logical flow, much like the word OR in Visual Basic and PowerBuilder. It can be used in an if statement to say 'if this condition OR this other condition' and if either condition is true, the entire statement is true. You can use a binary OR to combine values on a binary level. With OR, if a bit is set to 1 in either value, the resulting bit is set to 1. With a binary OR, the only way that a bit is set to 0 in the resulting value is if the bit was already 0 in both values. Take the same two values that were used to illustrate the binary AND:

Value 1 01011001

Value 2 00101001

If you binary OR these two values together, you get the following value:

ORed Value 01111001

In this case, every bit that was set to 1 in either value was set to 1 in the resulting value. Only those bits that were 0 in both values were 0 in the resulting value.

Binary Attribute Flags

Binary ANDs and ORs are used in C++ for setting and reading attribute flags. Attribute flags are values where each bit in the value specifies whether a specific option is turned on or off. This enables programmers to use defined flags. A defined flag is a value with only one bit set to 1 or a combination of other values in which a specific combination of bits is set to 1 so that multiple options are set with a single value. The flags controlling various options are ORed together, making a composite flag specifying which options should be on and which should be off.

If two flags that specify certain conditions are specified as two different bits in a byte, those two flags can often be ORed together as follows:

Flag 1 00001000

Flag 2 00100000

Combination 00101000

This is how flags are combined to specify a number of settings in a limited amount of memory space. In fact, this is what is done with most of the check box settings on the window and control properties dialogs. These on/off settings are ORed together to form one or two sets of flags that are examined by the Windows operating system to determine how to display the window or control and how it should behave.

On the flip side of this process, when you need to determine if a specific flag is included in the combination, you can AND the combination flag with the specific flag that you are looking for as follows:

Combination 00101000

Flag 1 00001000

Result 00001000

The result of this operation can be compared to the flag that you used to filter the combined flag. If the result is the same, the flag was included. Another common approach is to check whether the filtered combination flag is nonzero. If the flag being used for filtering the combination had not been included, the resulting flag would be zero. As a result, you could have left the comparison out of the if statement in the preceding code, leaving you with an if statement that looks like the following:

if (nFlags & MK_LBUTTON)

You can modify this approach to check whether a flag is not in the combination as follows:

if (!(nFlags & MK_LBUTTON))

You might find one of these ways of checking for a flag easier to understand than the others. You'll probably find all of them in use.

Improving the Drawing Program

If you ran your program, you probably noticed a small problem. To draw a solid line, you need to move the mouse very slowly. How do other painting programs solve this problem? Simple, they draw a line between two points drawn by the mouse. Although this seems a little like cheating, it's the way that computer drawing programs work.

As you move the mouse across the screen, your computer is checking the location of the mouse every few clock ticks. Because your computer doesn't have a constant trail of where your mouse has gone, it has to make some assumptions. The way your computer makes these assumptions is by taking the points that the computer does know about and drawing lines between them. When you draw lines with the freehand tool in Paint, your computer is playing connect the dots.

Because all the major drawing programs draw lines between each pair of points, what do you need to do to adapt your application so that it also uses this technique? First, you need to keep track of the previous position of the mouse. This means you need to add two variables to the dialog window to maintain the previous X and Y coordinates. You can do this by following these steps:

1. In the workspace pane, select the Class View tab.

2. Select the dialog class--in this case, the CMouseDlg class.

3. Right-click the mouse and select Add Member Variable from the pop-up menu.

4. Enter int as the Variable Type and m_iPrevY as the Variable Name and specify Private for the access in the Add Member Variable dialog, as shown in Figure 3.2.

FIGURE 3.2. The Add Member Variable dialog.

5. Click OK to add the variable.

6. Repeat steps 3 through 5, specifying the Variable Name as m_iPrevX to add the second variable.

After you add the variables needed to keep track of the previous mouse position, you can make the necessary modifications to the OnMouseMove function, as shown in Listing 3.2.

LISTING 3.2. THE REVISED OnMouseMove FUNCTION.

1: void CMouseDlg::OnMouseMove(UINT nFlags, CPoint point)

2:

///////////////////////

// MY CODE ENDS HERE

///////////////////////

CDialog::OnMouseMove(nFlags, point);

Look at the code that draws the line from the previous point to the current point:

dc.MoveTo(m_iPrevX, m_iPrevY);

dc.LineTo(point.x, point.y);

You see that you need to move to the first position and then draw a line to the second point. The first step is important because without it, there is no telling where Windows might think the starting position is. If you compile and run your application, it draws a bit better. However, it now has a peculiar behavior. Every time you press the left mouse button to begin drawing some more, your application draws a line from where you ended the last line you drew, as shown in Figure 3.3.

FIGURE 3.3. The drawing program with a peculiar behavior.

Adding the Finishing Touches

Your application is doing all its drawing on the mouse move event when the left button is held down. Initializing the previous position variables with the position of the mouse when the left button is pressed should correct this application behavior. Let's try this approach by following these steps:

1. Using the Class Wizard, add a function for the WM_LBUTTONDOWN message on the dialog object.

2. Edit the OnLButtonDown function that you just created, adding the code in Listing 3.3.

LISTING 3.3. THE OnLButtonDown FUNCTION.

1: void CMouseDlg::OnLButtonDown(UINT nFlags, CPoint point)

2:

When you compile and run your application, you should find that you can draw much like you would expect with a drawing program, as shown in Figure 3.4.

FIGURE 3.4. The finished drawing program.

Capturing Keyboard Events

Reading keyboard events is similar to reading mouse events. As with the mouse, there are event messages for when a key is pressed and when it is released. These events are listed in Table 3.2.

TABLE 3.2. KEYBOARD EVENT MESSAGES.

Message  Description

WM_KEYDOWN A key has been pressed down.

WM_KEYUP A key has been released.

The keyboard obviously has fewer messages than the mouse does. Then again, there are only so many things that you can do with the keyboard. These event messages are available on the dialog window object and are triggered only if there are no enabled controls on the window. Any enabled controls on the window have input focus, so all keyboard events go to them. That's why you remove all controls from the main dialog for your drawing application.

Changing the Drawing Cursor

To get a good idea of how you can use keyboard-related event messages, why don't you use certain keys to change the mouse cursor in your drawing application? Make the A key change the cursor to the default arrow cursor, which your application starts with. Then you can make B change the cursor to the I-beam and C change the cursor to the hourglass. To get started adding this functionality, follow these steps:

1. Using the Class Wizard, add a function for the WM_KEYDOWN message on the dialog object.

2. Edit the OnKeyDown function that you just created, adding the code in Listing 3.4.

LISTING 3.4. THE OnKeyDown FUNCTION.

1: void CMouseDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

2:

// Is the character 'B'

if (lsChar == `B')

// Is the character 'C'

if (lsChar == `C')

// Is the character 'X'

43: if (lsChar == `X')

///////////////////////

// MY CODE ENDS HERE

///////////////////////

CDialog::OnKeyDown(nChar, nRepCnt, nFlags);

In the function definition, you see three arguments to the OnKeyDown function. The first is the key that was pressed. This argument is the character code of the character, which needs to be converted into a character in the first line of your code. After you convert the character, you can perform straight-ahead comparisons to determine which key was pressed:

void CMouseDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

The second argument to the OnKeyDown function is the number of times that the key is pressed. Normally, if the key is pressed and then released, this value is 1. If the key is pressed and held down, however, the repeat count rises for this key. In the end, this value tells you how many times that Windows thinks the key has been pressed.

The third argument to the OnKeyDown function is a combination flag that can be examined to determine whether the Alt key was pressed at the same time as the key or whether the key being pressed is an extended key. This argument does not tell you whether the shift or control keys were pressed.

When you determine that a specific key was pressed, then it's time to change the cursor to whichever cursor is associated with that key. There are two steps to this process. The first step is to load the cursor into memory. You accomplish this step with the LoadStandardCursor function, which loads one of the standard Windows cursors and returns a handle to the cursor.

NOTE: A sister function, LoadCursor, can be passed the file or resource name of a custom cursor so that you can create and load your own cursors. If you design your own cursor in the resource editor in Visual C++, you can pass the cursor name as the only argument to the LoadCursor function. For example, if you create your own cursor and name it IDC_MYCURSOR, you can load it with the following line of code:

lhCursor = AfxGetApp()->LoadCursor(IDC_MYCURSOR);

After you load your own cursor, you can set the mouse pointer to your cursor using the SetCursor function, as with a standard cursor.

After the cursor is loaded into memory, the handle to that cursor is passed to the SetCursor function, which switches the cursor to the one the handle points to. If you compile and run your application, you should be able to press one of these keys and get the cursor to change, as in Figure 3.5. However, the moment you move the mouse to do any drawing, the cursor switches back to the default arrow cursor. The following section describes how to make your change stick.

FIGURE 3.5. Changing the cursor with specific keys.

Making the Change Stick

The problem with your drawing program is that the cursor is redrawn every time you move the mouse. There must be some way of turning off this behavior.

Each time the cursor needs to be redrawn--because the mouse has moved, because another window that was in front of your application has gone away, or because of whatever other reason--a WM_SETCURSOR event message is sent to your application. If you override the native behavior of your application on this event, the cursor you set remains unchanged until you change it again. To do this, follow these steps:

1. Add a new variable to the CMouseDlg class, as you did for the previous position variables. This time, declare the type as BOOL and name the variable m_bCursor, as shown in Figure 3.6.

FIGURE 3.6. Defining a class member variable.

2. Initialize the m_bCursor variable in the OnInitDialog with the code in Listing 3.5.

LISTING 3.5. THE OnInitDialog FUNCTION.

1: BOOL CMouseDlg::OnInitDialog()

2:

3. Alter the OnKeyDown function to set the m_bCursor flag to TRUE when you change the cursor, as in Listing 3.6.

LISTING 3.6. THE OnKeyDown FUNCTION.

1: void CMouseDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

2:

else

///////////////////////

// MY CODE ENDS HERE

///////////////////////

CDialog::OnKeyDown(nChar, nRepCnt, nFlags);

4. Using the Class Wizard, add a function for the WM_SETCURSOR message on the dialog object.

5. Edit the OnSetCursor function that you just created, adding the code in Listing 3.7.

LISTING 3.7. THE OnSetCursor FUNCTION.

1: BOOL CMouseDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)

The OnSetCursor function needs to always return TRUE or else call the ancestor function. The ancestor function resets the cursor and does need to be called when the application first starts. Because of this, you need to initialize your variable to FALSE so that until the user presses a key to change the cursor, the default OnSetCursor processing is executed. When the user changes the cursor, you want to bypass the default processing and return TRUE instead. This allows the user to draw with whichever cursor has been selected, including the hourglass, as shown in Figure 3.7.

FIGURE 3.7. Drawing with the hourglass cursor.

NOTE: The most common cursor change that you are likely to use in your programs is setting the cursor to the hourglass while your program is working on something that might take a while. There are actually two functions available in MFC that you can use to handle this task. The first is BeginWaitCursor, which displays the hourglass cursor for the user. The second function is EndWaitCursor, which restores the cursor to the default cursor. Both of these functions are members of the CCmdTarget class, from which all of the MFC window and control classes are derived.

If you have a single function controlling all the processing during which you need to display the hourglass and you don't need to display the hourglass after the function has finished, an easier way to show the hourglass cursor is to declare a variable of the CWaitCursor class at the beginning of the function. This automatically displays the hourglass cursor for the user. As soon as the program exits the function, the cursor will be restored to the previous cursor.

Summary

In this chapter, you learned about how you can capture mouse event messages and perform some simple processing based upon these events. You used the mouse events to build a simple drawing program that you could use to draw freehand figures on a dialog window.

You also learned how to grab keyboard events and determine which key is being pressed. You used this information to determine which cursor to display for drawing. For this to work, you had to learn about the default cursor drawing in MFC applications and how you could integrate your code with this behavior to make your application behave the way you want it to.

From here, you will learn how to use the Windows timer to trigger events at regular intervals. You will also learn how to use additional dialog windows to get feedback from the user so that you can integrate that feedback into how your application behaves. After that, you will learn how to create menus for your applications.

Q&A

Q How can I change the type of line that I am drawing? I would like to draw a larger line with a different color.

A When you use any of the standard device context commands to draw on the screen, you are drawing with what is known as a pen, much like the pen you use to draw on a piece of paper. To draw bigger lines, or different color lines, you need to select a new pen. You can do this by adapting the code in the OnMouseMove function, starting where you get the device context. The following code enables you to draw with a big red pen:

// Get the Device Context

CClientDC dc(this);

// Create a new pen

CPen lpen(PS_SOLID, 16, RGB(255, 0, 0));

// Use the new pen

dc.SelectObject(&lpen);

// Draw a line from the previous point to the current point

dc.MoveTo(m_iPrevX, m_iPrevY);

dc.LineTo(point.x, point.y);

Q How can you tell whether the Shift or Ctrl keys are being held down when you receive the WM_KEYDOWN message?

A You can call another function, ::GetKeyState, with a specific key code to determine whether that key is being held down. If the return value of the ::GetKeyState function is negative, the key is being held down. If the return value is nonnegative, the key is not being held down. For instance, if you want to determine whether the Shift key is being held down, you can use this code:

if (::GetKeyState(VK_SHIFT) < 0)

MessageBox('Shift key is down!');

A number of virtual key codes are defined in Windows for all the special keys. These codes let you look for special keys without worrying about OEM scan codes or other key sequences. You can use these virtual key codes in the ::GetKeyState function and pass them to the OnKeyDown function as the nChar argument. Refer to the Visual C++ documentation for a list of the virtual key codes.

Workshop

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.'

Quiz

1. What are the possible mouse messages that you can add functions for?

2. How can you tell if the left mouse button is down on the WM_MOUSEMOVE event message?

3. How can you prevent the cursor from changing back to the default cursor after you set it to a different one?

Exercises

1. Modify your drawing program so that the left mouse button can draw in red and the right mouse button can draw in blue.

2. Extend the OnKeyDown function to add some of the following standard cursors:

* IDC_CROSS

* IDC_UPARROW

* IDC_SIZEALL

* IDC_SIZENWSE

* IDC_SIZENESW

* IDC_SIZEWE

* IDC_SIZENS

* IDC_NO

* IDC_APPSTARTING

* IDC_HELP

Teach Yourself Visual C++ 6 in 21 Days -- Ch 4 -- Working with Timers

Teach Yourself Visual C++ 6 in 21 Days

Working with Timers

* Understanding Windows Timers

* Placing a Clock on Your Application

* Creating the Project and Application

* Adding the Timer IDs

* Starting the Clock Timer

* Handling the Clock Timer Event

* Adding a Second Timer to Your Application

* Adding the Application Variables

* Starting and Stopping the Counting Timer

* Enabling the Stop Button

* Summary

* Q&A

* Workshop

* Quiz

* Exercise

You may often find yourself building an application that needs to perform a specific action on a regular basis. The task can be something simple such as displaying the current time in the status bar every second or writing a recovery file every five minutes. Both of these actions are regularly performed by several applications that you probably use on a daily basis. Other actions that you might need to perform include checking specific resources on a regular basis, as a resource monitor or performance monitor does. These examples are just a few of the situations where you want to take advantage of the availability of timers in the Windows operating system.

Today you are going to learn

* How to control and use timers in your Visual C++ applications.

* How to set multiple timers, each with a different recurrence interval.

* How to know which timer has triggered.

* How you can incorporate this important resource into all your Visual C++ applications.

Understanding Windows Timers

Windows timers are mechanisms that let you set one or more timers to be triggered at a specific number of milliseconds. If you set a timer to be triggered at a 1,000 millisecond interval, it triggers every second. When a timer triggers, it sends a WM_TIMER message to your application. You can use the Class Wizard to add a function to your application to handle this timer message.

Timer events are placed only in the application event queue if that queue is empty and the application is idle. Windows does not place timer event messages in the application event queue if the application is already busy. If your application has been busy and has missed several timer event messages, Windows places only a single timer message in the event queue. Windows does not send your application all the timer event messages that occurred while your application was busy. It doesn't matter how many timer messages your application may have missed; Windows still places only a single timer message in your queue.

When you start or stop a timer, you specify a timer ID, which can be any integer value. Your application uses this timer ID to determine which timer event has triggered, as well as to start and stop timers. You'll get a better idea of how this process works as you build your application for today.

Placing a Clock on Your Application

In the application that you will build today, you will use two timers. The first timer maintains a clock on the window. This timer is always running while the application is running. The second timer is configurable to trigger at whatever interval the user specifies in the dialog. The user can start and stop this timer at will. Let's get started.

Creating the Project and Application

You will build today's sample application in three phases. In the first phase, you will add all the controls necessary for the entire application. In the second phase, you will add the first of the two timers. This first timer will control the clock on the application dialog. In the third phase, you will add the second timer, which the user can tune, start, and stop as desired.

To create today's application, follow these steps:

1. Create a new project, named Timers, using the same AppWizard settings that you've used for the past three days. Specify the application title as Timers.

2. Lay out the dialog window as shown in Figure 4.1, using the control properties in Table 4.1. Remember that when you place a control on the window, you can right-click the mouse to open the control's properties from the pop-up menu.

FIGURE 4.1. The Timers application dialog layout.

TABLE 4.1. CONTROL PROPERTY SETTINGS.

Object  Property Setting

Static Text ID IDC_STATIC

Caption Timer &Interval:

Edit Box ID IDC_INTERVAL

Button ID IDC_STARTTIME

Caption &Start Timer

Button ID IDC_STOPTIMER

Caption S&top Timer

Disabled Checked

Static Text ID IDC_STATIC

Caption Time:

Static Text ID IDC_STATICTIME

Caption Current Time

Static Text ID IDC_STATIC

Caption Count:

Static Text ID IDC_STATICCOUNT

Caption 0

Button ID IDC_EXIT

Caption E&xit

3. Set the tab order as you learned on Day 2, 'Using Controls in Your Application.'

4. Add code to the Exit button to close the application, as you did on Day 2.

Adding the Timer IDs

Because you will be using two timers in this application, you should add two IDs to your application to represent the two timer IDs. This can be done by following these steps:

1. On the Resource View tab in the workspace pane, right-click the mouse over the Timers resources folder at the top of the resource tree. Select Resource Symbols from the pop-up menu, as in Figure 4.2.

FIGURE 4.2. The Resource pop-up menu.

2. On the Resource Symbols dialog, click the New button.

3. On the New Symbol dialog, enter ID_CLOCK_TIMER as the symbol name and 1 as the value, as shown in Figure 4.3.

FIGURE 4.3. Adding a new resource symbol.

4. Repeat steps 2 and 3, specifying ID_COUNT_TIMER as the symbol name and 2 as the value.

5. Click the Close button to close the Resource Symbols dialog. The two timer IDs are now in your application and ready for use.

Starting the Clock Timer

To start the clock timer, you need to edit the OnInitDialog function, as you did in the previous two days. Add the new code in Listing 4.1.

LISTING 4.1. THE OnInitDialog FUNCTION.

1: BOOL CTimersDlg::OnInitDialog()

2: .

In this listing, you started the clock timer with the SetTimer function. The first argument that you passed to the SetTimer function is the ID for the clock timer. The second argument is how often you want to trigger the event. In this case, the clock timer event is triggered every 1,000 milliseconds, or about every second. The third argument is the address of an optional callback function that you can specify to bypass the WM_TIMER event. If you pass NULL for this argument, the WM_TIMER event is placed in the application message queue.

NOTE: A callback function is a function you create that is called directly by the Windows operating system. Callback functions have specific argument definitions, depending on which subsystem calls the function and why. After you get past the function definition, however, you can do whatever you want or need to do in the function.

A callback function works by passing the address of the function as an argument to a Windows function that accepts callback functions as arguments. When you pass the function address to Windows, your function is called directly every time the circumstances occur that require Windows to call the callback function.

Handling the Clock Timer Event

Now that you've started a timer, you need to add the code to handle the timer event message. You can do this by following these steps:

1. Using the Class Wizard, add a variable to the IDC_STATICTIME control of type CString named m_sTime.

2. Using the Class Wizard, add a function to handle the WM_TIMER message for the CTimersDlg object.

3. Edit the OnTimer function, adding the code in Listing 4.2.

LISTING 4.2. THE OnTimer FUNCTION.

1: void CTimersDlg::OnTimer(UINT nIDEvent)

2:

In this listing, you declare an instance of the CTime class, initializing it to the current system time. The next thing that you do is set the m_sTime string to the current time, using the Format method to format the time in the familiar HH:MM:SS format. Finally, you update the dialog window with the current time. If you compile and run your application now, you should see a clock running in the middle of your dialog window, as in Figure 4.4.

FIGURE 4.4. A running clock on your application dialog.

Adding a Second Timer to Your Application

As you have seen, adding a single timer to an application is a pretty simple task. All it takes is calling the SetTimer function and then placing the timer code in the OnTimer function. However, sometimes you need more than one timer running simultaneously in the same application. Then things get a little bit more involved.

Adding the Application Variables

Before you add the second timer to your application, you need to add a few variables to the controls. With the clock timer, you needed only a single variable for updating the clock display. Now you need to add a few other variables for the other controls, as listed in Table 4.2.

TABLE 4.2. CONTROL VARIABLES.

Object  Name Category Type

IDC_STATICCOUNT m_sCount Value CString

IDC_INTERVAL m_iInterval Value int

IDC_STARTTIME m_cStartTime Control CButton

IDC_STOPTIMER m_cStopTime Control CButton

After you add all the variables using the Class Wizard, follow these steps:

1. Using the Class Wizard, select the m_iInterval variable and specify a Minimum Value of 1 and a Maximum Value of 100000 in the two edit boxes below the list of variables, as shown in Figure 4.5.

FIGURE 4.5. Specifying a range for a variable.

2. On the Class View tab in the workspace pane, add a member variable to the CTimersDlg class as you learned yesterday. Specify the variable type as int, the variable name as m_iCount, and the access as Private.

3. Using the Class Wizard, add a function on the EN_CHANGE event message for the IDC_INTERVAL control ID (the edit box). Edit the function and add the code in Listing 4.3.

LISTING 4.3. THE OnChangeInterval FUNCTION.

1: void CTimersDlg::OnChangeInterval()

2:

When you specify a value range for the timer interval variable, Visual C++ automatically prompts the user, stating the available value range if the user enters a value outside of the specified range. This prompt is triggered by the UpdateData function call in the OnChangeInterval function. The last variable that was added through the workspace pane is used as the actual counter, which is incremented with each timer event.

Starting and Stopping the Counting Timer

To make your second timer operational, you need to

* Initialize the m_iInterval variable.

* Start the timer when the IDC_STARTTIME button is clicked.

* Increment the m_iCount variable and update the dialog on each timer event.

* Stop the timer when the IDC_STOPTIMER button is clicked.

To implement this additional functionality, perform the following steps:

1. Edit the OnInitDialog function, updating the code as in Listing 4.4.

LISTING 4.4. THE UPDATED OnInitDialog FUNCTION.

1: BOOL CTimersDlg::OnInitDialog()

2:

2. Using the Class Wizard, add a function to the BN_CLICKED message on the IDC_STARTTIME button. Edit the OnStarttime function as in Listing 4.5.

LISTING 4.5. THE OnStarttime FUNCTION.

1: void CTimersDlg::OnStarttime()

2:

3. Using the Class Wizard, add a function to the BN_CLICKED message on the IDC_STOPTIMER button. Edit the OnStoptimer function as in Listing 4.6.

LISTING 4.6. THE OnStoptimer FUNCTION.

1: void CTimersDlg::OnStoptimer()

2:

4. Edit the OnTimer function, updating the code as in Listing 4.7.

LISTING 4.7. THE UPDATED OnTimer FUNCTION.

1: void CTimersDlg::OnTimer(UINT nIDEvent)

2:

// Update the dialog

UpdateData(FALSE);

///////////////////////

// MY CODE ENDS HERE

///////////////////////

CDialog::OnTimer(nIDEvent);

In the OnInitDialog function, you added the initialization of the m_iInterval variable, starting it at 100. This initialization is reflected on the dialog window by calling the UpdateData function.

In the OnStarttime function, you first synchronize the variables with the control values, allowing you to get the current setting of the m_iInterval variable. Next, you initialize the m_iCount variable, setting it to 0, and then format the value in the m_sCount CString variable, which is updated in the dialog window. The last thing that you do is to start the timer, specifying the ID_COUNT_TIMER ID and using the interval from the m_iInterval variable.

In the OnStoptimer function, all you really need to do is stop the timer. You do this by calling the KillTimer function, passing the timer ID as the only argument.

It is in the OnTimer function that things begin to get interesting. Here, you still see the code for handling the clock timer event. To add the functionality for the counter timer, you need to determine which timer has triggered this function. The only argument to the OnTimer function just happens to be the timer ID. You can use this ID in a switch statement to determine which timer has called this function and to control which set of code is executed. The clock timer code is still the same as it was in Listing 4.2. The counter timer code is placed into its spot in the switch statement, incrementing the counter and then updating the m_sCount variable with the new value. You can compile and run your application at this point, and you can specify a timer interval and start the timer running, as in Figure 4.6.

FIGURE 4.6. A running counter on your application dialog.

Enabling the Stop Button

If you run your application, you'll find that it works well except for one small problem. When you start your second timer, you can't stop it. When you were specifying all the properties of the controls, you disabled the Stop Timer button. Before you can stop the timer, you need to enable this button.

What makes the most sense is enabling the stop button and disabling the start button once the timer starts. Then you reverse the situation when the timer stops again. You can do this in the same way you enabled and disabled controls on Day 2, or you can modify your approach just a little.

Remember that when you added variables to the controls, you added variables to the start and stop buttons. These were not normal variables, but control variables. Instead of getting a pointer to these controls using their IDs, you can work directly with the control variables. Try that now by updating the OnStarttime and OnStoptimer functions as in Listing 4.8.

LISTING 4.8. THE REVISED OnStarttime AND OnStoptimer FUNCTIONS.

1: void CTimersDlg::OnStarttime()

2:

32: void CTimersDlg::OnStoptimer()

Now when you compile and run your application, it looks more like Figure 4.7, where you can start and stop the counter timer. This enables you to play with the timer interval, putting in a variety of time intervals and observing the difference, with the clock ticking above the counter for reference.

FIGURE 4.7. The finished appli- cation.

Summary

Today you learned how to use the timers built into the Windows operating system to trigger your application at various time intervals that you can control. You learned how to use multiple timers in the same application, running them simultaneously and triggering different actions.

In the coming days, you'll learn how to use additional dialog windows to get feedback from the user so that you can integrate that feedback into how your application behaves. After that, you will learn how to a create menus for your applications. Then you will learn how you can work with text and fonts in your applications.

Q&A

Q What is the interval range that I can set for timers in my applications?

A The available range that you can set for timers in your applications is around 55 milliseconds on the short end to 232 - 1 milliseconds, or around 49 1/2 days, on the long end.

Q How many timers can I have running at the same time in my application?

A That depends. There are a limited number of timers available to all applications in the Windows operating system. Although the number that is available should be more than sufficient for all running applications using no more than a handful of timers, if an application goes overboard and begins hogging the timers, the operating system may run out. It could be your application that is denied the use of some timers, or it could be other applications that don't have any to use. As a general rule, if you use more than two or three timers at the same time, you might want to reconsider your application design and determine if there is another way to design and build your application so that it can work with fewer timers.

Q Is there any way to trigger my application to perform some work when it is idle, instead of using a timer to trigger the work when I think my app might be idle?

A Yes, there is. All Windows applications have an OnIdle function that can be used to trigger idle processing. OnIdle is discussed later on Day 18, 'Doing Multiple Tasks at One Time--Multitasking.'

Workshop

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.'

Quiz

1. What did you accomplish by adding the two timer IDs to the resource symbols?

2. What is another way to add these two IDs to the application?

3. How can you tell two timers apart in the OnTimer function?

4. How many timer events does your application receive if the timer is set for one second and your application has been busy for one minute, preventing it from receiving any timer event messages?

Exercise

Update your application so that when the counter timer is started, the clock timer is reset to run at the same interval as the counter timer. When the counter timer is stopped, return the clock timer to a one-second interval.



Politica de confidentialitate | Termeni si conditii de utilizare



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 618
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved