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

📄 ch28.htm

📁 VC使用大全。里面集合了VC使用的各种使用技巧。非常有用。
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<pre><font color="#008000">     char DrivePath[4] = { char( drive + 65 ), ':', '\\', '\0' };</font></pre>

<pre><font color="#008000">     if( GetDiskFreeSpace( DrivePath, &amp;sectorsPerCluster,</font></pre>

<pre><font color="#008000">          &amp;bytesPerSector, &amp;freeClusters, &amp;totalClusters ))</font></pre>

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

<pre><font color="#008000">          return sectorsPerCluster * bytesPerSector * freeClusters;</font></pre>

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

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

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

<pre><font color="#008000">          return 0;</font></pre>

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

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

<P>Change the Code Generation settings to Multithreaded Debug as discussed in the Console Applications section earlier in this chapter, and build the DLL. In the next section you will see how to use 32-bit DLLs in general, and how Windows finds DLLs on 
your system.</P>

<P>The most common use of a DLL is to provide extended, reusable functionality and let Windows implicitly load the DLL. Topics that will not be discussed in this book, that you might want to explore for yourself, include:</P>

<ul>

<li> Dynamic versus static linking of MFC.</P>

<li> Implicit versus explicit DLL loading, which requires the use of LoadLibrary and FreeLibrary.</P>

<li> Multithreading DLLs.</P>

<li> Sharing data across DLL boundaries.</P>

<li> Calling conventions for DLLs that will be used by other languages (__stdcall, WINAPI, ...).</P>

</ul>

<P>In this chapter you are going to use a default compile of DiskFree, using an implicit DllMain (the compiler added one), and an implicit loading of the DLL, allowing Windows to manage loading and unloading the library.</P>

<P><B>Using 32-bit DLLs</B></P>

<P>Many DLLs are loaded implicitly and their loading and unloading is managed by Windows. Libraries loaded in this fashion are searched for like executables: first the directory of the application loading the DLL is searched, followed by the current 
directory, the Windows\System directory, the Windows directory and finally each directory specified in the PATH.</P>

<P>It is a common practice to place a DLL in the Windows or Windows\System directories once the application is shipped, but in the meantime you may use the development directory of the executable for temporary storage. One thing to safeguard against is 
that you do not end up with multiple versions of the DLL in each of the Windows, Windows\System, or project directories.</P>

<P><B>Using a DLL</B></P>

<P>Implicitly loading and using a DLL is about as simple as using any other function. This is especially true if you created the header file as described in the &quot;Creating the DiskFree DLL&quot; section. When you compile your DLL, Microsoft Visual C++ 
creates a .LIBfile. (So, DISKFREE.DLL has a DISKFREE.LIB created by the compiler.) The library (.LIB) file is used to resolve the load address of the DLL and specify the full pathname of the dynamic link library, and the header file provides the 
declaration.</P>

<P>All you have to do is include the header in the file using the DLL functionality and add the .LIB name to the <U>P</U>roject, <U>S</U>ettings dialog box, on the Link tab (see Figure 28.3), in the Object/library modules edit field.</P>

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

<P><I>Add your LIB file to the project settings.</I></P>

<P>To test the DiskFree DLL, create a console application called TestDiskFree and add a C++ source file called TestDiskFree.cpp. Add the code from Listing 28.7 to this file. Copy DiskFree.h to this folder and add it to the project by choosing Project, Add 
To Project, Files, and selecting DiskFree.h. Copy DiskFree.Dll and DiskFree.Lib to the TestDiskFree folder also. (You'll find them in DiskFree\Debug.) Change the project settings as just described, and build the project. </P>

<P><I>Listing 28.</I><I>7</I><I>&#151;TestDiskFree.Cpp </I></P>

<pre><font color="#008000">#include &lt;afx.h&gt;</font></pre>

<pre><font color="#008000">#include &lt;iostream.h&gt;</font></pre>

<pre><font color="#008000">#include &quot;diskfree.h&quot;</font></pre>

<pre><font color="#008000">#define CodeTrace(arg) \</font></pre>

<pre><font color="#008000">     cout &lt;&lt; #arg &lt;&lt; endl;\</font></pre>

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

<pre><font color="#008000">int main()</font></pre>

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

<pre><font color="#008000">     CodeTrace( cout &lt;&lt; DiskFree(2) &lt;&lt; endl );</font></pre>

<pre><font color="#008000">     return 0;</font></pre>

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

<P>This code brings in the DLL by including diskfree.h, and then uses it. The CodeTrace macro simply prints out a line of code before executing it. All that this application does is call the DiskFree() function to ask how much space is free on drive 2. 
Drive 0 is a:, drive 1 is b: and drive 2 is c:. If you build and execute the program you should see output like Figure 28.6</P>

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

<P><I>Your little application calls the DLL.</I></P>

<P>According to TestDiskFree, the C: drive on the machine used for these samples has almost 400 M of free disk space. This number is correct. Now you can write real functions in a DLL, and use them or make them available to other people to use.</P>

<H3><B>Sending Messages and Commands</B></H3>

<P>As discussed 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; messages are the heart of Windows. Everything that happens in a Windows application happens because a message showed up to make it happen. When you 
move your mouse and click a button, a huge number of messages are generated, including WM_MOUSEMOVE for each movement of the mouse, WM_LBUTTONDOWN when the button goes down, WM_LBUTTONCLICK when the button is released, and higher level, more abstract 
messages like the WM_COMMAND message with the button's resource ID as one of its parameters. You can ignore the lower-level messages if you wish and many programmers do.</P>

<P>What you may not know is that <I>you</I> can generate messages, too. There are two functions that generate messages: <font color="#008000">CWnd::SendMessage()</font> and <font color="#008000">CWnd::PostMessage()</font>. Each of these gets a message to 
an object that inherits from <font color="#008000">CWnd</font>. An object that wants to send a message to a window using one of these functions must have a pointer to the window, and the window must be prepared to catch the message. A very common approach 
to this situation is to have a member variable in the sending object that stores a pointer to the window that will receive the message and another that stores the message to be sent:</P>

<pre><font color="#008000">CWnd* m_messagewindow;</font></pre>

<pre><font color="#008000">UINT m_message;</font></pre>

<P>Messages are represented by unsigned integers. They appear to have names only because names like WM_MOUSEMOVE are connected to integers with #<font color="#008000">define</font> statements.</P>

<P>The sending class has a member function to set these member variables, typically very short:</P>

<pre><font color="#008000">void Sender::SetReceiveTarget(CWnd *window, UINT message)</font></pre>

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

<pre><font color="#008000">    m_messagewindow = window;</font></pre>

<pre><font color="#008000">    m_message = message;               </font></pre>

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

<P>When the sending class needs to get a message to the window, it calls SendMessage:</P>

<pre><font color="#008000">    m_messagewindow-&gt;SendMessage(m_message, wparam, lparam);</font></pre>

<P>Or PostMessage:</P>

<pre><font color="#008000">    m_messagewindow-&gt;PostMessage(m_message, wparam, lparam);</font></pre>

<P>The difference between sending and posting a message is that <font color="#008000">SendMessage()</font> does not return until the message has been handled by the window that received it, but <font color="#008000">PostMessage()</font> just adds the 
message to the message queue and returns right away. If, for example, you build an object, pass that object's address as the <font color="#008000">lparam</font>, and then delete the object, you should choose <font color="#008000">SendMessage()</font>, 
because you can't delete the object until you are sure that the message-handling code has finished with it. If you are not passing pointers you can probably use <font color="#008000">PostMessage()</font> and move on as soon as the message has been added to 
the queue.</P>

<P>The meaning of the <font color="#008000">wparam</font> and <font color="#008000">lparam</font> values depends on the message you are sending. If it is a defined system message like WM_MOUSEMOVE, you can read the online documentation to learn what the 
parameters are. If, as is more likely, you are sending a message that you have invented, the meaning of the parameters is entirely up to you. You are the one who is inventing this message, and writing the code to handle it when it arrives at the other 
window.</P>

<P>To invent a message, add a defining statement to the header file of the class that will catch it:</P>

<pre><font color="#008000">#define WM_HELLO WM_USER + 300</font></pre>

<P>WM_USER is an unsigned integer that marks the start of the range of message numbers available for user defined messages. In this release of MFC, its value is 0x4000, though you should not depend on that. User defined messages have message numbers 
between WM_USER and 0x7FFF.</P>

<P>Then add a line to the message map, in both the header and source file, outside the ClassWizard comments. The source file message map might look like this:</P>

<pre><font color="#008000">BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)</font></pre>

<pre><font color="#008000">     //{{AFX_MSG_MAP(CMainFrame)</font></pre>

<pre><font color="#008000">          // NOTE - the ClassWizard will add and remove mapping </font><font color="#008000">macros here.</font></pre>

<pre><font color="#008000">          //    DO NOT EDIT what you see in these blocks of generated </font><font color="#008000">code !</font></pre>

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

<pre><font color="#008000">     ON_MESSAGE(WM_HELLO, OnHello)</font></pre>

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

<P>The entry added outside the <font color="#008000">//AFX_MSG_MAP</font> comments catches the <font color="#008000">WM_HELLO</font> message and arranges for the <font color="#008000">OnHello()</font> function to be called. The header file message map 
might look like this:</P>

<pre><font color="#008000">// Generated message map functions</font></pre>

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

<pre><font color="#008000">     //{{AFX_MSG(CMainFrame)</font></pre>

<pre><font color="#008000">     afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);</font></pre>

<pre><font color="#008000">          // NOTE - the ClassWizard will add and remove member </font><font color="#008000">functions here.</font></pre>

<pre><font color="#008000">          //    DO NOT EDIT what you see in these blocks of generated </font><font color="#008000">code!</font></pre>

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

<pre><font color="#008000">     afx_msg LRESULT OnHello(WPARAM wParam, LPARAM lParam);</font></pre>

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

<P>Then you add an implementation of <font color="#008000">OnHello()</font> to the source file to complete the process.</P>

<H3><B>Considering International Software Development Issues</B></H3>

<P>International boundaries are shrinking at incredible rates. As access to wider serial communications widens and the preponderance of discrete resalable components continues, more and more demands for pieces built by vendors world-wide will grow. Even 
in-house software development will less frequently be able to ignore international markets. The rise in popularity of the Internet has expanded the reach of many developers into countries where languages other than English and character sets other than 
ASCII predominate. This means your applications should be able to communicate with users in languages other than English, and in characters sets other than the typical Western character set.</P>

<P>Microcomputers were created in the United States which explains why we have 8-bit character based operating systems. There are only 26 letters in our alphabet and ten digits, which leaves plenty of room (about 220 characters worth) for punctuation and 
other miscellaneous characters. But countries like Japan and China require a character set in the thousands.</P>

<P>Unicode is one way to tackle the character set problem. The Unicode standard was developed and is supported by a consortium of some of the biggest players in the international computing markets. Among these are Adobe, Aldus, Apple, Borland, Digital, 
IBM, Lotus, Microsoft, Novell, and Xerox. </P>

<P>Unicode uses two bytes for each character, whereas ASCII uses only one. One byte (8 bits) can represent 28 or 256 characters. Two bytes (16 bits) can represent 65,536 characters. This is enough not just for one language, but for all the character sets 
in general use. For example, the Japanese character set, one of the largest, needs about 5000 characters. Most require far less. The Unicode specification sets aside different ranges for different character sets and can cover almost every language on Earth 
in one universal code&#151;a Unicode.</P>

<P>MFC has full Unicode support, with Unicode versions of almost every function. For example, consider the function <font color="#008000">CWnd::SetWindowText()</font>. It takes a string and sets the title of the window, or the caption of a button, to that 
string. What kind of string it takes depends on whether you have Unicode support turned on in your application. In reality, there are two different functions to set the window text one, a Unicode version and a non-Unicode version, and in WINUSER.H, the 
block of code shown in Listing 28.8 changes the function name that you call to SetWindowTextA if you are not using Unicode, or SetWindowTextW if you are.</P>

<P><I>Listing </I><I>28</I><I>.</I><I>8&#151;</I><I>Microsoft's WINUSER.H Implementing Unicode </I><I>Support</I></P>

<pre><font color="#008000">WINUSERAPI BOOL WINAPI SetWindowTextA(HWND hWnd, LPCSTR lpString);</font></pre>

<pre><font color="#008000">WINUSERAPI BOOL WINAPI SetWindowTextW(HWND hWnd, LPCWSTR lpString);</font></pre>

<pre><font color="#008000">#ifdef UNICODE</font></pre>

<pre><font color="#008000">#define SetWindowText  SetWindowTextW</font></pre>

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

<pre><font color="#008000">#define SetWindowText  SetWindowTextA</font></pre>

<pre><font color="#008000">#endif // !UNICODE</font></pre>

<P>The difference between these two functions is the type of the second parameter: LPCSTR for the A version and LPCWSTR for the W (Wide) version.</P>

<P>If you are using Unicode, whenever you pass a literal string (like &quot;Hello&quot;) to a function, wrap it in the _T macro, like this:</P>

<pre><font color="#008000">pWnd-&gt;SetWindowText(_T(&quot;Hello&quot;));</font></pre>

<P>If you can deal with the annoyance of wrapping all text strings in _T macros, just like that your application is Unicode aware. When you prepare your Greek or Japanese version of the application, life will be much simpler.</P>

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

<P>Windows 95 was built on old Windows, so it was not built using Unicode. This means that if you use Unicode in your Windows 95 programs, you are going to suffer performance penalties because the Windows 95 kernel will have to convert Unicode strings 
back to ordinary strings. Windows NT was designed at Microsoft from scratch, so is completely compatible with Unicode.</P>

<P>If you are developing for several platforms with C++ and using Unicode, your Win95 version may seem sluggish in comparison to the Windows NT version.</P>

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

<H3><B>From Here</B><B>...</B></H3>

<P>This chapter demonstrated the way to build a console application, with or without MFC. You also learned how to use a dynamic-link library (DLL) and how to create your own DLL, and how to send custom messages to another part of your application. 
Finally, you learned how to ready your applications for the international market with Unicode.</P>

<P>To learn about related topics see:</P>

<ul>

<li> <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; for an introduction to the importance of messages and how message maps work.</P>

<li> <A HREF="index26.htm" tppabs="http://www.mcp.com/814147200/0-7897/0-7897-1145-1/index26.htm" target="text">Chapter 26</A>, &quot;Exceptions, Templates, and the Latest Additions to C++&quot; for other advanced programming topics. </P>

</ul>

<p><hr></p>

<center>

<p><font size=-2>

&copy; 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a

Simon and Schuster Company.</font></p>

</center>

</BODY></HTML>

⌨️ 快捷键说明

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