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

📄 ch28.htm

📁 A very good resource on Visual C++ 6.0 environment. It teaches through step by step approach and fin
💻 HTM
📖 第 1 页 / 共 3 页
字号:
     unsigned long bytesPerSector, sectorsPerCluster,
          freeClusters, totalClusters;
     char DrivePath[4] = { char( drive + 65 ), `:', `\\', `\0' };
     if( GetDiskFreeSpace( DrivePath, &sectorsPerCluster,
          &bytesPerSector, &freeClusters, &totalClusters ))
     {
          return sectorsPerCluster * bytesPerSector * freeClusters;
     }
     else
     {
          return 0;
     }
</PRE>
<PRE>}
</PRE>
<P>Now you can 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><A HREF="javascript:popUp('28fig04.gif')"><B>FIG. 28.4</B></A><B> </B><I>Creating
a non-MFC DLL project is a one-step process.</I></P>
<P>The most common use of a DLL is to provide extended, reusable functionality and
let Windows implicitly load the DLL. Topics that aren't discussed in this book, which
you might want to explore for yourself, include the following:</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, ...)
</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>
<H3><A NAME="Heading7"></A>Using 32-Bit DLLs</H3>
<P>Many DLLs are loaded implicitly, and their loading and unloading are 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 for Windows 95 or 98, Winnt\System or Winnt\System32
for NT, 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 directory
after the application is shipped, but in the meantime, you can use the development
directory of the executable for temporary storage. One thing to safeguard against
is that you don't end up with multiple versions of the DLL in each of the Windows,
Windows\System, or project directories.</P>
<P><B>Using a DLL&#160;&#160;</B>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 .LIB file. (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 Project Settings dialog box, on the Link tab (see Figure
28.5), in the Object/Library Modules edit field.</P>
<P>To test the DiskFree DLL, create a console application called TestDiskFree as
An Empty Project 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 to include the
DiskFree.Lib file, and build the project.</P>
<P><A HREF="javascript:popUp('28fig05.gif')"><B>FIG. 28.5</B></A><B> </B><I>Add your
LIB file to the project settings.</I></P>
<P>
<H4>Listing 28.7&#160;&#160;TestDiskFree.cpp</H4>
<PRE>#include &lt;iostream.h&gt;
#include &quot;diskfree.h&quot;
#define CodeTrace(arg) \
     cout &lt;&lt; #arg &lt;&lt; endl;\
     arg
int main()
{
     CodeTrace( cout &lt;&lt; DiskFree(2) &lt;&lt; endl );
     return 0;
</PRE>
<PRE>}
</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 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>
<P><A HREF="javascript:popUp('28fig06.gif')"><B>FIG. 28.6</B></A><B> </B><I>Your
little application calls the DLL.</I></P>
<P>According to TestDiskFree, the C: drive on the machine used for these samples
has more than 200MB of free disk space. This number is correct.</P>
<P>Now you know how to write real functions in a DLL and use them yourself or make
them available for others.</P>
<P>
<H2><A NAME="Heading8"></A>Sending Messages and Commands</H2>
<P>As discussed in Chapter 3, &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 such as the WM_COMMAND
message with the button's resource ID as one of its parameters. You can ignore the
lower-level messages if you want; 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: CWnd::SendMessage() and CWnd::PostMessage().
Each of these gets a message to an object that inherits from CWnd. 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>
<P>
<PRE>CWnd* m_messagewindow;
UINT m_message;
</PRE>
<P>Messages are represented by unsigned integers. They appear to have names only
because names like WM_MOUSEMOVE are connected to integers with #define statements.</P>
<P>The sending class has a member function to set these member variables, typically
very short:</P>
<P>
<PRE>void Sender::SetReceiveTarget(CWnd *window, UINT message)
{
    m_messagewindow = window;
    m_message = message;
}
</PRE>
<P>When the sending class needs to get a message to the window, it calls SendMessage():</P>
<P>
<PRE>    m_messagewindow-&gt;SendMessage(m_message, wparam, lparam);
</PRE>
<P>or PostMessage():</P>
<P>
<PRE>    m_messagewindow-&gt;PostMessage(m_message, wparam, lparam);
</PRE>
<P>The difference between sending and posting a message is that SendMessage() does
not return until the message has been handled by the window that received it, but
PostMessage() 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 lparam, and
then delete the object, you should choose SendMessage() because you can't delete
the object until you are sure that the message- handling code has finished with it.
If you aren't passing pointers, you can probably use PostMessage() and move on as
soon as the message has been added to the queue.</P>
<P>The meaning of the wparam and lparam 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>
<P>
<PRE>#define WM_HELLO WM_USER + 300
</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>
<P>
<PRE>BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
     //{{AFX_MSG_MAP(CMainFrame)
          // NOTE - the ClassWizard will add and remove mapping macros here.
          //    DO NOT EDIT what you see in these blocks of generated code!
     //}}AFX_MSG_MAP
     ON_MESSAGE(WM_HELLO, OnHello)
END_MESSAGE_MAP()
</PRE>
<P>The entry added outside the //AFX_MSG_MAP comments catches the WM_HELLO message
and arranges for the OnHello() function to be called. The header file message map
might look like this:</P>
<P>
<PRE>// Generated message map functions
protected:
     //{{AFX_MSG(CMainFrame)
     afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
          // NOTE - the ClassWizard will add and remove member functions here.
          //    DO NOT EDIT what you see in these blocks of generated code!
     //}}AFX_MSG
     afx_msg LRESULT OnHello(WPARAM wParam, LPARAM lParam);
     DECLARE_MESSAGE_MAP()
</PRE>
<P>Then you add an implementation of OnHello() to the source file to complete the
process.</P>
<P>
<H2><A NAME="Heading9"></A>Considering International Software Development Issues</H2>
<P>International boundaries are shrinking at incredible rates. As the Internet and
other methods of cheap international software distribution continue to grow, so will
the demand for components built by vendors worldwide. 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 invented in the United States, which explains why we have
8-bit character-based operating systems. There are only 26 letters in our alphabet
and 10 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. (For more information, check <B>www.unicode.org</B>.)</P>
<P>Unicode uses two bytes for each character, whereas ASCII uses only one. One byte
(8 bits) can represent 2<SUP>8</SUP> 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 5,000 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--a Unicode.</P>
<P>MFC has full Unicode support, with Unicode versions of almost every function.
For example, consider the function CWnd::SetWindowText(). 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, two different functions 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 to SetWindowTextW if you are.</P>
<P>
<H4>Listing 28.8&#160;&#160;Microsoft's WINUSER.H Implementing Unicode<BR>
Support</H4>
<PRE>WINUSERAPI BOOL WINAPI SetWindowTextA(HWND hWnd, LPCSTR lpString);
WINUSERAPI BOOL WINAPI SetWindowTextW(HWND hWnd, LPCWSTR lpString);
#ifdef UNICODE
#define SetWindowText  SetWindowTextW
#else
#define SetWindowText  SetWindowTextA
</PRE>
<PRE>#endif // !UNICODE
</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 (such as &quot;Hello&quot;)
to a function, wrap it in the _T macro, like this:</P>
<P>
<PRE>pWnd-&gt;SetWindowText(_T(&quot;Hello&quot;));
</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>
<HR>
<STRONG>NOTE:</STRONG> Windows 95 was built on earlier versions of 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 it 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. 
<HR>
</P>

</BLOCKQUOTE>

<CENTER>
<P>
<HR>
<A HREF="ch27.htm" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/ch27/ch27.htm"><IMG SRC="previous.gif" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="apa.htm" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/apa/apa.htm"><IMG
SRC="next.gif" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"
BORDER="0"></A><A HREF="index.htm" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/index.htm"><IMG SRC="contents.gif" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A><BR>
</P>

<P>&#169; <A HREF="copy.htm" tppabs="http://www.fintech.ru/library/prog/SEUsingVC6/copy.htm">Copyright</A>, Macmillan Computer Publishing. All
rights reserved.
</CENTER>


</BODY>

</HTML>

⌨️ 快捷键说明

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