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

📄 ch16.htm

📁 VC 21天 学习VC 的好东西
💻 HTM
📖 第 1 页 / 共 4 页
字号:
a library module project.</I></P>

<P><A HREF="javascript:popUp('16fig02.gif')"><B>FIGURE 16.2.</B></A><B> </B><I>Specifying
project support options.</I></P>

<P><I></I>
<H4>Creating a Library Project</H4>
<P>To start the library project for today's example, you need to create a new project,
specifying that the project is a Win32 Static Library project. Give the project a
suitable name and click OK to create the project.</P>
<P>For today's sample project, specify on the one wizard step to include both MFC
and precompiled header support. Although the precompiled header support is not necessary,
it will speed up most compiles that you perform while building the module.</P>
<P>Once you create your module project, you'll find yourself working with a project
that has no classes. You've got a blank slate from which you can create whatever
type of module you need.</P>
<P>For your sample project, because you already have the CLine class built, copy
it from the Day 10 project area into the project directory for today's project. Add
both the header and source code file to today's project by choosing Project | Add
To Project \ Files. Once you add both of these files to the project, you should see
the CLine class appear in the Class View of your project.</P>
<P>
<H4>Defining the Classes</H4>
<P>Now that you've got a basic library module project ready to go, it's time to begin
adding the meat of the module. Using the CLine class is an easy way of reusing some
functionality that you created earlier in another setting. However, the real functionality
of this module will be in its ability to generate random drawings, or squiggles.
For this functionality, you'll need to create a new class.</P>
<P>To start this new class, add a new class to the project by selecting New Class
from the pop-up menu in the Class View tab. The first thing that you'll notice in
the New Class dialog is that you are limited to creating generic classes. Because
you are creating a static library that will be linked into the application, Visual
C++ is making some assumptions about the type of class that you want to create. Because
this is not an MFC project, even though MFC support is included, you are prevented
from creating a new MFC or form class. If you need to inherit a new class from an
MFC class, you have to add it as if it were a generic class.</P>
<P>Use the New Class dialog to create your new class. Give the class a name that
reflects its functionality, such as CModArt, and specify that it's derived from the
CObject class as public. You'll receive the same warning that the base class header
file cannot be found, but because you specified that MFC support should be included,
you can ignore that message.</P>
<P>Once you create your class, you need to add a couple of variables to the class.
First, you need somewhere to hold all the lines that will make up the drawing, so
you'll add an object array. Second, you need to know the area of the drawing surface,
so you'll want a CRect to hold the drawing area specification. You can add both of
these variables to your new class using the types and names in Table 16.1.</P>
<P>
<H4>TABLE 16.1. CModArt VARIABLES.</H4>
<P>
<TABLE BORDER="1">
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT"><I>Type</I></TD>
		<TD ALIGN="LEFT"><I>Name</I></TD>
		<TD ALIGN="LEFT"><I>Access</I></TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">static const COLORREF		</TD>
		<TD ALIGN="LEFT">m_crColors[8]		</TD>
		<TD ALIGN="LEFT">Public		</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">CRect		</TD>
		<TD ALIGN="LEFT">m_rDrawArea		</TD>
		<TD ALIGN="LEFT">Private		</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">CObArray		</TD>
		<TD ALIGN="LEFT">m_oaLines		</TD>
		<TD ALIGN="LEFT">Private		</TD>
	</TR>
</TABLE>
</P>
<P><B>Setting the Drawing Area</B></P>
<P>Before you can draw anything, you need to know the area that you have to draw
within. You can add a public function to your class that will copy the passed in
CRect to the member CRect variable. To add this function to your project, add a new
member function to your new class, specifying the type as void, the declaration as
SetRect(CRect rDrawArea), and the access as public. Edit the function as in Listing
16.1.</P>
<P>
<H4>LISTING 16.1. THE CModArt SetRect FUNCTION.</H4>
<PRE>1: void CModArt::SetRect(CRect rDrawArea)
2: {
3:     // Set the drawing area rectangle
4:     m_rDrawArea = rDrawArea;
5: }
</PRE>
<P><B>Creating a New Drawing</B></P>
<P>One of the key pieces to this module is the ability to generate random squiggles
that appear on the drawing area. By generating a whole series of these squiggles,
your module will be able to create an entire drawing. Starting with the single squiggle,
you can design a function that generates one squiggle and then calls this function
a number of times to generate the entire drawing.</P>
<P>This first function, the squiggle generator, needs to determine how many lines
will be in the squiggle. It needs to determine the color and width of the pen to
be used when drawing the squiggle. It also needs to determine the starting point
for the squiggle. From this point, it could loop through the appropriate number of
lines, generating a new destination to continue the squiggle from the previous destination
point.</P>
<P>To add this functionality to your project, add a new member function to the drawing
class. Specify the function type as void, the definition as NewLine, and the access
as private because this function will only be called by the master loop that is determining
how many of these squiggles will be in the final drawing. Edit the new function with
the code in Listing 16.2.</P>
<P>
<H4>LISTING 16.2. THE CModArt NewLine FUNCTION.</H4>
<PRE>1:  void CModArt::NewLine()
2:  {
3:      int lNumLines;
4:      int lCurLine;
5:      int nCurColor;
6:      UINT nCurWidth;
7:      CPoint pTo;
8:      CPoint pFrom;
9:
10:     // Normalize the rectangle before determining the width and height
11:     m_rDrawArea.NormalizeRect();
12:     // get the area width and height
13:     int lWidth = m_rDrawArea.Width();
14:     int lHeight = m_rDrawArea.Height();
15:
16:     // Determine the number of parts to this squiggle
17:     lNumLines = rand() % 100;
18:     // Are there any parts to this squiggle?
19:     if (lNumLines &gt; 0)
20:     {
21:         // Determine the color
22:         nCurColor = rand() % 8;
23:         // Determine the pen width
24:         nCurWidth = (rand() % 8) + 1;
25:         // Determine the starting point for the squiggle
26:         pFrom.x = (rand() % lWidth) + m_rDrawArea.left;
27:         pFrom.y = (rand() % lHeight) + m_rDrawArea.top;
28:         // Loop through the number of segments
29:         for (lCurLine = 0; lCurLine &lt; lNumLines; lCurLine++)
30:         {
31:             // Determine the end point of the segment
32:             pTo.x = ((rand() % 20) - 10) + pFrom.x;
33:             pTo.y = ((rand() % 20) - 10) + pFrom.y;
34:             // Create a new CLine object
35:             CLine *pLine = new CLine(pFrom, pTo, nCurWidth, 
                        &Acirc;m_crColors[nCurColor]);
36:             try
37:             {
38:                 // Add the new line to the object array
39:                 m_oaLines.Add(pLine);
40:             }
41:             // Did we run into a memory exception?
42:             catch (CMemoryException* perr)
43:             {
44:                 // Display a message for the user, giving him the
45:                 // bad news
46:                 AfxMessageBox(&quot;Out of memory&quot;, MB_ICONSTOP | MB_OK);
47:                 // Did we create a line object?
48:                 if (pLine)
49:                 {
50:                     // Delete it
51:                     delete pLine;
52:                     pLine = NULL;
53:                 }
54:                 // Delete the exception object
55:                 perr-&gt;Delete();
56:             }
57:             // Set the starting point to the end point
58:             pFrom = pTo;
59:         }
60:     }
61: }
</PRE>
<P>In this function, the first thing that you did was get the area that you had available
for drawing with the following three lines:</P>
<P>
<PRE>m_rDrawArea.NormalizeRect();
int lWidth = m_rDrawArea.Width();
int lHeight = m_rDrawArea.Height();
</PRE>
<P>In the first of these lines, you normalized the rectangle. This is necessary to
guarantee that the width and height returned in the next two lines are both positive
values. Because of the coordinate system used in Windows, getting the width by subtracting
the left-side position from the right-side position can result in a negative number.
The same can happen with the height. By normalizing the rectangle, you are guaranteeing
that you'll get positive results for these two values.</P>
<P>Once you determined the drawing area, you determined the number of line segments
you would use in this squiggle:</P>
<P>
<PRE>lNumLines = rand() % 100;
</PRE>
<P>The rand function is capable of returning numbers in a wide range. By getting
the modulus of 100, you are guaranteeing that the resulting number will be between
0 and 100. This is a common technique for generating random numbers within a certain
range, using the modulus function with the upper limit of the value range (or the
upper limit minus the lower limit, if the lower limit is not equal to 0, and then
adding the lower limit to the resulting number). You use the same technique to determine
the color, width, and starting position for the squiggle:</P>
<P>
<PRE>nCurColor = rand() % 8;
nCurWidth = (rand() % 8) + 1;
pFrom.x = (rand() % lWidth) + m_rDrawArea.left;
pFrom.y = (rand() % lHeight) + m_rDrawArea.top;
</PRE>
<P>Notice how when you were determining the starting position, you added the left
and top of the drawing area to the position that you generated. This guarantees that
the starting position is within the drawing area. Once you enter the loop, generating
all the line segments in the squiggle, you limit the available area for the next
destination within 10 of the current position:</P>
<P>
<PRE>pTo.x = ((rand() % 20) - 10) + pFrom.x;
pTo.y = ((rand() % 20) - 10) + pFrom.y;
CLine *pLine = new CLine(pFrom, pTo, nCurWidth, m_crColors[nCurColor]);
m_oaLines.Add(pLine);
</PRE>
<P>You can easily increase this distance to make the drawings more angular. Once
you generate the next line segment, you create the line object and add it to the
object array. Finally, you set the starting position to the ending position of the
line segment you just generated:</P>
<P>
<PRE>pFrom = pTo;
</PRE>
<P>Now you are ready to go through the loop again and generate the next line segment,
until you have generated all line segments in this squiggle.</P>
<P>Now that you can generate a single squiggle, the rest of the process is easy.
First, you determine how many squiggles will be in the drawing. Next, you loop for
the number of squiggles that need to be generated and call the NewLine function once
for each squiggle. To add this functionality to your project, add a new member function
to the drawing class. Specify the type as void, the declaration as NewDrawing, and
the access as public. Edit the function as in Listing 16.3.</P>
<P>
<H4>LISTING 16.3. THE CModArt NewDrawing FUNCTION.</H4>
<PRE>1:  void CModArt::NewDrawing()
2:  {
3:      int lNumLines;
4:      int lCurLine;
5:
6:      // Determine how many lines to create
7:      lNumLines = rand() % 10;
8:      // Are there any lines to create?
9:      if (lNumLines &gt; 0)
10:     {
11:         // Loop through the number of lines
12:         for (lCurLine = 0; lCurLine &lt; lNumLines; lCurLine++)
13:         {
14:             // Create the new line
15:             NewLine();
16:         }
17:     }
18: }
</PRE>
<P><B>Displaying the Drawing</B></P>
<P>To draw the set of squiggles on the drawing area, you can add a function that
will loop through the object array, calling the Draw function on each line segment
in the array. This function needs to receive the device context as the only argument
and must pass it along to each of the line segments. To add this function to your
project, add a new member function to the drawing class. Specify the function type
as void, the function declaration as Draw(CDC *pDC), and the access as public. Edit
the function as in Listing 16.4.</P>
<P>
<H4>LISTING 16.4. THE CModArt Draw FUNCTION.</H4>
<PRE>1:  void CModArt::Draw(CDC *pDC)
2:  {
3:      // Get the number of lines in the object array
4:      int liCount = m_oaLines.GetSize();
5:      int liPos;
6:
7:      // Are there any objects in the array?
8:      if (liCount)

⌨️ 快捷键说明

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