⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch06.htm

📁 VC使用大全。里面集合了VC使用的各种使用技巧。非常有用。
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<HTML>

<HEAD>

<TITLE>Special Edition Using Visual C++ 5 - Chapter 6</TITLE>

<LINK REL="Next" HREF="ch07.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/ch07.htm">

<LINK REL="Previous" HREF="ch05.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/ch05.htm"></HEAD>

<BODY BGCOLOR="#FFFFFF" TEXT="#000000">



<H2><B>Chapter 6</B></H2>

<H2><B>Drawing on the Screen</B></H2>

<hr>

<ul>

<li> <B>How device contexts control your displays</B></P>

<P>  You have to know how to manage device contexts before you can display anything on the screen.</P>

<li> <B>Respond to window-painting requests from Windows</B></P>

<P>  When Windows knows that your application's display needs updating, it sends a message to the application.</P>

<li> <B>Create and use fonts, pens, and brushes</B></P>

<P>  The basic elements that determine how your display looks are the fonts, pens, and brushes that you've created for the device context.</P>

<li> <B>How to use scrolling windows</B></P>

<P>  Often, your application will need to display more information than will fit in a window. Scrolling is the answer to this problem, and the MFC CScrollView class makes it simple.</P>

</ul>

<P>Most applications need to display some type of data in their windows. One would think that, because Windows is a device-independent operating system, creating window displays would be easier than luring a kitten with a saucer of milk. However, it is 
exactly Windows' device independence that places a little extra burden on the programmer's shoulders. Because you can never know in advance exactly what type of devices may be connected to a user's system, you can't make many assumptions about display 
capabilities. Functions that draw to the screen must do so indirectly through something called a <I>device context</I> (DC).</P>

<P>Visual C++'s MFC includes many classes that make dealing with DCs easier. These classes encapsulate graphical objects: not only the DC itself, but also pens, brushes, fonts, and more.</P>

<H3><B>Understanding Device Contexts</B></H3>

<P>As you know, every Windows application (in fact, every computer application) must manipulate data in some way. Most applications must also display data. Unfortunately, because of Windows' device independence, this task is not as straightforward in 
Windows as it is in a nongraphical operating system like DOS.</P>

<P>Although device independence forces you, the programmer, to deal with data displays indirectly, it helps you by ensuring that your programs run on all popular devices. In most cases, Windows handles devices for you through the device drivers that the 
user has installed on the system. These device drivers intercept the data that the application needs to display and then translates the data appropriately for the device on which it will appear, whether that is a screen, a printer, or some other output 
device.</P>

<P>To understand how all of this device independence works, imagine an art teacher trying to design a course of study appropriate for all types of artists. The teacher creates a course outline that stipulates the subject of a project, the suggested colors 
to be used, the dimensions of the finished project, and so on. What the teacher doesn't stipulate is the surface on which the project will be painted or the materials needed to paint on that surface. In other words, the teacher stipulates only general 
characteristics. The details of how these characteristics are applied to the finished project are left up to each specific artist.</P>

<P>For example, an artist using oil paints will choose canvas as his drawing surface and oil paints, in the colors suggested by the instructor, as the paint. On the other hand, an artist using watercolors will select watercolor paper on which to create 
her work, and she will, of course, use watercolors rather than oils for paint. Finally, the charcoal artist will select the appropriate drawing surface for charcoal and will use a single color.</P>

<P>The instructor in the preceding scenario is much like a Windows programmer. The programmer has no idea who may eventually use the program and what kind of system that user may have. The programmer can recommend the colors in which data should be 
displayed and the coordinates at which the data should appear, for example, but it is the device driver&#151;the Windows artist&#151;that ultimately decides how the data appears.</P>

<P>A system with a VGA monitor may display data with fewer colors than a system with a Super VGA monitor. Likewise, a system with a monochrome monitor displays the data in only a single color. Monitors with high resolutions can display more data than 
lower-resolution monitors. The device drivers, much like the artists in the imaginary art school, must take the display requirements and fine-tune them to the device on which the data will actually appear. And it is a data structure called a <I>device 
context</I> that links the application to the device's driver.</P>

<P>A device context (DC) is little more than a data structure that keeps track of the attributes of a window's drawing surface. These attributes include the currently selected pen, brush, and font that will be used to draw on the screen. Unlike an artist, 
who can have many brushes and pens with which to work, a DC can use only a single pen, brush, or font at a time. If you want to use a pen that draws wider lines, for example, you need to create the new pen and then replace the DC's old pen with the new 
one. Similarly, if you want to fill shapes with a red brush, you must create the brush and &quot;select it into the DC,&quot; which is how Windows programmers describe replacing a tool in a DC.</P>

<P>A window's client area is a versatile surface that can display anything a Windows program can draw. The client area can display any type of data because everything displayed in a window, whether it be text, spreadsheet data, a bitmap, or any other type 
of data, is displayed graphically. MFC helps you display data by encapsulating Windows' GDI functions and objects into its DC classes.</P>

<H3><B>Introducing the Paint1 Application</B></H3>

<P>In this chapter, you will build the Paint1 application, which demonstrates fonts, pens, and brushes. Paint1 will use the document/view paradigm discussed in <A HREF="index05.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index05.htm" target="text">Chapter 5</A>, &quot;Documents and Views&quot;, and the 
view will handle displaying the data. When run, the application will display text in several different fonts. When the user clicks the application, it displays lines drawn with several different pens. After another click it displays boxes filled with a 
variety of brushes.</P>

<P>The first step in creating Paint1 is to build an empty shell with AppWizard, as first discussed in <A HREF="index01.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index01.htm" target="text">Chapter 1</A>, &quot;Building Your First Application.&quot;. Choose File, New, and select the Projects tab. As shown 
in Figure 6.1, fill in the project name as Paint1 and fill in an appropriate directory for the project files. Make sure that <font color="#008000">MFC AppWizard </font><font color="#008000">(exe)</font> is selected. Click OK.</P>

<A HREF="Hfig01.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch06/Hfig01.gif"><b>Fig. 6.1</b></A>

<P><I>Start an AppWizard project workspace called Paint1.</I></P>

<P>Move through the AppWizard dialog boxes, change the settings to match those in the list that follows, then click Next to move to the next step:</P>

<P>Step 1: Single document</P>

<P>Step 2: Default settings</P>

<P>Step 3: Default settings</P>

<P>Step 4: Uncheck all check boxes</P>

<P>Step 5: Default settings</P>

<P>Step 6: Default settings</P>

<P>After you click Finish on the last step, the New project information box should resemble Figure 6.2. Click OK to create the project.</P>

<A HREF="Hfig02.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/figs/ch06/Hfig02.gif"><b>Fig. 6.2</b></A>

<P><I>The starter application for Paint1 is very simple.</I></P>

<P>Now that you have a starter application, it&#146;s time to add code to make it demonstrate some of the ways an MFC program can display data on the screen. By the time you get to the end of this chapter, the words <I>display context</I> won't make you 
scratch your head in perplexity.</P>

<blockquote><p><img src="note.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/note.gif">

<P>Your starter application has menus, but you are going to ignore them completely. It would be quite a bit of work to remove them; just pretend they aren&#146;t there.</P>

<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>

<H3><B>Building the Paint1 Application</B></H3>

<P>In order to build the Paint1 application, you first need to understand how painting and drawing work in an MFC program. Then you can set up the skeleton code to handle the clicks from the user and the three different kinds of display. Finally, you will 
fill in the code for each kind of display in turn.</P>

<P><B>Painting in an MFC Program</B></P>

<P>In <A HREF="index04.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index04.htm" target="text">Chapter 4</A>, &quot;Messages and Commands,&quot; you learned about message maps and how you can tell MFC which functions to call when it receives messages from Windows. One important message that every Windows 
program with a window must handle is <font color="#008000">WM_PAINT</font>. Windows sends the <font color="#008000">WM_PAINT</font> message to an application's window when the window needs to be redrawn. There are several events that cause Windows to send 
a <font color="#008000">WM_PAINT</font> message. The first event occurs when the user simply runs the program. In a properly written Windows application, the application's window gets a <font color="#008000">WM_PAINT</font> message almost immediately after 
being run, in order to ensure that the appropriate data is displayed from the very start.</P>

<P>Another time a window might receive the <font color="#008000">WM_PAINT</font> message is when the window has been resized or has recently been uncovered&#151;either fully or partially&#151;by another window. In either case, part of the window that 
wasn't visible before is now on the screen, and must be updated.</P>

<P>Finally, a program can indirectly send itself a <font color="#008000">WM_PAINT</font> message by invalidating its client area. Having this ability ensures that an application can change its window's contents almost any time it wishes. For example, a 
word processor might invalidate its window after the user pastes some text from the Clipboard.</P>

<P>When you studied message maps, you learned to convert a message name to a message-map macro and function name. You now know, for example, that the message-map macro for a <font color="#008000">WM_PAINT</font> message is <font 
color="#008000">ON_WM_PAINT()</font>. You also know that the matching message-map function should be called <font color="#008000">OnPaint()</font>. This is another case where MFC has already done most of the work of matching a Windows message with its 
message-response function. (If all this message-map stuff doesn't sound familiar, you might want to review <A HREF="index04.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index04.htm" target="text">Chapter 4</A>, &quot;Messages and Comands&quot;.)</P>

<P>You might guess that the next step for you is to catch the WM_PAINT message, or to override the <font color="#008000">OnPaint()</font> function that your view class inherited from CView, but you are not going to do that. The code for <font 
color="#008000">CView::OnPaint()</font> is in Listing 6.1. As you can see, WM_PAINT is already caught and handled for you.</P>

<P><I>Listing 6.1&#151;CView::OnPaint()</I></P>

<pre><font color="#008000">void CView::OnPaint()</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">     // standard paint routine</font></pre>

<pre><font color="#008000">     CPaintDC dc(this);</font></pre>

<pre><font color="#008000">     OnPrepareDC(&amp;dc);</font></pre>

<pre><font color="#008000">     OnDraw(&amp;dc);</font></pre>

<pre><font color="#008000">}</font></pre>

<p><font color="#008000">CPaintDC</font> is a special class for managing <I>paint DCs,</I> which are device contexts that are used only when responding to <font color="#008000">WM_PAINT</font> messages. An object of the <font 
color="#008000">CPaintDC</font> class does more than just create a DC; it also calls the <font color="#008000">BeginPaint()</font> Windows API function in the class's constructor and calls <font color="#008000">EndPaint()</font> in its destructor. When a 
program responds to <font color="#008000">WM_PAINT</font> messages, calls to <font color="#008000">BeginPaint()</font> and <font color="#008000">EndPaint()</font> are required. The <font color="#008000">CPaintDC</font> class handles this requirement 
without your having to get involved in all the messy details. As you can see, the <font color="#008000">CPaintDC</font> constructor takes a single argument, which is a pointer to the window for which you're creating the DC. The <font 
color="#008000">this</font> pointer points to the current view, so it is passed to the constructor to make a DC for the current view.</P>

<p><font color="#008000">OnPrepareDC()</font> is a CView function that prepares a DC for use. You&#146;ll learn more about it in <A HREF="index07.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index07.htm" target="text">Chapter 7</A>, &#147;Printing and Print Preview.&#148;</P>

<P><B>Switching the Display</B></P>

<P>The design for Paint1 states that when you click the application's window, the window's display changes. This seemingly magical feat is actually easy to accomplish. You add a member variable to the view to store what kind of display is being done, and 
change it when the user clicks the window. In other words, the program routes <font color="#008000">WM_LBUTTONDOWN</font> messages to the <font color="#008000">OnLButtonDown()</font> message-response function, which sets the <font 
color="#008000">m_display</font> flag as appropriate.</P>

<P>First, add the member variable. You must add it by hand rather than through the shortcut menu because the type includes an <font color="#008000">enum</font> declaration. Open CPaint1View.h from the FileView, and add these lines after the <font 
color="#008000">//Attributes</font> comment:</P>

<pre><font color="#008000">protected:</font></pre>

<pre><font color="#008000">     enum {Fonts, Pens, Brushes} m_Display;</font></pre>

<blockquote><p><img src="tip.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/tip.gif">

<P>This is an <I>anonymous</I> or unnamed <font color="#008000">enum</font>. You can learn more about <font color="#008000">enum</font> types in the electronic book &quot;C++ by Example&quot; included on this book's CD.</P>

<p><img src="bottom.gif" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/bottom.gif"></blockquote>

<P>Choose ClassView in the Project Workspace pane, expand the classes, expand CPaint1View, and then double-click the constructor, <font color="#008000">CPaint1View()</font>. Add this line of code in place of the TODO comment:</P>

<pre><font color="#008000">     m_Display = Fonts;</font></pre>

<P>This initializes the display selector to the font demonstration. You use the display selector in the <font color="#008000">OnDraw()</font> function called by <font color="#008000">CView::OnPaint()</font>. AppWizard has created <font 
color="#008000">CPaint1View::OnDraw()</font>, but it doesn&#146;t do anything at the moment. Double-click the function name in ClassView, and add the code shown in Listing 6.2 to the function, removing the TODO comment left by AppWizard.</P>

<P><I>Listing 6.2&#151;Cpainr1View::OnDraw()</I></P>

<pre><font color="#008000">void CPaint1View::OnDraw(CDC* pDC)</font></pre>

<pre><font color="#008000">{</font></pre>

<pre><font color="#008000">     CPaint1Doc* pDoc = GetDocument();</font></pre>

<pre><font color="#008000">     ASSERT_VALID(pDoc);</font></pre>

<pre><font color="#008000">     switch (m_Display)</font></pre>

<pre><font color="#008000">     {</font></pre>

<pre><font color="#008000">          case Fonts:</font></pre>

<pre><font color="#008000">               ShowFonts(pDC);</font></pre>

<pre><font color="#008000">               break;</font></pre>

<pre><font color="#008000">          case Pens:</font></pre>

<pre><font color="#008000">               ShowPens(pDC);</font></pre>

<pre><font color="#008000">               break;</font></pre>

<pre><font color="#008000">          case Brushes:</font></pre>

<pre><font color="#008000">               ShowBrushes(pDC);</font></pre>

<pre><font color="#008000">               break;</font></pre>

<pre><font color="#008000">     }</font></pre>

<pre><font color="#008000">}</font></pre>

<P>You will write the three functions <font color="#008000">ShowFonts()</font>, <font color="#008000">ShowPens()</font>, and <font color="#008000">ShowBrushes()</font> in upcoming sections of this chapter. Each of these functions uses the same DC pointer 
that was passed to <font color="#008000">OnDraw()</font> by <font color="#008000">OnPaint()</font>. Add them to the class now, by following these steps:</P>

<ol> 

<li><P> Right-click the <font color="#008000">CPaint1View</font> class in ClassView and select Add Member Function</P>

<li><P> Enter <font color="#008000">void</font> for the Function Type</P>

<li><P> Enter <font color="#008000">ShowFonts(CDC* pDC)</font> for the Function Declaration</P>

<li><P> Change the access to protected. Click OK.</P>

<li><P> Repeat steps 1 to 4 for ShowPens(CDC* pDC) and ShowBrushes(CDC* pDC).</P>

</ol>

<P>The last step in arranging for the display to switch is to catch left mouse clicks and write code in the message-handler to change <font color="#008000">m_display</font>.</P>

<P>Right-click <font color="#008000">CPaint1View</font> in the ClassView and select Add Windows Message Handler from the shortcut menu that appears. Double-click <font color="#008000">WM_LBUTTONDOWN</font> in the New Windows Message and Event Handlers 
listbox. ClassWizard adds a function called <font color="#008000">OnLButtonDown()</font> to the view and adds entries to the message map so that this function will be called whenever the user clicks the left mouse button over this view.</P>

<P>Click Edit Existing to edit the empty <font color="#008000">OnLButtonDown()</font> you just created, and add the code shown in Listing 6.3.</P>

<P><I>Listing 6.3&#151; CPaint1View::OnLButtonDown()</I></P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -