﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-franksunny的个人技术空间-随笔分类-MFC相关技术</title><link>http://www.cppblog.com/franksunny/category/2638.html</link><description>获得人生中的成功需要的专注与坚持不懈多过天才与机会。

                       ——C.W. Wendte</description><language>zh-cn</language><lastBuildDate>Sat, 22 Oct 2011 14:45:53 GMT</lastBuildDate><pubDate>Sat, 22 Oct 2011 14:45:53 GMT</pubDate><ttl>60</ttl><item><title>使用SHBrowseForFolder函数打开文件目录对话框</title><link>http://www.cppblog.com/franksunny/archive/2010/12/30/137754.html</link><dc:creator>frank.sunny</dc:creator><author>frank.sunny</author><pubDate>Thu, 30 Dec 2010 10:35:00 GMT</pubDate><guid>http://www.cppblog.com/franksunny/archive/2010/12/30/137754.html</guid><wfw:comment>http://www.cppblog.com/franksunny/comments/137754.html</wfw:comment><comments>http://www.cppblog.com/franksunny/archive/2010/12/30/137754.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/franksunny/comments/commentRss/137754.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/franksunny/services/trackbacks/137754.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 使用SHBrowseForFolder函数打开文件目录对话框&nbsp;&nbsp;<a href='http://www.cppblog.com/franksunny/archive/2010/12/30/137754.html'>阅读全文</a><img src ="http://www.cppblog.com/franksunny/aggbug/137754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/franksunny/" target="_blank">frank.sunny</a> 2010-12-30 18:35 <a href="http://www.cppblog.com/franksunny/archive/2010/12/30/137754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于内存映射文件处理</title><link>http://www.cppblog.com/franksunny/archive/2007/03/30/20974.html</link><dc:creator>frank.sunny</dc:creator><author>frank.sunny</author><pubDate>Fri, 30 Mar 2007 13:16:00 GMT</pubDate><guid>http://www.cppblog.com/franksunny/archive/2007/03/30/20974.html</guid><wfw:comment>http://www.cppblog.com/franksunny/comments/20974.html</wfw:comment><comments>http://www.cppblog.com/franksunny/archive/2007/03/30/20974.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/franksunny/comments/commentRss/20974.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/franksunny/services/trackbacks/20974.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关于内存映射文件处理</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">今天看到一篇文章讲内存映射文件的处理，虽然自己没有处理过如此大的文件系统，但是好奇就也看了下，谁知道自己以后会不会用到或考到这方面的知识。所以就给自己</span>
				<span lang="EN-US">mark</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一下，增加点自己的印象。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">首先，通过</span>
				<span lang="EN-US">CreateFile()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数来创建或打开一个文件内核对象，这个对象标识了磁盘上将要用作内存映射文件的文件。（其实是获取文件句柄）</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其次，通过</span>
				<span lang="EN-US">CreateFileMapping()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数来为刚才创建的文件内核对象创建一个文件映射内核对象并告诉系统文件的尺寸以及访问文件的方式。（获取文件映射内核对象的句柄）</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">再次，通过</span>
				<span lang="EN-US">MapViewOfFile()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数将文件内核映射对象添加到进程中。（获取映射内核对象的指针）</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接着，程序就可以通过指针进行常规的文件读取了，这里的操作就和文件操作一样，不做展开。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">用完之后，还得回收，先用</span>
				<span lang="EN-US">UnmapViewOfFile()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将释放映射内核对象指针，然后通过</span>
				<span lang="EN-US">CloseHandle</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关闭之前创建的文件映射内核对象句柄和文件内核对象句柄。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以下是我找到的文章的出处：</span>
				<span lang="EN-US">
						<a href="http://newcactus.bokee.com/viewdiary.15316244.html">http://newcactus.bokee.com/viewdiary.15316244.html</a>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下面纯粹是粘贴别人的作品：</span>
		</p>
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
				<b>
						<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: #333399; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">VC++</span>
				</b>
				<b>
						<span style="FONT-SIZE: 12pt; COLOR: #333399; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">中使用内存映射文件处理大文件</span>
				</b>
				<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 12pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
				<b>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">摘要：</span>
				</b>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> 本文给出了一种方便实用的解决大文件的读取、存储等处理的方法，并结合相关程序代码对具体的实现过程进行了介绍。<span lang="EN-US"><br /><br /></span>　　引言<span lang="EN-US"><br /><br /></span>　　文件操作是应用程序最为基本的功能之一，<span lang="EN-US">Win32 API</span>和<span lang="EN-US">MFC</span>均提供有支持文件处理的函数和类，常用的有<span lang="EN-US">Win32 API</span>的<span lang="EN-US">CreateFile()</span>、<span lang="EN-US">WriteFile()</span>、<span lang="EN-US">ReadFile()</span>和<span lang="EN-US">MFC</span>提供的<span lang="EN-US">CFile</span>类等。一般来说，以上这些函数可以满足大多数场合的要求，但是对于某些特殊应用领域所需要的动辄几十<span lang="EN-US">GB</span>、几百<span lang="EN-US">GB</span>、乃至几<span lang="EN-US">TB</span>的海量存储，再以通常的文件处理方法进行处理显然是行不通的。目前，对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的，本文下面将针对这种<span lang="EN-US">Windows</span>核心编程技术展开讨论。<span lang="EN-US"><br /><br /></span>　　内存映射文件<span lang="EN-US"><br /><br /></span>　　内存映射文件与虚拟内存有些类似，通过内存映射文件可以保留一个地址空间的区域，同时将物理存储器提交给此区域，只是内存文件映射的物理存储器来自一个已经存在于磁盘上的文件，而非系统的页文件，而且在对该文件进行操作之前必须首先对文件进行映射，就如同将整个文件从磁盘加载到内存。由此可以看出，使用内存映射文件处理存储于磁盘上的文件时，将不必再对文件执行<span lang="EN-US">I/O</span>操作，这意味着在对文件进行处理时将不必再为文件申请并分配缓存，所有的文件缓存操作均由系统直接管理，由于取消了将文件数据加载到内存、数据从内存到文件的回写以及释放内存块等步骤，使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。另外，实际工程中的系统往往需要在多个进程之间共享数据，如果数据量小，处理方法是灵活多变的，如果共享数据容量巨大，那么就需要借助于内存映射文件来进行。实际上，内存映射文件正是解决本地多个进程间数据共享的最有效方法。<span lang="EN-US"><br /><br /></span>　　内存映射文件并不是简单的文件<span lang="EN-US">I/O</span>操作，实际用到了<span lang="EN-US">Windows</span>的核心编程技术<span lang="EN-US">--</span>内存管理。所以，如果想对内存映射文件有更深刻的认识，必须对<span lang="EN-US">Windows</span>操作系统的内存管理机制有清楚的认识，内存管理的相关知识非常复杂，超出了本文的讨论范畴，在此就不再赘述，感兴趣的读者可以参阅其他相关书籍。下面给出使用内存映射文件的一般方法：<span lang="EN-US"><br /><br /></span>　　首先要通过<span lang="EN-US">CreateFile()</span>函数来创建或打开一个文件内核对象，这个对象标识了磁盘上将要用作内存映射文件的文件。在用<span lang="EN-US">CreateFile()</span>将文件映像在物理存储器的位置通告给操作系统后，只指定了映像文件的路径，映像的长度还没有指定。为了指定文件映射对象需要多大的物理存储空间还需要通过<span lang="EN-US">CreateFileMapping()</span>函数来创建一个文件映射内核对象以告诉系统文件的尺寸以及访问文件的方式。在创建了文件映射对象后，还必须为文件数据保留一个地址空间区域，并把文件数据作为映射到该区域的物理存储器进行提交。由<span lang="EN-US">MapViewOfFile()</span>函数负责通过系统的管理而将文件映射对象的全部或部分映射到进程地址空间。此时，对内存映射文件的使用和处理同通常加载到内存中的文件数据的处理方式基本一样，在完成了对内存映射文件的使用时，还要通过一系列的操作完成对其的清除和使用过资源的释放。这部分相对比较简单，可以通过<span lang="EN-US">UnmapViewOfFile()</span>完成从进程的地址空间撤消文件数据的映像、通过<span lang="EN-US">CloseHandle()</span>关闭前面创建的文件映射对象和文件对象。<span lang="EN-US"><br /><br /></span>　　内存映射文件相关函数<span lang="EN-US"><br /><br /></span>　　在使用内存映射文件时，所使用的<span lang="EN-US">API</span>函数主要就是前面提到过的那几个函数，下面分别对其进行介绍：<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<table class="MsoNormalTable" style="BACKGROUND: white; WIDTH: 100%; BORDER-COLLAPSE: collapse; mso-padding-alt: 0cm 0cm 0cm 0cm" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
								<td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 0cm; BORDER-TOP: #ece9d8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">HANDLE CreateFile(LPCTSTR lpFileName,<br />DWORD dwDesiredAccess,<br />DWORD dwShareMode,<br />LPSECURITY_ATTRIBUTES lpSecurityAttributes,<br />DWORD dwCreationDisposition,<br />DWORD dwFlagsAndAttributes, <br />HANDLE hTemplateFile); <o:p></o:p></span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 12pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
						<br />
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　　函数<span lang="EN-US">CreateFile()</span>即使是在普通的文件操作时也经常用来创建、打开文件，在处理内存映射文件时，该函数来创建<span lang="EN-US">/</span>打开一个文件内核对象，并将其句柄返回，在调用该函数时需要根据是否需要数据读写和文件的共享方式来设置参数<span lang="EN-US">dwDesiredAccess</span>和<span lang="EN-US">dwShareMode</span>，错误的参数设置将会导致相应操作时的失败。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<table class="MsoNormalTable" style="BACKGROUND: white; WIDTH: 100%; BORDER-COLLAPSE: collapse; mso-padding-alt: 0cm 0cm 0cm 0cm" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
								<td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 0cm; BORDER-TOP: #ece9d8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">HANDLE CreateFileMapping(HANDLE hFile,<br />LPSECURITY_ATTRIBUTES lpFileMappingAttributes,<br />DWORD flProtect,<br />DWORD dwMaximumSizeHigh,<br />DWORD dwMaximumSizeLow,<br />LPCTSTR lpName); <o:p></o:p></span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 12pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
						<br />
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　　<span lang="EN-US">CreateFileMapping()</span>函数创建一个文件映射内核对象，通过参数<span lang="EN-US">hFile</span>指定待映射到进程地址空间的文件句柄（该句柄由<span lang="EN-US">CreateFile()</span>函数的返回值获取）。由于内存映射文件的物理存储器实际是存储于磁盘上的一个文件，而不是从系统的页文件中分配的内存，所以系统不会主动为其保留地址空间区域，也不会自动将文件的存储空间映射到该区域，为了让系统能够确定对页面采取何种保护属性，需要通过参数<span lang="EN-US">flProtect</span>来设定，保护属性<span lang="EN-US">PAGE_READONLY</span>、<span lang="EN-US">PAGE_READWRITE</span>和<span lang="EN-US">PAGE_WRITECOPY</span>分别表示文件映射对象被映射后，可以读取、读写文件数据。在使用<span lang="EN-US">PAGE_READONLY</span>时，必须确保<span lang="EN-US">CreateFile()</span>采用的是<span lang="EN-US">GENERIC_READ</span>参数；<span lang="EN-US">PAGE_READWRITE</span>则要求<span lang="EN-US">CreateFile()</span>采用的是<span lang="EN-US">GENERIC_READ|GENERIC_WRITE</span>参数；至于属性<span lang="EN-US">PAGE_WRITECOPY</span>则只需要确保<span lang="EN-US">CreateFile()</span>采用了<span lang="EN-US">GENERIC_READ</span>和<span lang="EN-US">GENERIC_WRITE</span>其中之一即可。<span lang="EN-US">DWORD</span>型的参数<span lang="EN-US">dwMaximumSizeHigh</span>和<span lang="EN-US">dwMaximumSizeLow</span>也是相当重要的，指定了文件的最大字节数，由于这两个参数共<span lang="EN-US">64</span>位，因此所支持的最大文件长度为<span lang="EN-US">16EB</span>，几乎可以满足任何大数据量文件处理场合的要求。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<table class="MsoNormalTable" style="BACKGROUND: white; WIDTH: 100%; BORDER-COLLAPSE: collapse; mso-padding-alt: 0cm 0cm 0cm 0cm" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
								<td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 0cm; BORDER-TOP: #ece9d8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">LPVOID MapViewOfFile(HANDLE hFileMappingObject,<br />DWORD dwDesiredAccess,<br />DWORD dwFileOffsetHigh,<br />DWORD dwFileOffsetLow,<br />DWORD dwNumberOfBytesToMap);<o:p></o:p></span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 12pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
						<br />
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　　<span lang="EN-US">MapViewOfFile()</span>函数负责把文件数据映射到进程的地址空间，参数<span lang="EN-US">hFileMappingObject</span>为<span lang="EN-US">CreateFileMapping()</span>返回的文件映像对象句柄。参数<span lang="EN-US">dwDesiredAccess</span>则再次指定了对文件数据的访问方式，而且同样要与<span lang="EN-US">CreateFileMapping()</span>函数所设置的保护属性相匹配。虽然这里一再对保护属性进行重复设置看似多余，但却可以使应用程序能更多的对数据的保护属性实行有效控制。<span lang="EN-US">MapViewOfFile()</span>函数允许全部或部分映射文件，在映射时，需要指定数据文件的偏移地址以及待映射的长度。其中，文件的偏移地址由<span lang="EN-US">DWORD</span>型的参数<span lang="EN-US">dwFileOffsetHigh</span>和<span lang="EN-US">dwFileOffsetLow</span>组成的<span lang="EN-US">64</span>位值来指定，而且必须是操作系统的分配粒度的整数倍，对于<span lang="EN-US">Windows</span>操作系统，分配粒度固定为<span lang="EN-US">64KB</span>。当然，也可以通过如下代码来动态获取当前操作系统的分配粒度：<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<table class="MsoNormalTable" style="BACKGROUND: white; WIDTH: 100%; BORDER-COLLAPSE: collapse; mso-padding-alt: 0cm 0cm 0cm 0cm" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
								<td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 0cm; BORDER-TOP: #ece9d8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">SYSTEM_INFO sinf;<br />GetSystemInfo(&amp;sinf);<br />DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;<o:p></o:p></span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 12pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
						<br />
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　　参数<span lang="EN-US">dwNumberOfBytesToMap</span>指定了数据文件的映射长度，这里需要特别指出的是，对于<span lang="EN-US">Windows 9x</span>操作系统，如果<span lang="EN-US">MapViewOfFile()</span>无法找到足够大的区域来存放整个文件映射对象，将返回空值（<span lang="EN-US">NULL</span>）；但是在<span lang="EN-US">Windows 2000</span>下，<span lang="EN-US">MapViewOfFile()</span>只需要为必要的视图找到足够大的一个区域即可，而无须考虑整个文件映射对象的大小。<span lang="EN-US"><br /><br /></span>　　在完成对映射到进程地址空间区域的文件处理后，需要通过函数<span lang="EN-US">UnmapViewOfFile()</span>完成对文件数据映像的释放，该函数原型声明如下：<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<table class="MsoNormalTable" style="BACKGROUND: white; WIDTH: 100%; BORDER-COLLAPSE: collapse; mso-padding-alt: 0cm 0cm 0cm 0cm" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
								<td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 0cm; BORDER-TOP: #ece9d8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);<o:p></o:p></span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 12pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
						<br />
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　　唯一的参数<span lang="EN-US">lpBaseAddress</span>指定了返回区域的基地址，必须将其设定为<span lang="EN-US">MapViewOfFile()</span>的返回值。在使用了函数<span lang="EN-US">MapViewOfFile()</span>之后，必须要有对应的<span lang="EN-US">UnmapViewOfFile()</span>调用，否则在进程终止之前，保留的区域将无法释放。除此之外，前面还曾由<span lang="EN-US">CreateFile()</span>和<span lang="EN-US">CreateFileMapping()</span>函数创建过文件内核对象和文件映射内核对象，在进程终止之前有必要通过<span lang="EN-US">CloseHandle()</span>将其释放，否则将会出现资源泄漏的问题。<span lang="EN-US"><br /><br /></span>　　除了前面这些必须的<span lang="EN-US">API</span>函数之外，在使用内存映射文件时还要根据情况来选用其他一些辅助函数。例如，在使用内存映射文件时，为了提高速度，系统将文件的数据页面进行高速缓存，而且在处理文件映射视图时不立即更新文件的磁盘映像。为解决这个问题可以考虑使用<span lang="EN-US">FlushViewOfFile()</span>函数，该函数强制系统将修改过的数据部分或全部重新写入磁盘映像，从而可以确保所有的数据更新能及时保存到磁盘。<span lang="EN-US"><br /></span><b><span style="COLOR: #ac0000">使用内存映射文件处理大文件应用示例<span lang="EN-US"><br /><br /></span></span></b>　　下面结合一个具体的实例来进一步讲述内存映射文件的使用方法。该实例从端口接收数据，并实时将其存放于磁盘，由于数据量大（几十<span lang="EN-US">GB</span>），在此选用内存映射文件进行处理。下面给出的是位于工作线程<span lang="EN-US">MainProc</span>中的部分主要代码，该线程自程序运行时启动，当端口有数据到达时将会发出事件<span lang="EN-US">hEvent[0]</span>，<span lang="EN-US">WaitForMultipleObjects()</span>函数等待到该事件发生后将接收到的数据保存到磁盘，如果终止接收将发出事件<span lang="EN-US">hEvent[1]</span>，事件处理过程将负责完成资源的释放和文件的关闭等工作。下面给出此线程处理函数的具体实现过程：<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<table class="MsoNormalTable" style="BACKGROUND: white; WIDTH: 100%; BORDER-COLLAPSE: collapse; mso-padding-alt: 0cm 0cm 0cm 0cm" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
								<td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 0cm; BORDER-TOP: #ece9d8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">……<br />// </span>
												<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">创建文件内核对象，其句柄保存于<span lang="EN-US">hFile<br />HANDLE hFile = CreateFile("Recv1.zip",<br />GENERIC_WRITE | GENERIC_READ,<br />FILE_SHARE_READ, <br />NULL,<br />CREATE_ALWAYS, <br />FILE_FLAG_SEQUENTIAL_SCAN, <br />NULL);<br /><br />// </span>创建文件映射内核对象，句柄保存于<span lang="EN-US">hFileMapping<br />HANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE, <br />0, 0x4000000, NULL);<br />// </span>释放文件内核对象<span lang="EN-US"><br />CloseHandle(hFile);<br /><br />// </span>设定大小、偏移量等参数<span lang="EN-US"><br />__int64 qwFileSize = 0x4000000;<br />__int64 qwFileOffset = 0;<br />__int64 T = 600 * sinf.dwAllocationGranularity;<br />DWORD dwBytesInBlock = 1000 * sinf.dwAllocationGranularity;<br /><br />// </span>将文件数据映射到进程的地址空间<span lang="EN-US"><br />PBYTE pbFile = (PBYTE)MapViewOfFile(hFileMapping,<br />FILE_MAP_ALL_ACCESS,<br />(DWORD)(qwFileOffset&gt;&gt;32), (DWORD)(qwFileOffset&amp;0xFFFFFFFF), dwBytesInBlock);<br />while(bLoop) <br />{<br />// </span>捕获事件<span lang="EN-US">hEvent[0]</span>和事件<span lang="EN-US">hEvent[1]<br />DWORD ret = WaitForMultipleObjects(2, hEvent, FALSE, INFINITE); <br />ret -= WAIT_OBJECT_0;<br />switch (ret)<br />{<br />// </span>接收数据事件触发<span lang="EN-US"><br />case 0:<br />// </span>从端口接收数据并保存到内存映射文件<span lang="EN-US"><br />nReadLen=syio_Read(port[1], pbFile + qwFileOffset, QueueLen);<br />qwFileOffset += nReadLen;<br /><br />// </span>当数据写满<span lang="EN-US">60%</span>时，为防数据溢出，需要在其后开辟一新的映射视图<span lang="EN-US"><br />if (qwFileOffset &gt; T)<br />{<br />T = qwFileOffset + 600 * sinf.dwAllocationGranularity;<br />UnmapViewOfFile(pbFile);<br />pbFile = (PBYTE)MapViewOfFile(hFileMapping,<br />FILE_MAP_ALL_ACCESS,<br />(DWORD)(qwFileOffset&gt;&gt;32), (DWORD)(qwFileOffset&amp;0xFFFFFFFF), dwBytesInBlock);<br />}<br />break;<br /><br />// </span>终止事件触发<span lang="EN-US"><br />case 1:<br />bLoop = FALSE;<br /><br />// </span>从进程的地址空间撤消文件数据映像<span lang="EN-US"><br />UnmapViewOfFile(pbFile);<br /><br />// </span>关闭文件映射对象<span lang="EN-US"><br />CloseHandle(hFileMapping);<br />break;<br />}<br />}<br />…<o:p></o:p></span></span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="BACKGROUND: white; MARGIN: 0cm 0cm 12pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
				<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
						<br />
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　　在终止事件触发处理过程中如果只简单的执行<span lang="EN-US">UnmapViewOfFile()</span>和<span lang="EN-US">CloseHandle()</span>函数将无法正确标识文件的实际大小，即如果开辟的内存映射文件为<span lang="EN-US">30GB</span>，而接收的数据只有<span lang="EN-US">14GB</span>，那么上述程序执行完后，保存的文件长度仍是<span lang="EN-US">30GB</span>。也就是说，在处理完成后还要再次通过内存映射文件的形式将文件恢复到实际大小，下面是实现此要求的主要代码：<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<table class="MsoNormalTable" style="BACKGROUND: white; WIDTH: 100%; BORDER-COLLAPSE: collapse; mso-padding-alt: 0cm 0cm 0cm 0cm" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
								<td style="BORDER-RIGHT: #ece9d8; PADDING-RIGHT: 0cm; BORDER-TOP: #ece9d8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; PADDING-TOP: 0cm; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align="left">
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">// </span>
												<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">创建另外一个文件内核对象<span lang="EN-US"><br />hFile2 = CreateFile("Recv.zip", <br />GENERIC_WRITE | GENERIC_READ,<br />FILE_SHARE_READ, <br />NULL,<br />CREATE_ALWAYS, <br />FILE_FLAG_SEQUENTIAL_SCAN,<br />NULL);<br /><br />// </span>以实际数据长度创建另外一个文件映射内核对象<span lang="EN-US"><br />hFileMapping2 = CreateFileMapping(hFile2,<br />NULL, <br />PAGE_READWRITE,<br />0,<br />(DWORD)(qwFileOffset&amp;0xFFFFFFFF),<br />NULL);<br /><br />// </span>关闭文件内核对象<span lang="EN-US"><br />CloseHandle(hFile2);<br /><br />// </span>将文件数据映射到进程的地址空间<span lang="EN-US"><br />pbFile2 = (PBYTE)MapViewOfFile(hFileMapping2, <br />FILE_MAP_ALL_ACCESS, <br />0, 0, qwFileOffset);<br /><br />// </span>将数据从原来的内存映射文件复制到此内存映射文件<span lang="EN-US"><br />memcpy(pbFile2, pbFile, qwFileOffset); <br /><br />file://</span>从进程的地址空间撤消文件数据映像<span lang="EN-US"><br />UnmapViewOfFile(pbFile);<br />UnmapViewOfFile(pbFile2);<br /><br />// </span>关闭文件映射对象<span lang="EN-US"><br />CloseHandle(hFileMapping);<br />CloseHandle(hFileMapping2);<br /><br />// </span>删除临时文件<span lang="EN-US"><br />DeleteFile("Recv1.zip");<o:p></o:p></span></span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">
						<br />
				</span>
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">　　结论<span lang="EN-US"><br /><br /></span>　　经实际测试，内存映射文件在处理大数据量文件时表现出了良好的性能，比通常使用<span lang="EN-US">CFile</span>类和<span lang="EN-US">ReadFile()</span>和<span lang="EN-US">WriteFile()</span>等函数的文件处理方式具有明显的优势。本文所述代码在<span lang="EN-US">Windows 98</span>下由<span lang="EN-US">Microsoft Visual C++ 6.0</span>编译通过。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
<img src ="http://www.cppblog.com/franksunny/aggbug/20974.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/franksunny/" target="_blank">frank.sunny</a> 2007-03-30 21:16 <a href="http://www.cppblog.com/franksunny/archive/2007/03/30/20974.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Windows平台下的多线程编程</title><link>http://www.cppblog.com/franksunny/archive/2007/01/26/18029.html</link><dc:creator>frank.sunny</dc:creator><author>frank.sunny</author><pubDate>Fri, 26 Jan 2007 14:10:00 GMT</pubDate><guid>http://www.cppblog.com/franksunny/archive/2007/01/26/18029.html</guid><wfw:comment>http://www.cppblog.com/franksunny/comments/18029.html</wfw:comment><comments>http://www.cppblog.com/franksunny/archive/2007/01/26/18029.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/franksunny/comments/commentRss/18029.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/franksunny/services/trackbacks/18029.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 虽然自己用多线程编程用过一阵子，但是未曾仔细了解过概念，用的也是乱乱的，今天看到一篇线程总结的文章，感觉讲的很好，Windows下的多线程也就是了解了线程的概念然后加一同步代码就行了。																Windows平台下的多线程编程																																				 															...&nbsp;&nbsp;<a href='http://www.cppblog.com/franksunny/archive/2007/01/26/18029.html'>阅读全文</a><img src ="http://www.cppblog.com/franksunny/aggbug/18029.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/franksunny/" target="_blank">frank.sunny</a> 2007-01-26 22:10 <a href="http://www.cppblog.com/franksunny/archive/2007/01/26/18029.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>枚举串口四法</title><link>http://www.cppblog.com/franksunny/archive/2006/10/10/13551.html</link><dc:creator>frank.sunny</dc:creator><author>frank.sunny</author><pubDate>Tue, 10 Oct 2006 15:31:00 GMT</pubDate><guid>http://www.cppblog.com/franksunny/archive/2006/10/10/13551.html</guid><wfw:comment>http://www.cppblog.com/franksunny/comments/13551.html</wfw:comment><comments>http://www.cppblog.com/franksunny/archive/2006/10/10/13551.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/franksunny/comments/commentRss/13551.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/franksunny/services/trackbacks/13551.html</trackback:ping><description><![CDATA[@import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
<p class="MsoNormal" style="margin: 0cm 0cm 0pt">
<p align="left">&nbsp;</p>
<p align="center"><strong>枚举串口四法</strong></p>
<p align="left">&nbsp;</p>
<p align="left">串口作为最基本的电脑通信&nbsp;I/O&nbsp;接口，其使用虽然在&nbsp;PC&nbsp;上越来越少，但是在工业仪器领域仍然用的相当普遍，由于笔者工作中需要用到串口，而且发现枚举串口至今仍未搞得很清楚，为此自己先整理下，希望大侠和同行们对我不懂和错误的地方指点一下。</p>
<p align="left">&nbsp;</p>
<p align="left">1&nbsp;、查询注册表</p>
<p align="left">查询注册表的方法是网上见到的比较常见的方法，该方法就是使用编程方法读取注册表内信息，相当于用户通过在运行框内输入&nbsp;&#8221;regedit&#8221;&nbsp;（或&nbsp;regedit32&nbsp;）直接打开注册表，查看&#8220;&nbsp;HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM&nbsp;&#8221;项来获取串口信息。以下是源代码：</p>
<p>CString&nbsp;&nbsp;&nbsp;strSerialList[256];&nbsp;&nbsp;//&nbsp;临时定义&nbsp;256&nbsp;个字符串组，因为系统最多也就&nbsp;256&nbsp;个</p>
<p>HKEY hKey;</p>
<p><span>LPCTSTR
data_Set="HARDWARE\\DEVICEMAP\\SERIALCOMM\\";</span></p>
<p><span>long ret0 =
(::RegOpenKeyEx(HKEY_LOCAL_MACHINE, data_Set, 0, KEY_READ, &amp;hKey));</span></p>
<p><span>if(ret0 !=
ERROR_SUCCESS)</span></p>
<p>{</p>
<p>return -1;</p>
<p>}</p>
<p>int i = 0;</p>
<p>CHAR Name[25];</p>
<p><span>UCHAR
szPortName[25];</span></p>
<p>LONG Status;</p>
<p><span>DWORD dwIndex =
0;</span></p>
<p>DWORD dwName;</p>
<p><span>DWORD
dwSizeofPortName;</span></p>
<p>DWORD Type;</p>
<p><span>dwName =
sizeof(Name);</span></p>
<p><span>dwSizeofPortName
= sizeof(szPortName);</span></p>
<p>do</p>
<p>{</p>
<p><span>Status =
RegEnumValue(hKey, dwIndex++, Name, &amp;dwName, NULL, &amp;Type,</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;szPortName,
&amp;dwSizeofPortName);</span></p>
<p><span>if((Status ==
ERROR_SUCCESS)||(Status == ERROR_MORE_DATA))</span></p>
<p>{</p>
<p><span>strSerialList[i]
= CString(szPortName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;</span>串口字符串保存</p>
<p>i++;//&nbsp;串口计数</p>
<p>&nbsp;&nbsp;&nbsp;}</p>
<p><span>} while((Status
== ERROR_SUCCESS)||(Status == ERROR_MORE_DATA));</span></p>
<p>RegCloseKey(hKey);</p>
<p align="left">以上方法同样也可以实现对并口的查询，只要将&nbsp;"HARDWARE \\ DEVICEMAP\\ SERIALCOMM\\"&nbsp;用&nbsp;"HARDWARE\\DEVICEMAP\\PARALLEL PORTS\\"&nbsp;代替就行了。</p>
<p align="left">比较：该方法时间最省，笔者在自己电脑上试过，在&nbsp;1ms&nbsp;（少于&nbsp;1ms&nbsp;的我也不知道怎么编程计时）内即可完成；同时也可解决&nbsp;usb&nbsp;转串口设备的问题，比较实用，唯一缺点是，如果用户在装某些软硬件时在注册表中注册了虚拟串口之类的，用此法枚举得到的该类串口实际上是不能当串口用的。</p>
<p align="left">&nbsp;</p>
<p align="left">2&nbsp;、使用&nbsp;EnumPort&nbsp;方法</p>
<p align="left">该方法调用&nbsp;EnumPort&nbsp;（）&nbsp;API&nbsp;函数，该函数本身就是枚举电脑端口用的，它枚举的并非只有串口，所以必须对其所得串口进行分析选择，以下是源代码：</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int
m_nSerialPortNum(0);//&nbsp;</span>串口计数</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CString&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strSerialList[256];&nbsp;&nbsp;//&nbsp;临时定义&nbsp;256&nbsp;个字符串组</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPBYTE
pBite&nbsp;&nbsp;= NULL;</span></p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD
pcbNeeded = 0;&nbsp;&nbsp;// bytes received or required</span></p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD
pcReturned = 0;&nbsp;&nbsp;// number of ports received</span></p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_nSerialPortNum
= 0;</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;获取端口信息，能得到端口信息的大小&nbsp;pcbNeeded</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EnumPorts(NULL,
2, pBite, 0, &amp;pcbNeeded, &amp;pcReturned);</span></p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pBite
= new BYTE[pcbNeeded];</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;枚举端口，能得到端口的具体信息&nbsp;pBite&nbsp;以及端口的的个数&nbsp;pcReturned</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EnumPorts(NULL,
2, pBite, pcbNeeded, &amp;pcbNeeded, &amp;pcReturned);</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PORT_INFO_2 *pPort;</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pPort
= (PORT_INFO_2*)pBite;</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>for ( i =
0; i &lt; pcReturned; i++)</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CString
str = pPort[i].pPortName;</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;串口信息的具体确定</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if
(str.Left(3) == "COM")</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strSerialList[m_nSerialPortNum]
= str.Left(strlen(str) - 1);</span></p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//CString
temp = str.Right(strlen(str) - 3);//&nbsp;</span>下面两行注释获取串口序号用</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//m_nSerialPortNo[m_nSerialPortNum]
= atoi(temp.Left(strlen(temp) - 1));</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_nSerialPortNum++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p align="left">以上方法除了串口，还可以枚举所有的并口和打印机等接口，而且能找到虚拟串口（这些串口有些未使用时，在注册表和硬件设备管理器中是不能取得的）。但是该方法稍微耗时些，笔者在自己电脑上试过，大概需要几十&nbsp;ms&nbsp;，主要问题是该方法有些&nbsp;usb&nbsp;串口并不能查到，所以该方法并不可靠。</p>
<p align="left">&nbsp;</p>
<p align="left">3&nbsp;、依次打开串口的方法</p>
<p align="left">该方法就是中规中矩的依次打开串口，看打开是否成功来判断串口的有无，该方法源代码如下：</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int
m_nSerialPortNum(0);//&nbsp;</span>串口数</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CString&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strSerialList[256];&nbsp;&nbsp;//&nbsp;临时定义&nbsp;30&nbsp;个字符串组</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int nCom = 0;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int count = 0;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE hCom;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do {</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nCom++;</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strCom.Format("COM%d",
nCom);</span></p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hCom
= CreateFile(strCom, 0, 0, 0,</span></p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);</span></p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(INVALID_HANDLE_VALUE
== hCom )</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strSerialList[m_nSerialPortNum]
= strCom;</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_nSerialPortNum++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hCom);</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} while(1);</p>
<p align="left">以上方法枚举的都是当前可用的串口，如果有一个串口当前被占用则其后的串口也将无法枚举得到，当然以上方法也可以改成调用&nbsp;for&nbsp;循环让其枚举打开&nbsp;256&nbsp;个串口的方法以避免上述情况，不过该方法比前两种更耗时（一般查找一个串口就要&nbsp;15ms&nbsp;左右），不过可以枚举得到所有当前可打开的串口，当然不能枚举得到一些虚拟串口。</p>
<p align="left">&nbsp;</p>
<p align="left">4&nbsp;、使用&nbsp;SetupAPI&nbsp;函数集的方法</p>
<p align="left">此种方法是我所见过最简单的方法，之所以简单是因为已经有人将复杂的代码封装起来了，我只需像傻子一样调用就可以完成工作了，具体的说明请看<a href="http://www.codeguru.com/Cpp/W-P/system/hardwareinformation/article.php/c5721/">http://www.codeguru.com/Cpp/W-P/system/hardwareinformation/article.php/c5721/</a>&nbsp;，下面给出本人调用该方法的例子代码：</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int
m_nSerialPortNum(0);//&nbsp;</span>串口计数</p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CString&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strSerialList[256];&nbsp;&nbsp;//&nbsp;临时定义&nbsp;256&nbsp;个字符串组</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CArray&lt;SSerInfo,SSerInfo&amp;&gt;
asi;</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EnumSerialPorts(asi,TRUE);//&nbsp;参数为&nbsp;TRUE&nbsp;<span>时枚举当前可以打开的串口，<span>&nbsp;<br />
</span></span>//&nbsp;否则枚举所有串口</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_nSerialPortNum
= asi.GetSize();</span></p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (int i=0;
i&lt;asi.GetSize(); i++)</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p align="left"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CString
str = asi[i].strFrien dlyName;</span></p>
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p align="left">补充说明一下，使用该方法只要在你的程序中，添加&#8220;&nbsp;EnumSerial.cpp&nbsp;&#8221;和&#8220;&nbsp;EnumSerial.h&nbsp;&#8221;两个文件，并且将&nbsp;Setupapi.lib&nbsp;包含进你的工程文件中就行了，该方法时间上来说可能和第三种方法差不多，但该方法获取的串口完完全全就是硬件设备管理器中的串口。</p>
<p align="left">以上是笔者对枚举串口几种方法的小结，有些没弄明白或含糊的地方，还请指正。</p>
<p align="left"><strong>&nbsp;</strong></p>
<p>&nbsp;</p>
</p>
<span style="font-size: 22pt; font-family: 华文新魏; ">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: center" align="center">
</p>
</span><img src ="http://www.cppblog.com/franksunny/aggbug/13551.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/franksunny/" target="_blank">frank.sunny</a> 2006-10-10 23:31 <a href="http://www.cppblog.com/franksunny/archive/2006/10/10/13551.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何去除对话框默认的Enter和Esc按键响应</title><link>http://www.cppblog.com/franksunny/archive/2006/09/19/12694.html</link><dc:creator>frank.sunny</dc:creator><author>frank.sunny</author><pubDate>Mon, 18 Sep 2006 22:49:00 GMT</pubDate><guid>http://www.cppblog.com/franksunny/archive/2006/09/19/12694.html</guid><wfw:comment>http://www.cppblog.com/franksunny/comments/12694.html</wfw:comment><comments>http://www.cppblog.com/franksunny/archive/2006/09/19/12694.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/franksunny/comments/commentRss/12694.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/franksunny/services/trackbacks/12694.html</trackback:ping><description><![CDATA[
		<span lang="EN-US" style="COLOR: green">
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="COLOR: green">
								<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center">
						<b style="mso-bidi-font-weight: normal">
								<span style="FONT-SIZE: 16pt; COLOR: green; FONT-FAMILY: 宋体">如何去除对话框默认的<span lang="EN-US">Enter</span>和<span lang="EN-US">Esc</span>按键响应<span lang="EN-US"><o:p></o:p></span></span>
						</b>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
						<span lang="EN-US" style="COLOR: green">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">MFC</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">从简化方便入手，为我们创建的对话框，都增加了一个缺省的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Enter</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Esc</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键响应，前者响应对话框的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDOK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按钮，后者响应</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDCANCEL</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按钮，但是有时我们创建的对话框不需要这个简便的响应操作，奇怪的是我们在去除</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDOK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按钮和</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDCANCEL</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按钮后还是实现不了禁止如上两个缺省按键的响应。那么该如何实现呢，以下便是解决过程（以去除</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Enter</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键响应为例）：</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">首先，利用</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">ClassWizard</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为对话框的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDOK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">添加单击响应函数，去除该函数中默认的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">OnOK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数响应，如下所示</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">void CDialogDemoDlg::OnOK() <o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">{<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">
								<span style="mso-tab-count: 1">      </span>CDialog::OnOK();<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">}<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; LINE-HEIGHT: 150%; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">改为</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">void CDialogDemoDlg::OnOK() <o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">{<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">
								<span style="mso-tab-count: 1">      </span>//CDialog::OnOK();<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">}<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">注：进行如上这步后，显然你不论再怎么按</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Enter</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键都无法使对话框退出了，但是也导致该对话框就算用户用鼠标点击</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDOK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按钮也无法实现对话框默认的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">OnOK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数了。所以这一步只是解决了一个现象问题，本没有真正解决问题。下面我们要恢复这个按钮的功能。</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其次，去除缺省按钮。在资源视图下，将</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDOK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按钮属性栏中的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Default button</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">属性勾去。使得默认</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Enter</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键不再继续响应该按钮。</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第三，恢复</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">OnOk</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数的功能。首先在资源视图中，将</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDOK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按钮的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">ID</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">改变为</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDC_OK(</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这里用户根据需要可以自己设置资源的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">ID)</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；其次为其添加单击响应函数，并在需要执行结束的代码后添加</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">CDialog::OnOK()</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数，如下所示：</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">void CDialogDemoDlg::OnOk() <o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">{<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">
								<span style="mso-tab-count: 1">      </span>......//</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">省其它处理代码</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">
								<span style="mso-tab-count: 1">      </span>CDialog::OnOK();<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green">}<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; LINE-HEIGHT: 150%; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如上所述过程后，整个</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Enter</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键默认响应已经去除，而且也不会影响对话框正常响应</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">OnOK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数的功能，在如上对话框处理后，如果</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDC_OK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按钮的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">TabOrder</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">属性为</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">1</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的话，按</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Enter</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键就相当于鼠标单击</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDC_OK,</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所以用户必须在“</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Layout</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”的“</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Tab Order</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”下面重新布置</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">IDC_OK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">按钮的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">TabOrder</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">顺序。</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">也许细心的读者会发现，有时当不用进行第三步操作时，直接将第一步</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">OnOK()</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数中注释的</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">CDialog::OnOK()</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代码重新启用，也是可以“完成”去除</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Enter</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键默认响应的特性，何必要进行第三步这么复杂的操作，其实不进行第三步操作，并非真正实现了去除</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Enter</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键响应，比如对话框上有一个</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Edit</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">控件时，在编辑</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Edit</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">结束后，用户按下</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Enter</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键，程序就又马上去响应</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">OnOK</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数了。</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">好了，去除对话框</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Enter</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键缺省响应的过程就介绍到这里，读者可以试着去去除</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">Esc</span>
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键的响应。</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 7.8pt 0cm; TEXT-INDENT: 28pt; LINE-HEIGHT: 150%; mso-char-indent-count: 2.0; mso-para-margin-top: .5gd; mso-para-margin-right: 0cm; mso-para-margin-bottom: .5gd; mso-para-margin-left: 0cm">
						<span style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（注，该方法本人也是书上得来，仅做个人总结）</span>
						<span lang="EN-US" style="FONT-SIZE: 14pt; COLOR: green; LINE-HEIGHT: 150%">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				</p>
		</span> <img src ="http://www.cppblog.com/franksunny/aggbug/12694.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/franksunny/" target="_blank">frank.sunny</a> 2006-09-19 06:49 <a href="http://www.cppblog.com/franksunny/archive/2006/09/19/12694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>