??xml version="1.0" encoding="utf-8" standalone="yes"?>久久激情亚洲精品无码?V,久久久91人妻无码精品蜜桃HD,国产香蕉久久精品综合网http://www.shnenglu.com/twzheng/category/3939.html『站在风口浪紧握住鼠标旋{Q? 人在台北心在?/description>zh-cnSun, 14 Mar 2010 17:57:23 GMTSun, 14 Mar 2010 17:57:23 GMT60求windows xp J体?/title><link>http://www.shnenglu.com/twzheng/articles/109710.html</link><dc:creator>谭文?/dc:creator><author>谭文?/author><pubDate>Sun, 14 Mar 2010 16:05:00 GMT</pubDate><guid>http://www.shnenglu.com/twzheng/articles/109710.html</guid><wfw:comment>http://www.shnenglu.com/twzheng/comments/109710.html</wfw:comment><comments>http://www.shnenglu.com/twzheng/articles/109710.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/twzheng/comments/commentRss/109710.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/twzheng/services/trackbacks/109710.html</trackback:ping><description><![CDATA[求windows xp J体版,最好是台湾版的Q要能一步步的手动安?惌双系l?<br><br>找了好几天了Q很多资源都下不?br><br>今天好不Ҏ(gu)下了一个,但是香港版的Q且安装到选择盘符Ӟ键盘所有键都不能用,所以还是无法安?br><br>谢谢各位大哥大姐帮帮忙,弟感激不尽Q?img src ="http://www.shnenglu.com/twzheng/aggbug/109710.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/twzheng/" target="_blank">谭文?/a> 2010-03-15 00:05 <a href="http://www.shnenglu.com/twzheng/articles/109710.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Visual C++U程同步技术剖?/title><link>http://www.shnenglu.com/twzheng/articles/40548.html</link><dc:creator>谭文?/dc:creator><author>谭文?/author><pubDate>Sun, 06 Jan 2008 06:41:00 GMT</pubDate><guid>http://www.shnenglu.com/twzheng/articles/40548.html</guid><wfw:comment>http://www.shnenglu.com/twzheng/comments/40548.html</wfw:comment><comments>http://www.shnenglu.com/twzheng/articles/40548.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/twzheng/comments/commentRss/40548.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/twzheng/services/trackbacks/40548.html</trackback:ping><description><![CDATA[     摘要: Visual C++U程同步技术剖析摘自:(x)天极|作者:(x)中国甉|L传播研究所 郎锐    摘要Q?多线E同步技术是计算Y件开发的重要技术,本文对多U程的各U同步技术的原理和实现进行了初步探讨。  关键词:(x) VC++6.0Q?U程同步Q(f)界区Q事Ӟ互斥Q信号量Q?   阅读目录Q?  使线E同?  临界区  理事g内核对象   信号量内核对象  互斥内核对象   结   ...  <a href='http://www.shnenglu.com/twzheng/articles/40548.html'>阅读全文</a><img src ="http://www.shnenglu.com/twzheng/aggbug/40548.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/twzheng/" target="_blank">谭文?/a> 2008-01-06 14:41 <a href="http://www.shnenglu.com/twzheng/articles/40548.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>句柄的本?/title><link>http://www.shnenglu.com/twzheng/articles/40545.html</link><dc:creator>谭文?/dc:creator><author>谭文?/author><pubDate>Sun, 06 Jan 2008 06:12:00 GMT</pubDate><guid>http://www.shnenglu.com/twzheng/articles/40545.html</guid><wfw:comment>http://www.shnenglu.com/twzheng/comments/40545.html</wfw:comment><comments>http://www.shnenglu.com/twzheng/articles/40545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/twzheng/comments/commentRss/40545.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/twzheng/services/trackbacks/40545.html</trackback:ping><description><![CDATA[<strong style="FONT-SIZE: 18pt">句柄的本?/strong><br><span style="FONT-SIZE: 10pt">摘自 好易教程|?/span><br><br>一、书上定义:(x)<br><br><<Microsoft Windows 3 Developer''s Workshop>>(Microsoft Press,by Richard Wilton)<br>    在Windows环境中,句柄是用来标识项目的Q这些项目包括:(x)模块(module)、Q?task)、实?(instance)、文?file)、内存块(block of memory)、菜?menu)、控?control)、字?font)、资?resource)Q包括图?icon)Q光?(cursor)Q字W串(string){、GDI对象(GDI object)Q包括位?bitmap)Q画?brush)Q元文gQmetafileQ?调色?palette)Q画W?pen)Q区?(region)Q以?qing)设备描q表(device context)?<br><br><<WINDOWS~程短^?gt;>(南京大学出版C?Q?br>    句柄是WONDOWS用来标识被应用程序所建立或用的对象的唯一整数QW(xu)INDOWS使用各种各样的句柄标识诸如应用程序实例,H口Q控Ӟ位图QGDI对象{等。WINDOWS句柄有点象C语言中的文g句柄?<br><br>二、MFC源代码:(x)<br><br>#ifdef STRICT<br>typedef void *HANDLE;<br>#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name<br>#else<br>typedef PVOID HANDLE;<br>#define DECLARE_HANDLE(name) typedef HANDLE name<br>#endif<br><br>DECLARE_HANDLE(HMODULE); <br>DECLARE_HANDLE(HINSTANCE); <br>DECLARE_HANDLE(HLOCAL); <br>DECLARE_HANDLE(HGLOBAL); <br>DECLARE_HANDLE(HDC); <br>DECLARE_HANDLE(HRGN); <br>DECLARE_HANDLE(HWND); <br>DECLARE_HANDLE(HMENU); <br>DECLARE_HANDLE(HACCEL); <br>DECLARE_HANDLE(HTASK); <br><br><br>三、理解:(x)<br>    HANDLE是PVOIDQ也是无类型指针,<br>    上面q些资源的句柄Handles都不q是指向struct的指针,至于q个struct的用处,qM$都说unused了,现在解释下M$q么做的意义Q这是所谓数据封装,你可以在你的E序中把M$的内部结构指针传来传去,可是你却不知道它到底指向的内Ҏ(gu)什么?br><br>    句柄与指针确实是完全不同的两个概c(din)句柄仅仅是一?2位整敎ͼW(xu)IN32中用于标记某个系l或q程的对象,可以理解为对象烦引(׃M$未完全公开相关技术,在一定程度上只能如此理解Q,q个索引更像是一U映关p(从句柄到对象指针的映)Q而不是纯_Ҏ(gu)义上?#8220;数组下标”?<br><br><br>     句柄可以理解为用于指向或标识内存的一?#8220;资源”Q这些资源如Q文?file)、内存块(block of memory)、菜?menu){等。操作系l通过句柄来定位核心对象和pȝ资源?br>    指针即ؓ(f)指向内存?#8220;数据或指?#8221;某一单元?br><br>    说的切一点,句柄实际上是一U指向某U资源的指针Q但与指针又有所不同Q指针对应着一个数据在内存中的地址Q得C指针可以自由地修改该数据。Windowsq不希望一般程序修改其内部数据l构Q因样太不安全。所以Windowsl每个用GlobalAlloc{函数声明的内存区域指定一个句?本质上仍是一个指针,但不要直接操作它)Q^时你只是在调用API函数时利用这个句柄来说明要操作哪D内存?br><br>    <br>四、引喻:(x)<br>   牧童遥指杏花?br>   牧童的手为指针,杏花村的牌子为句柄,杏花村酒店ؓ(f)对象的实? <br><br><br>附注Q获得窗口句柄三U方?br><br>1.HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName) <br><br>   HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName) <br><br>2.HWND WindowFromPoint(POINT& Point)//获得当前鼠标光标位置的窗口HWND<br><br>3.BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)<br><br>   BOOL CALLBACK EnumChildWindows(HWND hWndParent, WNDENUMPROC lpEnumFunc,LPARAM lParam)<br><br>   BOOL CALLBACK EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)<br><br>   BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) <img src ="http://www.shnenglu.com/twzheng/aggbug/40545.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/twzheng/" target="_blank">谭文?/a> 2008-01-06 14:12 <a href="http://www.shnenglu.com/twzheng/articles/40545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于strcpy()与memcpy()比较http://www.shnenglu.com/twzheng/articles/26275.html谭文?/dc:creator>谭文?/author>Wed, 13 Jun 2007 12:57:00 GMThttp://www.shnenglu.com/twzheng/articles/26275.htmlhttp://www.shnenglu.com/twzheng/comments/26275.htmlhttp://www.shnenglu.com/twzheng/articles/26275.html#Feedback0http://www.shnenglu.com/twzheng/comments/commentRss/26275.htmlhttp://www.shnenglu.com/twzheng/services/trackbacks/26275.html关于strcpy()与memcpy()比较

举例Q?/p>

{

byte a[4];// 每一个字节赋数值类?br>
byte c1[4];

byte c2[4];

memcpy(c1, a, sizeof(byte)*4); //正确使用

strcpy((char*)(byte*)c2, (char*)(byte*)a);//错误调用

}

函数原型

   strcpy

   extern char *strcpy(char *dest,char *src);

   #include <string.h>

   功能Q把src所指由NULLl束的字W串复制到dest所指的数组?br>
   说明:src和dest所指内存区域不可以重叠且dest必须有够的I间来容Usrc的字W串?br>
   q回指向dest的指?br>


  memcpy

  extern void *memcpy(void *dest,void *src,unsigned int count);

  #include <string.h>

   功能Q由src所指内存区域复制count个字W串到dest所指内存区?

   说明Qsrc和dest所指内存区域不能重叠,函数q回指向dest的指?函数原型

 

关于memcpy的用?/span>

作用Q在dest处拷贝src处的字节Qƈ以count来计需要拷贝的字节数量Q进行内存的拯?/span>

参数Q?dest:新的存贮区的开始部?nbsp;  srcQ需要拷贝的开始部?nbsp;   countQ需要拷贝的字节数备注:(x)dest,srcQ它们都是从各自的地址处进行写入,如果是p而不?amp;p,那么奖会(x)取得p的|地址Q?在该值的地址处进行读出或写入?/span>

例:(x)  

int* intPoint = new int(3333);  

int* intPoint1;  

//在intPoint1的地址处写入intPoint地址处的|也就是intPoint指针倹{?nbsp;

memcpy( &intPoint1, &intPoint, 4 );

//使intPoint1指向了intPoint. ?  int* intPoint = new int(3333);

cout << *intPoint1 << endl;

可以看出 strcpy() 是处理的字符?遇零l束)Qmemcpy() 是处理一个缓冲区Qvoid*cd的)Q而我们的内容中有数字0Q而数?又是字符串的l尾字符 ' \0' 的数字表玎ͼ字符串拷贝是遇到0q束,所以,如果要拷贝的~冲区如果是非字W串那么尽量用memcpy()Q这样可以避免出错的可能?/p>

]]>
C/C++中回调函数初?/title><link>http://www.shnenglu.com/twzheng/articles/CALLBACK.html</link><dc:creator>谭文?/dc:creator><author>谭文?/author><pubDate>Mon, 21 May 2007 08:51:00 GMT</pubDate><guid>http://www.shnenglu.com/twzheng/articles/CALLBACK.html</guid><wfw:comment>http://www.shnenglu.com/twzheng/comments/24543.html</wfw:comment><comments>http://www.shnenglu.com/twzheng/articles/CALLBACK.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/twzheng/comments/commentRss/24543.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/twzheng/services/trackbacks/24543.html</trackback:ping><description><![CDATA[<h1>C/C++中回调函数初?/h1> <span style="FONT-SIZE: 10pt">[摘自] 天极开发网Qhttp://dev.yesky.com/Q?/span><br><br><strong>         ?br><br></strong>  对于很多初学者来_(d)往往觉得回调函数很神U,很想知道回调函数的工作原理。本文将要解释什么是回调函数、它们有什么好处、ؓ(f)什么要使用它们{等问题Q在开始之前,假设你已l熟知了函数指针?<br><br>  <strong>什么是回调函数Q?/strong><br><br>  而言之,回调函数是一个通过函数指针调用的函数。如果你把函数的指针Q地址Q作为参C递给另一个函敎ͼ当这个指针被用ؓ(f)调用它所指向的函数时Q我们就说这是回调函数?br><br>  <strong>Z么要使用回调函数Q?/strong><br><br>  因ؓ(f)可以把调用者与被调用者分开。调用者不兛_谁是被调用者,所有它需知道的,只是存在一个具有某U特定原型、某些限制条Ӟ如返回gؓ(f)intQ的被调用函数?br><br>  如果想知道回调函数在实际中有什么作用,先假设有q样一U情况,我们要编写一个库Q它提供了某些排序算法的实现Q如冒排序、快速排序、shell排序、shake排序{等Q但Z库更加通用Q不惛_函数中嵌入排序逻辑Q而让使用者来实现相应的逻辑Q或者,惌库可用于多种数据cdQint、float、stringQ,此时Q该怎么办呢Q可以用函数指针,q进行回调?br><br>  回调可用于通知机制Q例如,有时要在E序中设|一个计时器Q每C定时_(d)E序?x)得到相应的通知Q但通知机制的实现者对我们的程序一无所知。而此Ӟ需有一个特定原型的函数指针Q用q个指针来进行回调,来通知我们的程序事件已l发生。实际上QSetTimer() API使用了一个回调函数来通知计时器,而且Q万一没有提供回调函数Q它q会(x)把一个消息发往E序的消息队列?br><br>  另一个用回调机制的API函数是EnumWindow()Q它枚D屏幕上所有的层H口Qؓ(f)每个H口调用一个程序提供的函数Qƈ传递窗口的处理E序。如果被调用者返回一个|ql进行P代,否则Q退出。EnumWindow()q不兛_被调用者在何处Q也不关心被调用者用它传递的处理E序做了什么,它只兛_q回|因ؓ(f)Zq回|它将l箋执行或退出?br><br>  不管怎么_(d)回调函数是l自C语言的,因而,在C++中,应只在与C代码建立接口Q或与已有的回调接口打交道时Q才使用回调函数。除了上q情况,在C++中应使用虚拟Ҏ(gu)或函数符QfunctorQ,而不是回调函数?br><br>  <strong>一个简单的回调函数实现</strong><br><br>  下面创徏了一个sort.dll的动态链接库Q它导出了一个名为CompareFunction的类?-typedef int (__stdcall *CompareFunction)(const byte*, const byte*)Q它?yu)是回调函数的类型。另外,它也导出了两个方法:(x)Bubblesort()和Quicksort()Q这两个Ҏ(gu)原型相同Q但实现了不同的排序法?br><br> <table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1> <tbody> <tr> <td>void DLLDIR __stdcall Bubblesort(byte* array,int size,int elem_size,CompareFunction cmpFunc);<br><br>void DLLDIR __stdcall Quicksort(byte* array,int size,int elem_size,CompareFunction cmpFunc);</td> </tr> </tbody> </table> <br>  q两个函数接受以下参敎ͼ(x)<br><br>  ·byte * arrayQ指向元素数l的指针QQ意类型)?br><br>  ·int sizeQ数l中元素的个数?br><br>  ·int elem_sizeQ数l中一个元素的大小Q以字节为单位?br><br>  ·CompareFunction cmpFuncQ带有上q原型的指向回调函数的指针?br><br>  q两个函数的?x)对数组q行某种排序Q但每次都需军_两个元素哪个排在前面Q而函C有一个回调函敎ͼ其地址是作Z个参C递进来的。对~写者来_(d)不必介意函数在何处实玎ͼ或它怎样被实现的Q所需在意的只是两个用于比较的元素的地址Qƈq回以下的某个|库的~写者和使用者都必须遵守q个U定Q:(x)<br><br>  ·-1Q如果第一个元素较?yu),那它在已排序好的数组中,应该排在W二个元素前面?br><br>  ·0Q如果两个元素相{,那么它们的相对位|ƈ不重要,在已排序好的数组中,谁在前面都无所谓?<br><br>  ·1Q如果第一个元素较大,那在已排序好的数l中Q它应该排第二个元素后面?br><br>  Z以上U定Q函数Bubblesort()的实现如下,Quicksort()q微复杂一点:(x)<br><br> <table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1> <tbody> <tr> <td>void DLLDIR __stdcall Bubblesort(byte* array,int size,int elem_size,CompareFunction cmpFunc)<br>{<br> for(int i=0; i < size; i++)<br> {<br>  for(int j=0; j < size-1; j++)<br>  {<br>   //回调比较函数<br>   if(1 == (*cmpFunc)(array+j*elem_size,array+(j+1)*elem_size))<br>   {<br>    //两个相比较的元素怺?br>    byte* temp = new byte[elem_size];<br>    memcpy(temp, array+j*elem_size, elem_size);<br>    memcpy(array+j*elem_size,array+(j+1)*elem_size,elem_size);<br>    memcpy(array+(j+1)*elem_size, temp, elem_size);<br>    delete [] temp;<br>   }<br>  }<br> }<br>}</td> </tr> </tbody> </table> <br>  注意Q因为实C使用了memcpy()Q所以函数在使用的数据类型方面,?x)有所局限?br><br>  对用者来_(d)必须有一个回调函敎ͼ其地址要传递给Bubblesort()函数。下面有二个单的CZQ一个比较两个整敎ͼ而另一个比较两个字W串Q?br><br> <table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1> <tbody> <tr> <td>int __stdcall CompareInts(const byte* velem1, const byte* velem2)<br>{<br> int elem1 = *(int*)velem1;<br> int elem2 = *(int*)velem2;<br><br> if(elem1 < elem2)<br>  return -1;<br> if(elem1 > elem2)<br>  return 1;<br><br> return 0;<br>}<br><br>int __stdcall CompareStrings(const byte* velem1, const byte* velem2)<br>{<br> const char* elem1 = (char*)velem1;<br> const char* elem2 = (char*)velem2;<br> return strcmp(elem1, elem2);<br>}</td> </tr> </tbody> </table> <br>  下面另有一个程序,用于试以上所有的代码Q它传递了一个有5个元素的数组lBubblesort()和Quicksort()Q同时还传递了一个指向回调函数的指针?br><br> <table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1> <tbody> <tr> <td>int main(int argc, char* argv[])<br>{<br> int i;<br> int array[] = {5432, 4321, 3210, 2109, 1098};<br><br> cout << "Before sorting ints with Bubblesort\n";<br> for(i=0; i < 5; i++)<br>  cout << array[i] << '\n';<br><br> Bubblesort((byte*)array, 5, sizeof(array[0]), &CompareInts);<br><br> cout << "After the sorting\n";<br> for(i=0; i < 5; i++)<br>  cout << array[i] << '\n';<br><br> const char str[5][10] = {"estella","danielle","crissy","bo","angie"};<br><br> cout << "Before sorting strings with Quicksort\n";<br> for(i=0; i < 5; i++)<br>  cout << str[i] << '\n';<br><br> Quicksort((byte*)str, 5, 10, &CompareStrings);<br><br> cout << "After the sorting\n";<br> for(i=0; i < 5; i++)<br>  cout << str[i] << '\n';<br><br> return 0;<br>}</td> </tr> </tbody> </table> <br>  如果惌行降序排序(大元素在先)Q就只需修改回调函数的代码,或用另一个回调函敎ͼq样~程h灉|性就比较大了?br><strong><br>         调用U定<br><br></strong>  上面的代码中Q可在函数原型中扑ֈ__stdcallQ因为它以双下划U打_(d)所以它是一个特定于~译器的扩展Q说到底也就是微软的实现。Q何支持开发基于Win32的程序都必须支持q个扩展或其{h(hun)物。以__stdcall标识的函C用了标准调用U定Qؓ(f)什么叫标准U定呢,因ؓ(f)所有的Win32 APIQ除了个别接受可变参数的除外Q都使用它。标准调用约定的函数在它们返回到调用者之前,都会(x)从堆栈中U除掉参敎ͼq也是Pascal的标准约定。但在C/C++中,调用U定是调用者负责清理堆栈,而不是被调用函数Qؓ(f)强制函数使用C/C++调用U定Q可使用__cdecl。另外,可变参数函数也用C/C++调用U定?br><br>  Windows操作pȝ采用了标准调用约定(PascalU定Q,因ؓ(f)其可减小代码的体U。这点对早期的Windows来说非常重要Q因为那时它q行在只?40KB内存的电(sh)脑上?br><br>  如果你不喜欢__stdcallQ还可以使用CALLBACK宏,它定义在windef.h中:(x)<br><br> <table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1> <tbody> <tr> <td>#define CALLBACK __stdcallor<br><br>#define CALLBACK PASCAL //而PASCAL在此?defined成__stdcall</td> </tr> </tbody> </table> <br>  <strong>作ؓ(f)回调函数的C++Ҏ(gu)</strong><br><br>  因ؓ(f)qx很可能会(x)使用到C++~写代码Q也怼(x)惛_把回调函数写成类中的一个方法,但先来看看以下的代码Q?br><br> <table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1> <tbody> <tr> <td>class CCallbackTester<br>{<br> public:<br> int CALLBACK CompareInts(const byte* velem1, const byte* velem2);<br>};<br><br>Bubblesort((byte*)array, 5, sizeof(array[0]),<br>&CCallbackTester::CompareInts);</td> </tr> </tbody> </table> <br>  如果使用微Y的编译器Q将?x)得C面这个编译错误:(x)<br><br> <table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1> <tbody> <tr> <td>error C2664: 'Bubblesort' : cannot convert parameter 4 from 'int (__stdcall CCallbackTester::*)(const unsigned char *,const unsigned char *)' to 'int (__stdcall *)(const unsigned char *,const unsigned char *)' There is no context in which this conversion is possible</td> </tr> </tbody> </table> <br>  q是因ؓ(f)非静态成员函数有一个额外的参数Qthis指针Q这迫使你在成员函数前面加上static。当Ӟq有几种Ҏ(gu)可以解决q个问题Q但限于幅Q就不再了?br><br> <img src ="http://www.shnenglu.com/twzheng/aggbug/24543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/twzheng/" target="_blank">谭文?/a> 2007-05-21 16:51 <a href="http://www.shnenglu.com/twzheng/articles/CALLBACK.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows数据cdhttp://www.shnenglu.com/twzheng/articles/24535.html谭文?/dc:creator>谭文?/author>Mon, 21 May 2007 07:55:00 GMThttp://www.shnenglu.com/twzheng/articles/24535.htmlhttp://www.shnenglu.com/twzheng/comments/24535.htmlhttp://www.shnenglu.com/twzheng/articles/24535.html#Feedback0http://www.shnenglu.com/twzheng/comments/commentRss/24535.htmlhttp://www.shnenglu.com/twzheng/services/trackbacks/24535.html阅读全文

]]>
最通俗显的“IO模式”解?/title><link>http://www.shnenglu.com/twzheng/articles/24508.html</link><dc:creator>谭文?/dc:creator><author>谭文?/author><pubDate>Sun, 20 May 2007 17:46:00 GMT</pubDate><guid>http://www.shnenglu.com/twzheng/articles/24508.html</guid><wfw:comment>http://www.shnenglu.com/twzheng/comments/24508.html</wfw:comment><comments>http://www.shnenglu.com/twzheng/articles/24508.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/twzheng/comments/commentRss/24508.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/twzheng/services/trackbacks/24508.html</trackback:ping><description><![CDATA[<table style="TABLE-LAYOUT: fixed"> <tbody> <tr> <td> <div id="1111166" class=cnt> <div id="1616611" class=articleTitle><strong>[转] 最通俗显?#8220;IO模式”解析<br></strong>[源] Qhttp://hi.baidu.com/firebird/blog/item/f592b3193a02814542a9adeb.html<br><br> <font size=2>    一Qselect模型<br>    二:(x)WSAAsyncSelect模型<br>    三:(x)WSAEventSelect模型<br>    四:(x)Overlapped I/O 事g通知模型<br>    五:(x)Overlapped I/O 完成例程模型<br>    六:(x)IOCP模型</font><br><br>原文名:(x)《基于Delphi的Socket I/O模型全接?nbsp;?<br>老陈有一个在外地工作的女儿,不能l常回来Q老陈和她通过信g联系。他们的信会(x)被邮递员投递到他们的信里?nbsp; <br><br>q和Socket模型非常cM。下面我׃老陈接收信gZ讲解Socket I/O模型?nbsp; <br><br>一Qselect模型  <br><br>老陈非常想看到女儿的信。以至于他每?0分钟׃楼检查信,看是否有奛_的信Q在q种情况下,“下楼查信?#8221;然后回到g耽误了老陈太多的时_(d)以至于老陈无法做其他工作?nbsp; <br><br>select模型和老陈的这U情况非常相|(x)周而复始地L?.....如果有数?.....接收/发?......  <br><br>使用U程来select应该是通用的做法:(x)  <br><br>procedure TListenThread.Execute;  <br>var  <br>  addr : TSockAddrIn;  <br>  fd_read : TFDSet;  <br>  timeout : TTimeVal;  <br>  ASock,  <br>  MainSock : TSocket;  <br>  len, i : Integer;  <br>begin  <br>  MainSock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );  <br>  addr.sin_family := AF_INET;  <br>  addr.sin_port := htons(5678);  <br>  addr.sin_addr.S_addr := htonl(INADDR_ANY);  <br>  bind( MainSock, @addr, sizeof(addr) );  <br>  listen( MainSock, 5 );  <br><br>  while (not Terminated) do  <br>  begin  <br>   FD_ZERO( fd_read );  <br>   FD_SET( MainSock, fd_read );  <br>   timeout.tv_sec := 0;  <br>   timeout.tv_usec := 500;  <br>   if select( 0, @fd_read, nil, nil, @timeout ) > 0 then //臛_?个等待Accept的connection  <br>   begin  <br>    if FD_ISSET( MainSock, fd_read ) then  <br>    begin  <br>    for i:=0 to fd_read.fd_count-1 do //注意Qfd_count <= 64Q?<br>   也就是说select只能同时理最?4个连?nbsp; <br>    begin  <br>     len := sizeof(addr);  <br>     ASock := accept( MainSock, addr, len );  <br>     if ASock <> INVALID_SOCKET then  <br>      ....//为ASock创徏一个新的线E,在新的线E中再不停地select  <br>     end;  <br>    end;     <br>   end;  <br>  end; //while (not self.Terminated)  <br><br>  shutdown( MainSock, SD_BOTH );  <br>  closesocket( MainSock );  <br>end; <br>  <br><br><br>二:(x)WSAAsyncSelect模型  <br><br>后来Q老陈使用了微软公司的新式信箱。这U信非常先q,一旦信里有新的信Ӟ盖茨׃(x)l老陈打电(sh)话:(x)喂,大爷Q你有新的信件了Q从此,老陈再也不必频繁上下楼检查信׃Q牙也不gQ你瞅准了,蓝天......不是Q微?.....  <br><br>微Y提供的WSAAsyncSelect模型是q个意思?nbsp; <br><br>WSAAsyncSelect模型是Windows下最单易用的一USocket I/O模型。用这U模型时QW(xu)indows?x)把|络事g以消息的形势通知应用E序?nbsp; <br><br>首先定义一个消息标C常量:(x)  <br><br>const WM_SOCKET = WM_USER + 55; <br>  <br><br><br>再在主Form的private域添加一个处理此消息的函数声明:(x)  <br><br>private  <br>procedure WMSocket(var Msg: TMessage); message WM_SOCKET; <br>  <br>   <br><br>然后可以用WSAAsyncSelect了:(x)  <br><br>var  <br>  addr : TSockAddr;  <br>  sock : TSocket;  <br><br>  sock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );  <br>  addr.sin_family := AF_INET;  <br>  addr.sin_port := htons(5678);  <br>  addr.sin_addr.S_addr := htonl(INADDR_ANY);  <br>  bind( m_sock, @addr, sizeof(SOCKADDR) );  <br><br>  WSAAsyncSelect( m_sock, Handle, WM_SOCKET, FD_ACCEPT or FD_CLOSE );  <br><br>  listen( m_sock, 5 );  <br>  .... <br>  <br><br><br>应用E序可以Ҏ(gu)到WM_SOCKET消息q行分析Q判断是哪一个socket产生了网l事件以?qing)事件类型?x)  <br><br>procedure TfmMain.WMSocket(var Msg: TMessage);  <br>var  <br>  sock : TSocket;  <br>  addr : TSockAddrIn;  <br>  addrlen : Integer;  <br>  buf : Array [0..4095] of Char;  <br>begin  <br>  //Msg的WParam是生了|络事g的socket句柄QLParam则包含了事gcd  <br>  case WSAGetSelectEvent( Msg.LParam ) of  <br>  FD_ACCEPT :  <br>   begin  <br>    addrlen := sizeof(addr);  <br>    sock := accept( Msg.WParam, addr, addrlen );  <br>    if sock <> INVALID_SOCKET then  <br>     WSAAsyncSelect( sock, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE );  <br>   end;  <br><br>   FD_CLOSE : closesocket( Msg.WParam );  <br>   FD_READ : recv( Msg.WParam, buf[0], 4096, 0 );  <br>   FD_WRITE : ;  <br>  end;  <br>end; <br>  <br><br><br>三:(x)WSAEventSelect模型  <br><br>后来Q微软的信箱非常畅销Q购买微软信qZ百万计数......以至于盖茨每?4时l客h?sh)话Q篏得腰酸背痛,喝蚁力神都不好。微软改q了他们的信:(x)在客L(fng)家中d一个附加装|,q个装置?x)监视客L(fng)信箱Q每当新的信件来_(d)此装|会(x)发出“C件到?#8221;壎ͼ提醒老陈L信。盖茨终于可以睡觉了?nbsp; <br><br>同样要用线E:(x)  <br><br>procedure TListenThread.Execute;  <br>var  <br>  hEvent : WSAEvent;  <br>  ret : Integer;  <br>  ne : TWSANetworkEvents;  <br>  sock : TSocket;  <br>  adr : TSockAddrIn;  <br>  sMsg : String;  <br>  Index,  <br>  EventTotal : DWORD;  <br>  EventArray : Array [0..WSA_MAXIMUM_WAIT_EVENTS-1] of WSAEVENT;  <br>begin  <br>  ...socket...bind...  <br>  hEvent := WSACreateEvent();  <br>  WSAEventSelect( ListenSock, hEvent, FD_ACCEPT or FD_CLOSE );  <br>  ...listen...  <br><br>  while ( not Terminated ) do  <br>  begin  <br>   Index := WSAWaitForMultipleEvents( EventTotal, @EventArray[0], FALSE,  <br>  WSA_INFINITE, FALSE );  <br>   FillChar( ne, sizeof(ne), 0 );  <br>   WSAEnumNetworkEvents( SockArray[Index-WSA_WAIT_EVENT_0],  <br>    EventArray <br>  [Index-WSA_WAIT_EVENT_0], @ne );  <br><br>   if ( ne.lNetworkEvents and FD_ACCEPT ) > 0 then  <br>   begin  <br>    if ne.iErrorCode[FD_ACCEPT_BIT] <> 0 then  <br>     continue;  <br><br>    ret := sizeof(adr);  <br>    sock := accept( SockArray[Index-WSA_WAIT_EVENT_0], adr, ret );  <br>    if EventTotal > WSA_MAXIMUM_WAIT_EVENTS-1 then <br>      //q里W(xu)SA_MAXIMUM_WAIT_EVENTS同样?4  <br>    begin  <br>     closesocket( sock );  <br>     continue;  <br>    end;  <br><br>    hEvent := WSACreateEvent();  <br>    WSAEventSelect( sock, hEvent, FD_READ or FD_WRITE or FD_CLOSE );  <br>    SockArray[EventTotal] := sock;  <br>    EventArray[EventTotal] := hEvent;  <br>    Inc( EventTotal );  <br>   end;  <br><br>   if ( ne.lNetworkEvents and FD_READ ) > 0 then  <br>   begin  <br>    if ne.iErrorCode[FD_READ_BIT] <> 0 then  <br>     continue;  <br>     FillChar( RecvBuf[0], PACK_SIZE_RECEIVE, 0 );  <br>     ret := recv( SockArray[Index-WSA_WAIT_EVENT_0], RecvBuf[0],  <br>    PACK_SIZE_RECEIVE, 0 );  <br>     ......  <br>    end;  <br>   end;  <br>end; <br>  <br><br><br><br>四:(x)Overlapped I/O 事g通知模型  <br><br>后来Q微软通过调查发现Q老陈不喜Ƣ上下楼收发信gQ因Z下楼其实很浪Ҏ(gu)间。于是微软再ơ改q他们的信箱。新式的信箱采用了更为先q的技术,只要用户告诉微Y自己的家在几楼几P新式信箱?x)把信g直接传送到用户的家中,然后告诉用户Q你的信件已l放C的家中了Q老陈很高_(d)因ؓ(f)他不必再亲自收发信g了!  <br><br>Overlapped I/O 事g通知模型和W(xu)SAEventSelect模型在实C非常怼Q主要区别在"Overlapped”QOverlapped模型是让应用E序使用重叠数据l构(WSAOVERLAPPED)Q一ơ投递一个或多个Winsock I/Oh。这些提交的h完成后,应用E序?x)收到通知。什么意思呢Q就是说Q如果你想从socket上接收数据,只需要告诉系l,qlؓ(f)你接收数据,而你需要做的只是ؓ(f)pȝ提供一个缓冲区~~~~~  <br><br>ListenU程和W(xu)SAEventSelect模型一模一PRecv/SendU程则完全不同:(x)  <br><br>procedure TOverlapThread.Execute;  <br>var  <br>  dwTemp : DWORD;  <br>  ret : Integer;  <br>  Index : DWORD;  <br>begin  <br>  ......  <br><br>  while ( not Terminated ) do  <br>  begin  <br>   Index := WSAWaitForMultipleEvents <br>   ( FLinks.Count, @FLinks.Events[0], FALSE,  <br>    RECV_TIME_OUT, FALSE );  <br>   Dec( Index, WSA_WAIT_EVENT_0 );  <br>   if Index > WSA_MAXIMUM_WAIT_EVENTS-1 then  <br>    //时或者其他错?nbsp; <br>    continue;  <br><br>   WSAResetEvent <br>   ( FLinks.Events[Index] );  <br>   WSAGetOverlappedResult( FLinks.Sockets[Index],  <br>      FLinks.pOverlaps[Index], @dwTemp, FALSE,FLinks. <br>     pdwFlags[Index]^ );  <br><br>   if dwTemp = 0 then //q接已经关闭  <br>   begin  <br>    ......  <br>    continue;  <br>   end else  <br>  begin  <br>   fmMain.ListBox1.Items.Add( FLinks.pBufs[Index]^.buf );  <br>  end;  <br><br>  //初始化缓冲区  <br>  FLinks.pdwFlags[Index]^ := 0;  <br>  FillChar( FLinks.pOverlaps[Index]^,  <br>    sizeof(WSAOVERLAPPED), 0 );  <br>  FLinks.pOverlaps[Index]^. <br>   hEvent := FLinks.Events[Index];  <br>  FillChar( FLinks.pBufs[Index]^.buf^,  <br>   BUFFER_SIZE, 0 );  <br><br>  //递一个接收数据请?nbsp; <br>  WSARecv( FLinks.Sockets[Index], FLinks.pBufs[Index], 1, <br>       FLinks.pdwRecvd[Index]^, FLinks.pdwFlags[Index]^,  <br>      FLinks.pOverlaps[Index], nil );  <br>end;  <br>end; <br>  <br><br><br>五:(x)Overlapped I/O 完成例程模型  <br><br>老陈接收到新的信件后Q一般的E序是:(x)打开信封----掏出信纸----阅读信g----回复信g......Zq一步减ȝ戯担,微Y又开发了一U新的技术:(x)用户只要告诉微Y对信件的操作步骤Q微软信将按照q些步骤d理信Ӟ不再需要用户亲自拆?阅读/回复了!老陈l于q上了小资生z!  <br><br>Overlapped I/O 完成例程要求用户提供一个回调函敎ͼ发生新的|络事g的时候系l将执行q个函数Q?nbsp; <br><br>procedure WorkerRoutine( const dwError, cbTransferred : DWORD;  <br>const  <br>lpOverlapped : LPWSAOVERLAPPED; const dwFlags : DWORD ); stdcall; <br>  <br><br><br>然后告诉pȝ用WorkerRoutine函数处理接收到的数据Q?nbsp; <br><br>WSARecv( m_socket, @FBuf, 1, dwTemp, dwFlag, @m_overlap, WorkerRoutine );  <br>   然后......没有什么然后了Q系l什么都l你做了Q微软真实体_(d)  <br><br>while ( not Terminated ) do//q就是一个Recv/SendU程要做的事?.....什么都不用做啊Q!Q?nbsp; <br>begin  <br>  if SleepEx( RECV_TIME_OUT, True ) = WAIT_IO_COMPLETION then //  <br>  begin  <br>   ;  <br>  end else  <br>  begin  <br>   continue;  <br>  end;  <br>end; <br>  <br><br><br>六:(x)IOCP模型  <br><br>微Y信箱g很完,老陈也很满意。但是在一些大公司情况却完全不同!q些大公司有C万计的信,每秒钟都有数以百计的信g需要处理,以至于微软信q常因负药转而崩溃!需要重新启动!微Y不得不出杀手锏......  <br><br>微Yl每个大公司z了一名名?#8220;Completion Port”的超U机器hQ让q个机器人去处理那些信gQ?nbsp; <br><br>“Windows NT组注意到这些应用程序的性能没有预料的那么高。特别的Q处理很多同时的客户h意味着很多U程q发地运行在pȝ中。因为所有这些线E都是可q行的[没有被挂起和{待发生什么事]QMicrosoft意识到NT内核p了太多的旉来{换运行线E的上下文[Context]Q线E就没有得到很多CPU旉来做它们的工作。大家可能也都感觉到q行模型的瓶颈在于它为每一个客戯求都创徏了一个新U程。创建线E比起创E开销要小Q但也远不是没有开销的。我们不妨设想一下:(x)如果事先开好N个线E,让它们在那hold[堵塞]Q然后可以将所有用L(fng)h都投递到一个消息队列中厅R然后那N个线E逐一从消息队列中d出消息ƈ加以处理。就可以避免针对每一个用戯求都开U程。不仅减了U程的资源,也提高了U程的利用率。理Z很不错,你想我等泛泛之辈都能惛_来的问题QMicrosoft又怎会(x)没有考虑到呢?”-----摘自nonocast的《理解I/O Completion Port?nbsp; <br><br>先看一下IOCP模型的实玎ͼ(x)  <br><br>//创徏一个完成端?nbsp; <br>FCompletPort := CreateIoCompletionPort( INVALID_HANDLE_VALUE, 0,0,0 );  <br><br>//接受q程q接Qƈ把这个连接的socket句柄l定到刚才创建的IOCP?nbsp; <br>AConnect := accept( FListenSock, addr, len);  <br>CreateIoCompletionPort( AConnect, FCompletPort, nil, 0 );  <br><br>//创徏CPU?2 + 2个线E?nbsp; <br>for i:=1 to si.dwNumberOfProcessors*2+2 do  <br>begin  <br>  AThread := TRecvSendThread.Create( false );  <br>  AThread.CompletPort := FCompletPort;//告诉q个U程Q你要去q个IOCP去访问数?nbsp; <br>end; <br>  <br><br><br>p么简单,我们要做的就是徏立一个IOCPQ把q程q接的socket句柄l定到刚才创建的IOCP上,最后创建n个线E,q告诉这n个线E到q个IOCP上去讉K数据可以了?nbsp; <br><br>再看一下TRecvSendThreadU程都干些什么:(x)  <br><br>procedure TRecvSendThread.Execute;  <br>var  <br>  ......  <br>begin  <br>  while (not self.Terminated) do  <br>  begin  <br>   //查询IOCP状态(数据d操作是否完成Q?nbsp; <br>   GetQueuedCompletionStatus( CompletPort, BytesTransd,  <br>    CompletKey, POVERLAPPED(pPerIoDat), TIME_OUT );  <br><br>   if BytesTransd <> 0 then  <br>    ....;//数据d操作完成  <br>    <br>    //再投递一个读数据h  <br>    WSARecv( CompletKey, @(pPerIoDat^.BufData), 1,  <br>    BytesRecv, Flags, @(pPerIoDat^.Overlap), nil );  <br>   end;  <br>end; <br>  <br><br><br>dU程只是单地查IOCP是否完成了我们投递的d操作Q如果完成了则再投递一个新的读写请求?nbsp; <br><br>应该注意刎ͼ我们创徏的所有TRecvSendThread都在讉K同一个IOCPQ因为我们只创徏了一个IOCPQ,q且我们没有使用临界区!N不会(x)产生冲突吗?不用考虑同步问题吗?  <br><br>q正是IOCP的奥妙所在。IOCP不是一个普通的对象Q不需要考虑U程安全问题。它?x)自动调配访问它的线E:(x)如果某个socket上有一个线EA正在讉KQ那么线EB的访问请求会(x)被分配到另外一个socket。这一切都是由pȝ自动调配的,我们无需q问?/div> </div> </td> </tr> </tbody> </table> <img src ="http://www.shnenglu.com/twzheng/aggbug/24508.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/twzheng/" target="_blank">谭文?/a> 2007-05-21 01:46 <a href="http://www.shnenglu.com/twzheng/articles/24508.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>typename 的两个含?/title><link>http://www.shnenglu.com/twzheng/articles/23693.html</link><dc:creator>谭文?/dc:creator><author>谭文?/author><pubDate>Wed, 09 May 2007 03:47:00 GMT</pubDate><guid>http://www.shnenglu.com/twzheng/articles/23693.html</guid><wfw:comment>http://www.shnenglu.com/twzheng/comments/23693.html</wfw:comment><comments>http://www.shnenglu.com/twzheng/articles/23693.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/twzheng/comments/commentRss/23693.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/twzheng/services/trackbacks/23693.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 12pt"><span style="FONT-SIZE: 10pt; COLOR: #993366"><font size=3><font color=#800080>[转]<strong> typename 的两个含?/strong><br></font></font>【摘自】armman的专?br><br><strong>template<class T> class Widget;        // uses "class"<br>template<typename T> class Widget;     // uses "typename"</strong></span><span style="FONT-SIZE: 10pt; COLOR: #993366"><br>  {案Q没什么不同。在声明一?template type parameterQ模板类型参敎ͼӞclass ?typename 意味着完全相同的东ѝ一些程序员更喜Ƣ在所有的旉都用 classQ因为它更容易输入。其他h更喜?typenameQ因为它暗示着q个参数不必要是一?class typeQ类cdQ。少数开发者在Mcd都被允许的时候?typenameQ而把 class 保留l仅接受 user-defined typesQ用户定义类型)的场合。但是从 C++ 的观点看Qclass ?typename 在声明一?template parameterQ模板参敎ͼ时意味着完全相同的东ѝ?br><br>  然而,C++ q不L?class ?typename 视ؓ(f){同的东ѝ有时必M?typename。ؓ(f)了理解这一点,我们不得不讨论在一?templateQ模板)中涉?qing)到的两U名字?br><br>  假设我们有一个函数的模板Q它能取得一?STL-compatible containerQSTL 兼容容器Q中持有的能赋值给 ints 的对象。进一步假设这个函数只是简单地打印它的W二个元素的倹{它是一个用p涂的方法实现的p涂的函敎ͼ而且像下面写的Q它甚至不能~译Q但是请这些事先放在一边:(x)<br><br>template<typename C> // print 2nd element in<br>void print2nd(const C& container) // container;<br>{ <br> // this is not valid C++!<br> if (container.size() >= 2) {<br>  C::const_iterator iter(container.begin()); // get iterator to 1st element<br>  ++iter; // move iter to 2nd element<br>  int value = *iter; // copy that element to an int<br>  std::cout << value; // print the int<br> }<br>}<br>  q个函数中的两个 local variablesQ局部变量)Qiter ?value。iter 的类型是 C::const_iteratorQ一个依赖于 template parameterQ模板参敎ͼC 的类型。一?templateQ模板)中的依赖于一?template parameterQ模板参敎ͼ的名字被UCؓ(f) dependent namesQ依赖名字)。当一?dependent namesQ依赖名字)嵌套在一?classQ类Q的内部ӞU它?nested dependent nameQ嵌套依赖名字)。C::const_iterator 是一?nested dependent nameQ嵌套依赖名字)。实际上Q它是一?nested dependent type nameQ嵌套依赖类型名Q,也就是说Q一个涉?qing)到一?typeQ类型)?nested dependent nameQ嵌套依赖名字)?br><br>  print2nd 中的另一?local variableQ局部变量)value h int cd。int 是一个不依赖于Q?template parameterQ模板参敎ͼ的名字。这L(fng)名字?non-dependent namesQ非依赖名字Q闻名?br><br>  nested dependent nameQ嵌套依赖名字)?x)导致解析困难。例如,假设我们更加愚蠢Cq种Ҏ(gu)开?print2ndQ?br>template<typename C><br>void print2nd(const C& container)<br>{<br> C::const_iterator * x;<br> ...<br>}<br>  q看上去好像是我们将 x 声明Z个指?C::const_iterator ?local variableQ局部变量)。但是它看上d此仅仅是因ؓ(f)我们知道 C::const_iterator 是一?typeQ类型)。但是如?C::const_iterator 不是一?typeQ类型)呢?如果 C 有一?static data memberQ静态数据成员)y叫?const_iterator 呢?再如?x y是一?global variableQ全局变量Q的名字呢?在这U情况下Q上面的代码׃是声明一?local variableQ局部变量)Q而是成ؓ(f) C::const_iterator 乘以 xQ当Ӟq听h有些愚蠢Q但它是可能的,而编?C++ 解析器的人必考虑所有可能的输入Q甚x愚蠢的?br><br>  直到 C 成ؓ(f)已知之前Q没有Q何办法知?C::const_iterator 到底是不是一?typeQ类型)Q而当 templateQ模板)print2nd 被解析的时候,C q不是已知的。C++ 有一条规则解册个歧义:(x)如果解析器在一?templateQ模板)中遇C?nested dependent nameQ嵌套依赖名字)Q它假定那个名字不是一?typeQ类型)Q除非用其它方式告诉它。缺省情况下Qnested dependent nameQ嵌套依赖名字)不是 typesQ类型)。(对于q条规则有一个例外)<br><br>  Cq个Q再看看 print2nd 的开_(d)(x)<br>template<typename C>void print2nd(const C& container)<br>{<br> if (container.size() >= 2) {<br>  C::const_iterator iter(container.begin()); // this name is assumed to<br>  ... // not be a type<br>  qؓ(f)什么不是合法的 C++ 现在应该很清楚了。iter ?declarationQ声明)仅仅?C::const_iterator 是一?typeQ类型)时才有意义,但是我们没有告诉 C++ 它是Q?C++ 假定它不是。要惌{变这个Ş势,我们必须告诉 C++ C::const_iterator 是一?typeQ类型)。我们将 typename 攑֜紧挨着它的前面来做到这一点:(x)<br><br>template<typename C> // this is valid C++<br>void print2nd(const C& container)<br>{<br>if (container.size() >= 2) {<br>typename C::const_iterator iter(container.begin());<br>...<br>}<br>}<br>  通用的规则很单:(x)在涉?qing)到一个在 templateQ模板)中的 nested dependent type nameQ嵌套依赖类型名Q的M时候,必须把单?typename 攑֜紧挨着它的前面。(重申一下,我待?x)儿要描qC个例外。)<br><br>  typename 应该仅仅被用于标?nested dependent type nameQ嵌套依赖类型名Q;其它名字不应该用它。例如,q是一个取得一?containerQ容器)和这?containerQ容器)中的一?iteratorQP代器Q的 function templateQ函数模板)Q?br><br>template<typename C> // typename allowed (as is "class")<br>void f(const C& container, // typename not allowed<br>typename C::iterator iter); // typename required<br>  C 不是一?nested dependent type nameQ嵌套依赖类型名Q(它不是嵌套在依赖于一?template parameterQ模板参敎ͼ的什么东西内部的Q,所以在声明 container 时它不必?typename 前置Q但?C::iterator 是一?nested dependent type nameQ嵌套依赖类型名Q,所以它必需?typename 前置?br><br>  "typename must precede nested dependent type names"Q?/span><span style="FONT-SIZE: 10pt; COLOR: #993366">“</span><span style="FONT-SIZE: 10pt; COLOR: #993366">typename 必须前置于嵌套依赖类型名</span><span style="FONT-SIZE: 10pt; COLOR: #993366">”</span><span style="FONT-SIZE: 10pt; COLOR: #993366">Q规则的例外?typename 不必前置于在一?list of base classesQ基cd表)中的或者在一?member initialization listQ成员初始化列表Q中作ؓ(f)一?base classes identifierQ基cL识符Q的 nested dependent type nameQ嵌套依赖类型名Q。例如:(x)<br><br>template<typename T><br>class Derived: public Base<T>::Nested { // base class list: typename not<br> public: // allowed<br>  explicit Derived(int x)<br>  : Base<T>::Nested(x) // base class identifier in mem<br>  { <br>   // init. list: typename not allowed<br>    typename Base<T>::Nested temp; // use of nested dependent type<br>   ... // name not in a base class list or<br>  } // as a base class identifier in a<br> ... // mem. init. list: typename required<br>};<br>  q样的矛监־令h讨厌Q但是一旦在l历中获得一点经验,几乎不会(x)在意它?br><br>  让我们来看最后一?typename 的例子,因ؓ(f)它在看到的真实代码中h代表性。假设我们在写一个取得一?iteratorQP代器Q的 function templateQ函数模板)Q而且我们要做一?iteratorQP代器Q指向的 objectQ对象)的局部拷?tempQ我们可以这样做Q?br>template<typename IterT><br>void workWithIterator(IterT iter)<br>{<br> typename std::iterator_traits<IterT>::value_type temp(*iter);<br> ...<br>}<br>  不要?std::iterator_traits<IterT>::value_type 吓倒你。那仅仅是一?standard traits classQ标准特性类Q的使用Q用 C++ 的说法就?"the type of thing pointed to by objects of type IterT"Q?/span><span style="FONT-SIZE: 10pt; COLOR: #993366">“</span><span style="FONT-SIZE: 10pt; COLOR: #993366">被类型ؓ(f) IterT 的对象所指向的东西的cd</span><span style="FONT-SIZE: 10pt; COLOR: #993366">”</span><span style="FONT-SIZE: 10pt; COLOR: #993366">Q。这个语句声明了一个与 IterT objects 所指向的东西类型相同的 local variableQ局部变量)(temp)Q而且?iter 所指向?objectQ对象)?temp q行了初始化。如?IterT ?vector<int>::iteratorQtemp 是 int cd。如?IterT ?list<string>::iteratorQtemp 是 string cd。因?std::iterator_traits<IterT>::value_type 是一?nested dependent type nameQ嵌套依赖类型名Q(value_type 嵌套?iterator_traits<IterT> 内部Q而且 IterT 是一?template parameterQ模板参敎ͼQ,我们必须让它?typename 前置?br><br>  如果觉得?std::iterator_traits<IterT>::value_type 令h讨厌Q就惌那个与它相同的东西来代表它。如果像大多数程序员Q对多次输入它感到恐惧,那么需要创Z?typedef。对于像 value_type q样?traits member namesQ特性成员名Q,一个通用的惯例是 typedef name ?traits member name 相同Q所以这L(fng)一?local typedef 通常定义成这P(x)<br><br>template<typename IterT> void workWithIterator(IterT iter)<br>{<br> typedef typename std::iterator_traits<IterT>::value_type value_type;<br><br> value_type temp(*iter);<br> ...<br>}<br>  很多E序员最初发?"typedef typename" q列不太和谐Q但它是涉及(qing) nested dependent type namesQ嵌套依赖类型名Q规则的一个合理的附带l果?br><br>  一些编译器接受必需 typename 时它却缺q代码Q一些编译器接受不许 typename 时它却存在的代码Q还有少数的Q通常是老旧的)?x)拒l?typename 出现在它必需出现的地斏V这意味着 typename ?nested dependent type namesQ嵌套依赖类型名Q的交互作用?x)导致一些轻微的可移植性问题?br><br><strong>Things to Remember  </strong> </span><span style="FONT-SIZE: 10pt; COLOR: #993366">·</span><span style="FONT-SIZE: 10pt; COLOR: #993366">在声?template parametersQ模板参敎ͼӞclass ?typename 是可互换的?br>  </span><span style="FONT-SIZE: 10pt; COLOR: #993366">·</span><span style="FONT-SIZE: 10pt; COLOR: #993366">?typename L?nested dependent type namesQ嵌套依赖类型名Q,?base class listsQ基cd表)中或在一?member initialization listQ成员初始化列表Q中作ؓ(f)一?base class identifierQ基cL识符Q时除外?/span></p> <img src ="http://www.shnenglu.com/twzheng/aggbug/23693.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/twzheng/" target="_blank">谭文?/a> 2007-05-09 11:47 <a href="http://www.shnenglu.com/twzheng/articles/23693.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++/CLR泛型与C++模板之间的对?/title><link>http://www.shnenglu.com/twzheng/articles/23591.html</link><dc:creator>谭文?/dc:creator><author>谭文?/author><pubDate>Mon, 07 May 2007 16:04:00 GMT</pubDate><guid>http://www.shnenglu.com/twzheng/articles/23591.html</guid><wfw:comment>http://www.shnenglu.com/twzheng/comments/23591.html</wfw:comment><comments>http://www.shnenglu.com/twzheng/articles/23591.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/twzheng/comments/commentRss/23591.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/twzheng/services/trackbacks/23591.html</trackback:ping><description><![CDATA[<span style="FONT-SIZE: 24pt"> C++/CLR泛型与C++模板之间的对?span style="FONT-SIZE: 24pt">[摘自~程乐园]</span><br><br></span> <p>Visual Studio 2005把泛型编E的cd参数模型引入了微?NET框架lg。C++/CLI支持两种cd参数机制--通用语言q行ӞCLRQ泛型和C++模板。本文将介绍两者之间的一些区?-特别是参数列表和cdU束模型之间的区别?<br><br>  参数列表又回来了<br><br>  参数列表与函数的信号QsignatureQ类|(x)它标明了参数的数量和每个参数的类型,q把l每个参数关联一个唯一的标识符Q这样在模板定义的内部,每个参数可以被唯一地引用?br><br>  参数在模板或泛型的定义中起占位符QplaceholderQ的作用。用户通过提供l定到参数的实际值来建立对象实例。参数化cd的实例化q单的文本替代Q宏扩展机制是使用文本替代的)。相反地Q它把实际的用户值绑定到定义中的相关的Ş式参C?br><br>  在泛型中Q每个参数都表现为Objectcd或衍生自Object的类型。在本文后面你可以看刎ͼq约束了你可能执行的操作cd或通过cd参数声明的对象。你可以通过提供更加明确的约束来调整q些U束关系。这些明的U束引用那些衍生出实际类型参数的基类或接口集合?br><br>  模板除了支持cd参数之外Q还支持表达式和模板参数。此外,模板q支持默认的参数倹{这些都是按照位|而不是名U来分解的。在两种机制之下Q类型参数都是与cLcd名称关键字一起引入的?br><br>  参数列表的额外的模板功能<br><br>  模板作ؓ(f)cd参数的补充,允许两种cd的参敎ͼ(x)非类型(non-typeQ参数和模板参数。我们将分别短地介绍一下?br><br>  非类型参数受常数表达式的U束。我们应该立x到它是数值型或字W串帔R。例如,如果选择提供固定大小的堆栈,你就可能同时指定一个非cd的大参数和元素cd参数Q这样就可以同时按照元素cd和大来划分堆栈实例的类别。例如,你可以在代码1中看到带有非cd参数的固定大的堆栈?br><br>  代码1Q带有非cd固定大小的堆?br><br>template <class elemType, int size><br>public ref class tStack<br>{<br> array<elemType> ^m_stack;<br> int top;<br><br> public:<br>  tStack() : top( 0 ) <br>  { m_stack = gcnew array<elemType>( size ); }<br>};<br>  此外Q如果模板类设计者可以ؓ(f)每个参数指定默认|使用h可能方便多了。例如,把缓冲区的默认大设|ؓ(f)1KB是很好的。在模板机制下,可以l参数提供默认|如下所C:(x)<br><br>// 带有默认值的模板声明<br>template <class elemType, int size = 1024><br>public ref class FixedSizeStack {};<br>  用户可以通过提供明确的第二个值来重蝲默认大小|(x)<br><br>// 最?28个字W串实例的堆?br>FixedSizeState<String^, 128> ^tbs = gcnew FixedSizeStack<String^, 128>;<br>  否则Q由于没有提供第二个参数Q它使用了相关的默认|如下所C:(x)<br><br>// 最?024个字W串实例的堆?br>FixedSizeStack<String^> ^tbs = gcnew FixedSizeStack<String^>;<br>  使用默认的参数值是标准模板库(STLQ的一个基本的设计特征。例如,下面的声明就来自ISO-C++标准Q?br><br>// ISO-C++名字I间std中的默认cd参数值示?<br>{<br> template <class T, class Container = deque<T> > <br> class queue;<br><br> template <class T, class Allocator = allocator<T> > <br> class vector;<br> // ...<br>}<br>  你可以提供默认的元素cdQ如下所C:(x)<br><br>// 带有默认的元素类型的模板声明 <br>template <class elemType=String^, int size=1024><br>public ref class tStack {}; </p> <p><br> </p> <p>  从设计的角度来说很难证明它的正确性,因ؓ(f)一般来说容器不?x)集中在在单个默认类型上?br><br>  指针也可以作为非cd参数Q因为对象或函数的地址在编译时已知了Q因此是一个常量表辑ּ。例如,你可能希望ؓ(f)堆栈cL供第三个参数Q这个参数指明遇到特定条件的时候用的回调处理E序。明智地使用typedef可以大幅度简化那些表面上看v来很复杂的声明,如下所C:(x)</p> <p>typedef void (*handler)( ... array<Object^>^ );<br>template <class elemType, int size, handler cback ><br>public ref class tStack {};<br>  当然Q你可以为处理程序提供默认?-在这个例子中Q是一个已有的Ҏ(gu)的地址。例如,下面的缓冲区声明提供了大小和处理程序:(x)<br><br>void defaultHandler( ... array<Object^>^ ){ ... }<br><br>template < class elemType, <br>int size = 1024, <br>handler cback = &defaultHandler ><br>public ref class tStack {};<br>  ׃默认值的位置ơ序优先于命名次序,因此如果不提供明的大小|即ɘq个大小与默认值是重复的)Q就无法提供重蝲的处理程序的。下面就是可能用到的修改堆栈的方法:(x)<br><br>void demonstration() <br>{<br> // 默认的大和处理E序<br> tStack<String^> ^ts1 = nullptr; <br> // 默认的处理程?br> tStack<String^, 128> ^ts2 = gcnew tStack<String^, 128>;<br> // 重蝲所有的三个参数<br> tStack<String^, 512, &yourHandler> ^ts3;<br>}<br><br>  模板支持的第二种额外的参数就是template模板参数--也就是这个模板参数本w表Cؓ(f)一个模ѝ例如:(x)<br><br>// template模板参数<br>template <template <class T> class arena, class arenaType><br>class Editor { <br>arena<arenaType> m_arena; <br>// ...<br>};<br>  Editor模板cdZ两个模板参数arena和arenaType。ArenaType是一个模板类型参敎ͼ你可以传递整型、字W串型、自定义cd{等。Arena是一个template模板参数。带有单个模板类型参数的M模板c都可以l定到arena。m_arena是一个绑定到arenaType模板cd参数的模板类实例。例如:(x)<br><br>// 模板~冲区类<br>template <class elemType><br>public ref class tBuffer {};<br><br>void f()<br>{<br> Editor<tBuffer,String^> ^textEditor;<br> Editor<tBuffer,char> ^blitEditor;<br> // ...<br>} </p> <p> </p> <p>  cd参数U束<br><br>  如果你把参数化类型简单地作ؓ(f)存储和检索元素的容器Q那么你可以略过q一部分了。当你需要调用某个类型参敎ͼ例如在比较两个对象,查看它们相等或者其中一个小于另一个的时候,或者通过cd参数调用Ҏ(gu)名称或嵌套类型的时候)上的操作的时候,才会(x)考虑U束的问题。例如:(x)</p> <p>template <class T><br>ref class Demonstration {<br> int method() {<br>  typename T::A *aObj; <br>  // ...<br> }<br>};</p> <p><br>  q段代码成功地声明了aObjQ它同时q约束了能够成功地绑定到你的cL板的cd参数。例如,如果你编写下面的代码QaObj的声明就是非法的Q在q种特定的情况下Q,~译器会(x)报错误信息:(x) </p> <p>int demoMethod()<br>{<br> Demonstration<int> ^demi = gcnew Demonstration<int>( 1024 );<br> return dm->method();<br>}</p> <p><br>  当然Q其特定的约束是Q这个类型参数必d含一个叫做A的类型的嵌套声明。如果它的名字叫做B、C或Z都没有关pR更普通的U束是类型参数必表CZ个类Q否则就不允怋用T::范围操作W。我使用intcd参数同时q反了这两条U束。例如,Visual C++~译器会(x)生成下面的错误信息:(x)</p> <p>error C2825: 'T': must be a class or namespace when followed by '::' </p> <p><br>  C++模板机制受到的一条批评意见是Q缺乏用于描q这U类型约束的形式语法Q请注意Q在参数化类型的原始设计囄中,Bjarne Stroustrup了曾l考虑q提供显式约束语法,但是他对q种语法不太满意Qƈ选择了在那个时候不提供q种机制Q。也是_(d)在一般情况下Q用户在阅读源代码或相关的文档,或者编译自q代码q读随后的~译器错误消息的时候,才能意识到模板有隐含U束?br><br>  如果你必L供一个与模板不匹配的cd参数该怎么办呢Q一斚wQ我们能做的事情很少。你~写的Q何类都有一定的假设Q这些假设表Cؓ(f)某些使用斚w的约束。很难设计出适合每种情况的类Q设计出适合每种情况和每U可能的cd参数的模板类更加困难?<br><br>  另一斚wQ存在大量的模板Ҏ(gu)ؓ(f)用户提供?q回"I间。例如,cL板成员函C?x)绑定到cd参数Q直到在代码中用该函数为止Q这个时候才l定Q。因此,如果你用模板类的时候,没有使用那些使类型参数失效的Ҏ(gu)Q就不会(x)遇到问题?br><br>  如果q样也不可行Q那么还可以提供该方法的一个专门的版本Q让它与你的cd参数兌。在q种情况下,你需要提供Demonstration<int>::Ҏ(gu)的一个专用的实例Q或者,更ؓ(f)普遍的情冉|Q在提供整数cd参数的时候,提供整个模板cȝ专门的实现方式?<br><br>  一般来_(d)当你提到参数化类型可以支持多U类型的时候,你一般谈到的是参数化的被动?-也就是说Q主要是cd的存储和索,而不是积极地操作Q处理)它?br><br>  作ؓ(f)模板的设计h员,你必ȝ道自q实现对类型参数的隐含U束条gQƈ且努力去保q些条g不是多余的。例如,要求cd参数提供{于和小于操作是合理的;但是要求它支持小于或{于或XOR位运符׃太合理了。你可以通过把这些操作分解到不同的接口中Q或者要求额外的、表C函数、委托或函数对象的参数来放松Ҏ(gu)作符的依赖性。例如,代码2昄了一个本地C++E序员用内建的{于操作W实现的搜烦Ҏ(gu)?br><br>  代码2Q不利于模板的搜索实?/p> <p>template <class elemType, int size=1024><br>ref class Container <br>{<br> array<elemType> ^m_buf;<br> int next;<br><br> public:<br>  bool search( elemType et )<br>  {<br>   for each ( elemType e in m_buf )<br>    if ( et == e )<br>     return true;<br>    return false;<br>  }<br><br>  Container() <br>  { <br>   m_buf = gcnew array<elemType>(size); <br>   next = 0; <br>  }<br><br>  void add( elemType et )<br>  { <br>   if ( next >= size ) <br>    throw gcnew Exception; <br>    m_buf[ next++ ] = et; <br>  }<br><br>  elemType get( int ix )<br>  {<br>   if ( ix < next ) <br>    return m_buf[ ix ]; <br>   throw gcnew Exception; <br>  }<br>  // ...<br> };</p> <p><br> </p> <p>  在这个搜索函C没有M错误。但是,它不太利于用模板,因ؓ(f)cd参数与等于操作符紧密耦合了。更为灵zȝҎ(gu)是提供第二个搜烦Ҏ(gu)Q允许用户传递一个对象来q行比较操作。你可以使用函数成员模板来实现这个功能。函数成员模板提供了一个额外的cd参数。请看一看代??br><br>  代码3Q用模?/p> <p>template <class elemType, int size=1024><br>ref class Container <br>{<br> // 其它的都相同 ...<br> // q是一个函数成员模?..<br> // 它可以同时引用包含的cd数和自有参数...<br><br> template <class Comparer><br> bool search( elemType et, Comparer comp )<br> {<br>  for each ( elemType e in m_buf )<br>   if ( comp( et, e ) )<br>    return true;<br> <br>   return false;<br> }<br> // ...<br>};</p> <p><br>  现在用户可以选择使用哪一个方法来搜烦内容了:(x)紧密耦合的等于操作符搜烦效率较高Q但是不适合于所有类型;较灵zȝ成员模板搜烦要求传递用于比较的cd?br><br>  哪些对象适用q种比较目的Q函数对象就是普通的用于q种目的的C++设计模式。例如,下面是一个比较两个字W串是否相等的函数对象:(x)</p> <p>class EqualGuy {<br> public: <br>  bool operator()( String^ s1, String^ s2 )<br>  {<br>   return s1->CompareTo( s2 ) == 0;<br>  }<br>};</p> <p><br>  代码4中的代码昄了你如何调用q两个版本的搜烦成员函数模板和传l的版本?br><br>  代码4Q两个搜索函?/p> <p>int main()<br>{<br> Container<String^> ^sxc = gcnew Container<String^>;<br> sxc->add( "Pooh" );<br> sxc->add( "Piglet" );<br><br> // 成员模板搜烦 ...<br> if ( sxc->search( "Pooh", EqualGuy() ) )<br>  Console::WriteLine( "found" );<br> else Console::WriteLine( "not found" );<br><br>  // 传统的等于搜?...<br>  if ( sxc->search( "Pooh" ) )<br>   Console::WriteLine( "found" );<br>  else Console::WriteLine( "not found" );<br>}</p> <p><br>  一旦有了模板的概念Q你׃(x)发现使用模板几乎没有什么事情不是实现。至感觉是q样的?/p>   泛型U束<br><br>  与模板不同,泛型定义支持形式U束语法Q这些语法用于描q可以合法地l定的类型参数。在我详l介l约束功能之前,我们短地考虑一下ؓ(f)什么泛型选择了提供约束功能,而模杉K择了不提供q个功能。我怿Q最主要的原因是两种机制的绑定时间之间差异。模板在~译的过E中l定Q因此无效的cd?x)让E序停止~译。用户必ȝ卌册个问题或者把它重新处理成非模板编E方案。执行程序的完整性不存在风险?br><br>  另一斚wQ泛型在q行时绑定,在这个时候才发现用户指定的类型无效就已经太迟了。因此通用语言l构QCLIQ需要一些静态(也就是编译时Q机制来保在运行时只会(x)l定有效的类型。与泛型相关的约束列表是~译时过滤器Q也是_(d)如果q反的时候,?x)阻止程序的建立?<br><br>  我们来看一个例子。图5昄了用泛型实现的容器类。它的搜索方法假讄型参数衍生自IcomparableQ因此它实现了该接口的CompareToҎ(gu)的一个实例。请注意Q容器的大小是在构造函Cqh供的Q而不是作为第二个、非cd参数提供的。你应该记得泛型不支持非cd参数的?br><br>  代码5Q作为泛型实现的容器<o:p></o:p> <p>generic <class elemType><br>public ref class Container <br>{<br> array<elemType> ^m_buf;<br> int next;<br> int size;<br> <br>public:<br> bool search( elemType et )<br> {<br>  for each ( elemType e in m_buf )<br>   if ( et->CompareTo( e ))<br>    return true;<br>   return false;<br> }<br><br> Container( int sz ) <br> { <br>  m_buf = gcnew array<elemType>(size = sz); <br>  next = 0; <br> }<br><br> // add() ?get() 是相同的 ... <br><br>};<o:p></o:p></p> <p><br>  该泛型类的实现在~译的时候失败了Q遇C如下所C的致命的编译诊断信息:(x)<o:p></o:p></p> <p>error C2039: 'CompareTo' : is not a member of 'System::Object'<o:p></o:p></p> <p><br>  你也许有点糊涂了Q这是怎么回事Q没有h认ؓ(f)它是System::Object的成员啊。但是,在这U情况下你就错了。在默认情况下,泛型参数执行最严格的可能的U束Q它把自q所有类型约束ؓ(f)Objectcd。这个约束条件是对的Q因为只允许CLIcdl定到泛型上Q当Ӟ所有的CLIcd都多多少地衍生自Object。因此在默认情况下,作ؓ(f)泛型的作者,你的操作非常安全Q但是可以用的操作也是有限的?br><br>  你可能会(x)惻I好吧Q我减小灉|性,避免~译器错误,用等于操作符代替CompareToҎ(gu)Q但是它却引起了更严重的错误Q?o:p></o:p></p> <p>error C2676: binary '==' : 'elemType' does not define this operator<br>or a conversion to a type acceptable to the predefined operator<o:p></o:p></p> <p><br>  同样Q发生的情况是,每个cd参数开始的时候都被Object的四个公qҎ(gu)包围着QToString、GetType、GetHashCode和Equals。其效果是,q种在单独的cd参数上列出约束条件的工作表现了对初始的强约束条件的逐步放松。换句话_(d)作ؓ(f)泛型的作者,你的d是按照泛型约束列表的U定Q采用可以验证的方式来扩展那些允许的操作。我们来看看如何实现q样的事务?br><br>  我们用约束子句来引用U束列表Q用非保留?where"实现。它被放|在参数列表和类型声明之间。实际的U束包含一个或多个接口cd?或一个类cd的名U。这些约束显CZ参数cd希望实现的或者衍生出cd参数的基cR每U类型的公共操作集合都被d到可用的操作中,供类型参C用。因此,Z让你的elemType参数调用CompareToQ你必须d与Icomparable接口兌的约束子句,如下所C:(x)<o:p></o:p></p> <p>generic <class elemType><br>where elemType : IComparable<br>public ref class Container <br>{<br> // cȝM没有改变 ... <br>};<o:p></o:p></p> <p><br>  q个U束子句扩展了允许elemType实例调用的操作集合,它是隐含的ObjectU束和显式的IcomparableU束的公共操作的l合体。该泛型定义现在可以~译和用了。当你指定一个实际的cd参数的时候(如下面的代码所C)Q编译器验证实际的cd参数是否与将要绑定的cd参数的约束相匚wQ?<o:p></o:p></p> <p>int main()<br>{<br> // 正确的:(x)String和int实现了IComparable<br> Container<String^> ^sc; <br> Container<int> ^ic; <br><br> //错误的:(x)StringBuilder没有实现IComparable <br> Container<StringBuilder^> ^sbc; <br>}<o:p></o:p></p> <p><br>  ~译器会(x)提示某些q反了规则的信息Q例如sbc的定义。但是泛型的实际的绑定和构造已l由q行时完成了?br><br>  接着Q它?x)同旉证泛型在定义点(~译器处理你的实现的时候)和构造点Q编译器Ҏ(gu)相关的约束条件检查类型参数的时候)是否q反了约束。无论在那个点失败都?x)出现编译时错误?o:p></o:p></p> <p>  U束子句可以每个cd参数包含一个条目。条目的ơ序不一定跟参数列表的次序相同。某个参数的多个U束需要用逗号分开。约束在与每个参数相关的列表中必d一Q但是可以出现在多个U束列表中。例如:(x)<o:p></o:p></p> <p>generic <class T1, class T2, class T3><br>where T1 : IComparable, ICloneable, Image<br>where T2 : IComparable, ICloneable, Image<br>where T3 : ISerializable, CompositeImage<br>public ref class Compositor <br>{<br> // ...<br>};<o:p></o:p></p> <p><br>  在上面的例子中,出现了三个约束子句,同时指定了接口类型和一个类cdQ在每个列表的末)。这些约束是有额外的意义的,即类型参数必ȝ合所有列出的U束Q而不是符合它的某个子集。我的同事Jon Wray指出Q由于你是作为泛型的作者来扩展操作集合的,因此如果放松了约束条Ӟ那么该泛型的用户在选择cd参数的时候就得增加更多的U束?br><br>  T1、T2和T3子句可以按照其它的次序放|。但是,不允许跨两个或多个子句指定某个cd参数的约束列表。例如,下面的代码就?x)出现违反语法错误?x)<o:p></o:p></p> <p>generic <class T1, class T2, class T3><br>// 错误的:(x)同一个参C允许有两个条?br>where T1 : IComparable, ICloneable<br>where T1 : Image<br>public ref class Compositor <br>{<br> // ...<br>};<o:p></o:p></p> <p><br>  cȝ束类型必L未密的QunsealedQ参考类Q数值类和密类都是不允许的Q因为它们不允许l承Q。有四个System名字I间cL止出现在约束子句中的,它们分别是:(x)System::Array、System::Delegate?System::Enum和System::ValueType。由于CLI只支持单l承Qsingle inheritanceQ,U束子句只支持一个类cd的包含。约束类型至要像泛型或函数那样Ҏ(gu)讉K。例如,你不能声明一个公共泛型ƈ列出一个或多个内部可视的约束?br><br>  Mcd参数都可以绑定到一个约束类型。下面是一个简单的例子Q?o:p></o:p></p> <p>generic <class T1, class T2><br>where T1 : IComparable<T1><br>where T2 : IComparable<T2><br>public ref class Compositor <br>{<br> // ... <br>};<o:p></o:p></p> <p><br>  U束是不能承的。例如,如果我从Compositorl承得到下面的类QCompositor的T1和T2上的IcomparableU束不会(x)应用?BlackWhite_Compositorcȝ同名参数上:(x)<o:p></o:p></p> <p>generic <class T1, class T2><br>public ref class BlackWhite_Compositor : Compositor<br>{<br> // ... <br>};<o:p></o:p></p> <p><br>  当这些参C基类一起用的时候,q就有几分设计方面的便利了。ؓ(f)了保证Compositor的完整性,BlackWhite_Compositor必须把CompositorU束传播l那些传递到Compositor子对象的所有参数。例如,正确的声明如下所C:(x)<o:p></o:p></p> <p>generic <class T1, class T2><br>where T1 : IComparable<T1><br>where T2 : IComparable<T2><br>public ref class BlackWhite_Compositor : Compositor<br>{<br> // ...<br>};<o:p></o:p></p> <p><br>  包装<br><br>  你已l看CQ在C++/CLI下面Q你可以选择CLR泛型或C++模板。现在你所拥有的知识已l可以根据特定的需求作出明智的选择了。在两种机制下,越元素的存储和索功能的参数化类型都包含了每U类型参数必L持操作的假设?br><br>  使用模板的时候,q些假设都是隐含的。这l模板的作者带来了很大的好处,他们对于能够实现什么样的功能有很大的自由度。但是,q对于模板的使用者是不利的,他们l常面对某些可能的类型参C的没有正式文档记载的U束集合。违反这些约束集合就?x)导致编译时错误Q因此它对于q行时的完整性不是威胁,模板cȝ使用可以Lp|出现。这U机制的设计偏好們֐于实现者?<br><br>  使用泛型的时候,q些假设都被明显化了Qƈ与约束子句中列D的基本类型集合相兌。这Ҏ(gu)型的使用者是有利的,q且保证传递给q行时用于类型构造的M泛型都是正确的。据我看来,它在设计的自由度上有一些约束,q且使某些模板设计习(fn)惯稍微难以受到支持。对q些形式U束的违反,无论使在定义点还是在用户指定cd参数的时候,都会(x)D~译旉误。这U机制的设计偏好們֐于消费者?o:p></o:p></p> <p>  从设计的角度来说很难证明它的正确性,因ؓ(f)一般来说容器不?x)集中在在单个默认类型上?br><br>  指针也可以作为非cd参数Q因为对象或函数的地址在编译时已知了Q因此是一个常量表辑ּ。例如,你可能希望ؓ(f)堆栈cL供第三个参数Q这个参数指明遇到特定条件的时候用的回调处理E序。明智地使用typedef可以大幅度简化那些表面上看v来很复杂的声明,如下所C:(x)<o:p></o:p></p> typedef void (*handler)( ... array<Object^>^ );<br>template <class elemType, int size, handler cback ><br>public ref class tStack {};<br>  当然Q你可以为处理程序提供默认?-在这个例子中Q是一个已有的Ҏ(gu)的地址。例如,下面的缓冲区声明提供了大小和处理程序:(x)<br><br>void defaultHandler( ... array<Object^>^ ){ ... }<br><br>template < class elemType, <br>int size = 1024, <br>handler cback = &defaultHandler ><br>public ref class tStack {};<br>  ׃默认值的位置ơ序优先于命名次序,因此如果不提供明的大小|即ɘq个大小与默认值是重复的)Q就无法提供重蝲的处理程序的。下面就是可能用到的修改堆栈的方法:(x)<br><br>void demonstration() <br>{<br> // 默认的大和处理E序<br> tStack<String^> ^ts1 = nullptr; <br> // 默认的处理程?br> tStack<String^, 128> ^ts2 = gcnew tStack<String^, 128>;<br> // 重蝲所有的三个参数<br> tStack<String^, 512, &yourHandler> ^ts3;<br>}<br><br>  模板支持的第二种额外的参数就是template模板参数--也就是这个模板参数本w表Cؓ(f)一个模ѝ例如:(x)<br><br>// template模板参数<br>template <template <class T> class arena, class arenaType><br>class Editor { <br>arena<arenaType> m_arena; <br>// ...<br>};<br>  Editor模板cdZ两个模板参数arena和arenaType。ArenaType是一个模板类型参敎ͼ你可以传递整型、字W串型、自定义cd{等。Arena是一个template模板参数。带有单个模板类型参数的M模板c都可以l定到arena。m_arena是一个绑定到arenaType模板cd参数的模板类实例。例如:(x)<br><br>// 模板~冲区类<br>template <class elemType><br>public ref class tBuffer {};<br><br>void f()<br>{<br> Editor<tBuffer,String^> ^textEditor;<br> Editor<tBuffer,char> ^blitEditor;<br> // ...<br>} <img src ="http://www.shnenglu.com/twzheng/aggbug/23591.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/twzheng/" target="_blank">谭文?/a> 2007-05-08 00:04 <a href="http://www.shnenglu.com/twzheng/articles/23591.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CC++中的预处理宏http://www.shnenglu.com/twzheng/articles/22681.html谭文?/dc:creator>谭文?/author>Mon, 23 Apr 2007 15:19:00 GMThttp://www.shnenglu.com/twzheng/articles/22681.htmlhttp://www.shnenglu.com/twzheng/comments/22681.htmlhttp://www.shnenglu.com/twzheng/articles/22681.html#Feedback0http://www.shnenglu.com/twzheng/comments/commentRss/22681.htmlhttp://www.shnenglu.com/twzheng/services/trackbacks/22681.html 

CC++中的预处理宏

--徐东?/span>

摘要Q?/span>?span>C++从Cl承的遗产中Q预处理宏是其中的一部分。在CC++的发展过E中Q预处理宏是否还有意义?本文讨Z?/span>

关键字:(x)预处??span> #define #pragma

 

   C++中有那么多灵zȝҎ(gu),例如重蝲、类型安全的模板、const关键字等{,Z么程序员q要?#8220;#define”q样的预处理指o(h)Q?/span>

   典型的一个例子,大家都知?#8220;const int a=100;”比“#define a 100”要好Q因为const提供cd安全、避免了预处理的意外修改{?/span>

   然而,q是有一些理p我们M?define?/span>

一、用预处理?/span>

1Q?span>   守护头文?/span>

Z防止头文件被多次包含Q这是一U常用技巧?/span>

#ifndef MYPROG_X_H

#define MYPROG_X_H

// … 头文件x.h的其余部?/span>

#endif

2Q?span>   使用预处理特?/span>

在调试代码中Q插入行h~译旉q类信息通常很有用,可以使用预定义的标准宏,例如__FILE__、__LINE__、__DATE__和__TIME__?/span>

3Q?span>   ~译时期选择代码

A. 调试代码

选择性的输出一些调试信息:(x)

void f()

{

#ifdef _DEBUG

   cerr<<”调试信息”<<endl;

#endif

// .. f()的其他部?/span>

}

通常我们也可以用条g判断来代替:(x)

void f()

{

   if(_DEBUG)

   {

   cerr<<”调试信息”<<endl;

}

// .. f()的其他部?/span>

}

B. 特定q_代码

同一函数同一功能在不同的~译q_上可能有不同的表现Ş式,我们可以通过定义宏来区分不同的^台?/span>

C. 不同的数据表C方?/span>

<<深入出MFC>>q本书对MFC框架中宏的用解析的很透彻Q也让我们领略到宏的强大功能。可以参看DECLARE_MESSAGE_MAP(),

BEGIN_MESSAGE_MAP, END_MESSAGE_MAP的实现?/span>

4Q?span>   #pragma的用,例如?pragma止掉无伤大雅的警告Q用于可UL性的条g~译中。例如,

包含winsock2 lib文gQ?/span>

#pragma comment(lib,ws2_32)

用如下预处理宏,可以使结构按1字结寚wQ?/span>

#pragma pack(push)

#pragma pack(1)

// l构定义

#pragma pack(pop)

     止掉某些警告信息:(x)

#pragma warning( push )

#pragma warning( disable : 4705 )

#pragma warning( disable : 4706 )

#pragma warning( error : 164 )// ?64可告作为错误报?/span>

// Some code

#pragma warning( pop )

 

二、宏的常见陷?/span>

   下面C如何写一个简单的预处理宏max()Q这个宏有两个参敎ͼ比较q返回其中较大的一个倹{在写这样一个宏ӞҎ(gu)犯哪些错误?有四大易犯错误?/span>

1Q?span>   不要忘记为参数加上括?/span>

// ?Q括号陷׃Q参?/span>

//

#define max(a, b) a < b ? b : a

例如Q?/span>

max(i += 2, j)

展开后:(x)

i += 2 < j ? j : i += 2

考虑q算W优先和语a规则Q实际上是:(x)

i += ((2 < j) ? j : i += 2)

q种错误可能需要长旉的调试才可以发现?/span>

2Q?span>   不要忘记为整个展开式加上括?/span>

// ?Q括号陷׃Q展开?/span>

//

#define max(a, b) (a) < (b) ? (b) : (a)

   例如Q?/span>

   m = max(j, k) + 42;

   展开后ؓ(f)Q?/span>

   m = (j) < (k) ? (j) : (k) + 42;

考虑q算W优先和语a规则Q实际上是:(x)

   m = ((j) < (k)) ? (j) : ((k) + 42);

   如果j >= k, m被赋值k+42,正确Q如果j < k, m被赋值j,是错误的。如果给展开式加上括Pp决了q个问题?/span>

3Q?span>   当心多参数运?/span>

// ?Q多参数q算

//

#define max(a, b) ((a) < (b) ? (b) : (a))

max(++j, k);

   如果++j的结果大于kQj?x)递增两次Q这可能不是E序员想要的Q?/span>

((++j) < (k) ? (k) : (++j))

   cM的:(x)

max(f(), pi)

展开后:(x)

((f()) < (pi) ? (pi) : (f()))

如果f()的结果大于等于piQf()?x)执行两ơ,q绝对缺乏效率,而且可能是错误的?/span>

4Q?span>   名字冲突

宏只是执行文本替换,而不文本在哪儿Q这意味着只要使用宏,p心对这些宏命名。具体来_(d)q个max宏最大的问题是,极有可能?x)和标准的max()函数模板冲突Q?/span>

// ?Q?span>名字冲突

//

#define max(a,b) ((a) < (b) ? (b) : (a))

#include <algorithm> // 冲突!

?span><algorithm>中,有如下:(x)

template<typename T> const T&

max(const T& a, const T& b);

宏将它替换ؓ(f)如下Q将无法~译Q?/span>

template<typename T> const T&

((const T& a) < (const T& b) ? (const T& b) : (const T& a));

所以,我们量避免命名的冲H,惛_一个不q_的,难以拼写的名字,q样才能最大可能地避免与其他名字空间冲H?/span>

 

宏的其他~陷Q?/span>

5Q?span>   宏不能递归

   Ҏ(gu)理解?/span>

6Q?span>   宏没有地址

你可能得CQ何自由函数或成员函数的指针,但不可能得到一个宏的指针,因ؓ(f)宏没有地址。宏之所以没有地址Q原因很昄===宏不是代码,宏不?x)以自n的Ş势存在,因ؓ(f)它是一U被化了的文本替换规则?/span>

7Q?span>   宏有调?/span>

在编译器看到代码之前Q宏׃(x)修改相应的代码,因而,他会(x)严重改变变量名称和其他名Uͼ此外Q在调试阶段Q无法跟t到宏的内部?/span>



]]>
[转] 深入探讨MFC消息循环和消息܇http://www.shnenglu.com/twzheng/articles/22071.html谭文?/dc:creator>谭文?/author>Mon, 16 Apr 2007 16:12:00 GMThttp://www.shnenglu.com/twzheng/articles/22071.htmlhttp://www.shnenglu.com/twzheng/comments/22071.htmlhttp://www.shnenglu.com/twzheng/articles/22071.html#Feedback0http://www.shnenglu.com/twzheng/comments/commentRss/22071.htmlhttp://www.shnenglu.com/twzheng/services/trackbacks/22071.html [转] 深入探讨MFC消息循环和消息܇

深入探讨MFC消息循环和消息܇

作者:(x)周焱

?先,应该清楚MFC的消息@?::GetMessage,::PeekMessage)Q消息܇(CWinThread::PumpMessage)?MFC的消息在H口之间的\由是两g不同的事情。在MFC的应用程序中(应用E序cd于CWinThreadl承)Q必要有一个消息@环,他的作用是从 应用E序的消息队列中d消息Qƈ把它zN出?::DispatchMessage)。而消息\由是指消息派送出M后,pȝ(USER32.DLL) 把消息投递到哪个H口Q以?qing)以后消息在H口之间的传递是怎样的?/font>

消息分ؓ(f)队列消息(q入U程的消息队? 和非队列消息(不进入线E的消息队列)。对于队列消息,最常见的是鼠标和键盘触发的消息Q例如WM_MOUSERMOVE,WM_CHAR{消息;q有?如:(x)WM_PAINT、WM_TIMER和W(xu)M_QUIT。当鼠标、键盘事件被触发后,相应的鼠标或键盘驱动E序׃(x)把这些事件{换成相应的消息,然后?送到pȝ消息队列Q由Windowspȝ负责把消息加入到相应U程的消息队列中Q于是就有了消息循环(从消息队列中dq派送消?。还有一U是非队列消 息,他绕q系l队列和消息队列Q直接将消息发送到H口q程。例?当用hzM个窗口系l发送WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR。创建窗口时发送WM_CREATE消息。在后面你将看到QMSq么设计是很有道理的Q以?qing)他的整套实现机制?/p>

q里讲述MFC的消息@环,消息c(din)先看看E序启动Ӟ怎么q入消息循环的:(x)
_tWinMain ->AfxWinMain ->AfxWinInit ->CWinThread::InitApplication ->CWinThread::InitInstance ->CWinThread::Run

非对话框E序的消息@环的事情都从qC(j)WinThread的一Run开?..

W一部分Q非对话框程序的消息循环机制?/strong>

//thrdcore.cpp
// main running routine until thread exits
int CWinThread::Run()
{
ASSERT_VALID(this);

// for tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;

// acquire and dispatch messages until a WM_QUIT message is received.
for (;;)
{
// phase1: check to see if we can do idle work
while (bIdle &&
   !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
{
   // call OnIdle while in bIdle state
   if (!OnIdle(lIdleCount++))
    bIdle = FALSE; // assume "no idle" state
}

// phase2: pump messages while available
do
{
   // pump message, but quit on WM_QUIT
   if (!PumpMessage())
    return ExitInstance();

   // reset "no idle" state after pumping "normal" message
   if (IsIdleMessage(&m_msgCur))
   {
    bIdle = TRUE;
    lIdleCount = 0;
   }

} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
}    //无限循环Q退出条件是收到WM_QUIT消息?/font>

ASSERT(FALSE); // not reachable
}

q是一个无限@环,他的退出条件是收到WM_QUIT消息Q?/p>

if (!PumpMessage())
    return ExitInstance();

在PumpMessage中,如果收到WM_QUIT消息Q那么返回FALSE,所以ExitInstance()函数执行Q蟩出@环,q回E序的退Z码。所以,一个程序要退出,只用在代码中调用函数

VOID PostQuitMessage( int nExitCode )。指定退Z码nExitCode可以退出程序?/font>

下面讨论一下这个函数Run的流E,分两步:(x)

1, W一个内循环phase1。bIdle代表E序是否I闲。他的意思就是,如果E序是空闲ƈ且消息队列中没有要处理的消息Q那么调用虚函数OnIdleq行 I闲处理。在q个处理中将更新UI界面(比如工具栏按钮的enable和disable状?Q删除(f)时对?比如用FromHandle得到的对象指 针。由于这个原因,在函C间传递由FromHandle得到的对象指针是不安全的Q因Z没有持久?。OnIdle是可以重载的Q你可以重蝲他ƈq回 TRUE使消息@环l处于空闲状态?/p>

NOTEQMS用(f)时对象是Z效率上的考虑Q内存 有效利用Qƈ能够在空闲时自动撤销资源。关于由句柄转换成对象,可以有若q种Ҏ(gu)。一般是先申明一个对象obj,然后使用obj.Attatch来和一?句柄l定。这样生的对象是永久的Q你必须用obj.Detach来释攑֯象?/font>

2Q第二个内@环phase2。在q个循环内先启动消息?PumpMessage),如果不是WM_QUIT消息Q消息܇消息发送出?::DispatchMessage)。消息的目的地是消息l构中的hwnd字段所对应的窗口?br>//thrdcore.cpp
BOOL CWinThread::PumpMessage()
{
ASSERT_VALID(this);

//如果是WM_QUIT退出函?return FALSE)Q这导致程序结?
if (!::GetMessage(&m_msgCur, NULL, NULL, NULL)) {
#ifdef _DEBUG
   if (afxTraceFlags & traceAppMsg)
    TRACE0("CWinThread::PumpMessage - Received WM_QUIT.\n");
   m_nDisablePumpCount++; // application must die
    // Note: prevents calling message loop things in 'ExitInstance'
    // will never be decremented
#endif
   return FALSE;
}

#ifdef _DEBUG
if (m_nDisablePumpCount != 0)
{
   TRACE0("Error: CWinThread::PumpMessage called when not permitted.\n");
   ASSERT(FALSE);
}
#endif

#ifdef _DEBUG
if (afxTraceFlags & traceAppMsg)
   _AfxTraceMsg(_T("PumpMessage"), &m_msgCur);
#endif

// process this message

if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
{
   ::TranslateMessage(&m_msgCur); //键{?/font>
   ::DispatchMessage(&m_msgCur); //zN消?/font>
}
return TRUE;
}

?q一步有一个特别重要的函数大家一定认识:(x)PreTranslateMessage。这个函数在::DispatchMessage发送消息到H口之前Q?q行Ҏ(gu)息的预处理。PreTranslateMessage函数是CWinThread的成员函敎ͼ大家重蝲的时候都是在ViewcL者主H口cMQ那 么,它是怎么q入别的cȝ呢?代码如下Q?br>//thrdcore.cpp
BOOL CWinThread::PreTranslateMessage(MSG* pMsg)
{
ASSERT_VALID(this);

// 如果是线E消息,那么会(x)调用U程消息的处理函?/font>
if (pMsg->hwnd == NULL && DispatchThreadMessageEx(pMsg))
   return TRUE;

// walk from target to main window
CWnd* pMainWnd = AfxGetMainWnd();
if (CWnd::WalkPreTranslateTree(pMainWnd->GetSafeHwnd(), pMsg))
   return TRUE;

// in case of modeless dialogs, last chance route through main
//   window's accelerator table
if (pMainWnd != NULL)
{
   CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
   if (pWnd->GetTopLevelParent() != pMainWnd)
    return pMainWnd->PreTranslateMessage(pMsg);
}

return FALSE;   // no special processing
}

׃面这个函数可以看出:(x)

W一Q如?pMsg->hwnd == NULL),说明q是一个线E消息。调用CWinThread::DispatchThreadMessageEx到消息映表扑ֈ消息入口Q然后调用消息处理函数?/p>

NOTE: 一般用PostThreadMessage函数发送线E之间的消息Q他和窗口消息不同,需要指定线Eid,消息Ȁ被系l放入到目标U程的消息队列中Q用 ON_THREAD_MESSAGE( message, memberFxn )宏可以映线E消息和他的处理函数。这个宏必须在应用程序类(从CWinThreadl承)中,因ؓ(f)只有应用E序cL处理U程消息。如果你在别的类(?如视囄)中用q个宏,U程消息的消息处理函数将得不到线E消息?/font>

W二Q消息的目标H口?PreTranslateMessage函数首先得到消息处理权,如果函数q回FALSEQ那么他的父H口得到消息的处理权,直到ȝ口;如果函数q回 TRUE(表示消息已经被处理了)Q那么就不需要调用父cȝPreTranslateMessage函数。这P保证了消息的目标H口以及(qing)他的父窗口都?以有Z(x)调用PreTranslateMessage--在消息发送到H口之前q行预处?如果自己处理完然后返回FALSE的话 -_-b),如果你想要消息不传递给父类q行处理的话Q返回TRUEp了?/p>

W三Q如果消息的目标H口和主H口没有父子关系Q那么再调用?H口的PreTranslateMessage函数。ؓ(f)什么这Pq二步知道Q一个窗口的父窗口不是主H口的话Q尽它?PreTranslateMessageq回FALSEQ主H口也没有机?x)调用PreTranslateMessage函数。我们知道,加速键的{换一?在框架窗口的PreTranslateMessage函数中。我N了MFC中关于加速键转换的处理,只有CFrameWnd, CMDIFrameWndQCMDIChildWnd{窗口类有。所以,W三步的意思是Q如果消息的目标H口(他的父窗口不是主H口Q比如一个这L(fng)非模 式对话框)使消息的预处理lO游的?他的PreTranslateMessageq回FALSE)Q那么给一ơ机?x)给ȝ口调?PreTranslateMessage(万一他是某个加速键消息呢?)Q这栯够保证在有非模式对话框的情况下还能保证主H口的加速键好?br>我做了一个小例子Q在对话框类的PreTranslateMessage中,q回FALSE。在ȝ口显C个非模式对话框,在对话框拥有焦点的时候,仍然能够ȀzMH口的快捷键?/p>

MQ整个框架就是让每个消息的目标窗?包括他的父窗?都有Z(x)参与消息到来之前的处理。呵呵~

?此,非对话框的消息@环和消息늚机制差不多了。这个机制在一个无限@环中Q不断地从消息队列中获取消息Qƈ且保证了E序的线E消息能够得到机?x)处理?H口消息在预处理之后被发送到相应的窗口处理过E。那么,q有一点疑问,Z么要一?x)儿调?:PeekMessage,一?x)儿调?: GetMessage呢,他们有什么区别?

NOTEQ一般来_(d)GetMessage被设计用来高效地从消息队列获取消息。如果队列中没有消息Q那么函数GetMessage导致线E休?让出CPU旉)。而PeekMessage是判断消息队列中如果没有消息Q它马上q回0Q不?x)导致线E处于睡眠状态?/font>

?上面的phase1W一个内循环中用CPeekMessageQ它的参数PM_NOREMOVE表示q不从消息队列中U走消息Q而是一个检查询,如果 消息队列中没有消息他立刻q回0Q如果这时线E空闲的话将?x)引h息@环调用OnIdle处理q程(上面讲到了这个函数的重要?。如果将:: PeekMessageҎ(gu)::GetMessage(***),那么如果消息队列中没有消息,U程休眠,直到U程下一ơ获得CPU旉q且有消息出?才可能l执行,q样Q消息@环的I闲旉没有得到应用QOnIdle也将得不到执行。这是Z么既要用::PeekMessage(查询),又要 ?:GetMessage(做实际的工作)的缘故?/p>

W二部分: 对话框程序的消息循环机制

Z对话框的MFC工程和上面的消息循环机制不一栗实际上MFC的对话框工程E序是模式对话框。他和上面讲到的非对话框E序的不同之处,主要在于应用E序对象的InitInstance()不一栗?/p>

//dlg_5Dlg.cpp
BOOL CDlg_5App::InitInstance()
{
AfxEnableControlContainer();
#ifdef _AFXDLL
Enable3dControls();    // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif

CDlg_5Dlg dlg; //定义一个对话框对象
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal(); //对话框的消息循环在这里面开?/font>
if (nResponse == IDOK)
{
   // TODO: Place code here to handle when the dialog is
   // dismissed with OK
}
else if (nResponse == IDCANCEL)
{
   // TODO: Place code here to handle when the dialog is
   // dismissed with Cancel
}

// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}

NOTE: InitInstance函数q回FALSEQ由最上面E序启动程可以看出QCWinThread::Run是不?x)得到执行的。也是_(d)上面W一部分 说的消息循环在对话框中是不能执行的。实际上Q对话框也有消息循环Q她的消息@环在CDialog::DoModal()虚函C的一?RunModalLoop函数中?/font>

q个函数的实C在CWndcMQ?br>int CWnd::RunModalLoop(DWORD dwFlags)
{
ASSERT(::IsWindow(m_hWnd)); // window must be created
ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state

// for tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;
BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
HWND hWndParent = ::GetParent(m_hWnd);
m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
MSG* pMsg = &AfxGetThread()->m_msgCur;

// acquire and dispatch messages until the modal state is done
for (;;)
{
   ASSERT(ContinueModal());

   // phase1: check to see if we can do idle work
   while (bIdle &&
    !::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
   {
    ASSERT(ContinueModal());

    // show the dialog when the message queue goes idle
    if (bShowIdle)
    {
     ShowWindow(SW_SHOWNORMAL);
     UpdateWindow();
     bShowIdle = FALSE;
    }

    // call OnIdle while in bIdle state
    if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
    {
     // send WM_ENTERIDLE to the parent
     ::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
    }
    if ((dwFlags & MLF_NOKICKIDLE) ||
     !SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
    {
     // stop idle processing next time
     bIdle = FALSE;
    }
   }

// phase2: pump messages while available
   do
   {
    ASSERT(ContinueModal());

    // pump message, but quit on WM_QUIT
   //PumpMessage(消息?的实现和上面讲的差不多。都是派送消息到H口?/font>
    if (!AfxGetThread()->PumpMessage())
    {
     AfxPostQuitMessage(0);
     return -1;
    }

    // show the window when certain special messages rec'd
    if (bShowIdle &&
     (pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
    {
     ShowWindow(SW_SHOWNORMAL);
     UpdateWindow();
     bShowIdle = FALSE;
    }

    if (!ContinueModal())
     goto ExitModal;

    // reset "no idle" state after pumping "normal" message
    if (AfxGetThread()->IsIdleMessage(pMsg))
    {
     bIdle = TRUE;
     lIdleCount = 0;
    }

   } while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
} //无限循环

ExitModal:
m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
return m_nModalResult;
}

先说说怎么退个无限@环,在代码中Q?br>if (!ContinueModal())
goto ExitModal;
军_是否退出@环,消息循环函数q回也就是快要结束结束程序了?br>BOOL CWnd::ContinueModal()
{
return m_nFlags & WF_CONTINUEMODAL;
}

NOTE: CWnd::ContinueModal()函数查对话框是否l箋模式。返回TRUE,表示现在是模式的Q返回FALSEQ表C对话框已经不是模式(要l束)?/font>

?果要l束对话框,在内部最l会(x)调用函数CWnd::EndModalLoopQ它取消m_nFlags的模式标?消息循环中的 ContinueModal函数返回FALSEQ消息@环将l束Q程序将退?Q然后激发消息@环读取消息。也是_(d)l束模式对话框是一个标志,改变 q个标志可以了。他的代码是Q?/p>

//wincore.cpp
void CWnd::EndModalLoop(int nResult)
{
ASSERT(::IsWindow(m_hWnd));

// this result will be returned from CWnd::RunModalLoop
m_nModalResult = nResult;

// make sure a message goes through to exit the modal loop
if (m_nFlags & WF_CONTINUEMODAL)
{
   m_nFlags &= ~WF_CONTINUEMODAL;
   PostMessage(WM_NULL);
}
}

NOTE: PostMessage(NULL)是有用的。如果消息队列中没有消息的话Q可能消息@环中的ContinueModal()不会(x)马上执行Q发送一个空消息是激发消息@环马上工作?/font>

下面说一下CWnd::RunModalLoop函数中的消息循环I竟q了些什么事?
1, W一个内循环。首先从消息队列中查询消息,如果对话框空Ԍ而且消息队列中没有消息,他做三g事情Q大家应到都能从字面上明白什么意思。最重要的是发?WM_KICKIDLE消息。ؓ(f)什么呢Q第一部分讲到了,非对话框E序用OnIdle来更新用L(fng)?UI)Q比如工hQ状态栏。那么,如果对话框中?有工h和状态栏呢,在哪里更?|上有很多这L(fng)E序)Q可以处理WM_KICKIDLE消息Q?br>
LRESULT CDlg_5Dlg::OnKickIdle(WPARAM w,LPARAM l)
{
     //调用CWnd::UpdateDialogControls更新用户界面
     UpdateDialogControls(this, TRUE);
     return 0;
}

NOTE: CWnd::UpdateDialog函数发送CN_UPDATE_COMMAND_UI消息l所有的用户界面对话框控件?/font>

2, W二个内循环。最重要的还是PumpMessagezN消息到目标H口。其他的Q像W二个if语句Q?x118消息好像是WM_SYSTIMER消息(p?l用来通知光标跛_的一个消?。也是_(d)如果消息为WM_SYSTIMER或者WM_SYSKEYDOWN,q且I闲昄标志为真的话Q就昄H口q?通知H口立刻重绘?/p>

MQ对话框的消息@环机制和非对话框(比如SDI,MDI)q是cM 的,仅仅侧重点不同。模式对话框是模式显C,自然有他的特炏V下面部分讨Z下模式对话框和非模式对话框的区别。因为模式对话框有自qҎ(gu)消息循环Q?非模式对话框Q共用程序的消息循环Q和普通的H口已经没有什么大的区别了?/font>

W三部分Q模式对话框和非模式对话框的区别

q个话题已经有很多h讨论Q我说说我所理解的意思?br>在MFC 框架中,一个对话框对象DoModal一下就能生一个模式对话框QCreate一下就能生一个非模式对话框。实际上Q无论是模式对话框还是非模式对话 框,在MFC内部都是调用::CreateDialogIndirect(***)函数来创建非模式对话框。只是模式对话框作了更多的工作,包括使父H口 无效Q然后进入自q消息循环{等?:CreateDialogIndirect(***)函数最l调用CreateWindowEx函数通知pȝ创徏 H体q返回句柄,他内部没有实现自q消息循环?br>非模式对话框创徏之后立即q回Qƈ且和ȝ序共用一个消息@环。非模式对话框要{对话框l束之后才返回,自己有消息@环。比如下面的代码Q?br>CMyDlg* pdlg = new CMyDlg;
pdlg ->Create(IDD_DIALOG1);
pdlg->ShowWindow(SW_SHOW);
MessageBox("abc");
非模式对话框和消息框MessageBox几乎是同时弹出来。而如果将CreateҎ(gu)DoModalQ那么,只能弹出模式对话框,在关闭了对话框之?模式对话框自q消息循环l束)Q消息框才弹出来?/p>

NOTEQ?可以在模式对话框中调用GetParent()->EnableWindow(true);q样Q主H口的菜单,工具栏又ȀzMQ能用了。MFC?用非模式对话框来模拟模式对话框,而在win32 SDKE序中,模式对话框激发他的父H口Enable操作是没有效果的?/font>

关于消息循环ȝQ?/strong>


1Q?我们站在一个什么高度看消息循环Q消息@环其实没有什么深奥的道理。如果一个邮递员要不断在一个城市中送信Q我们要求他做什么?要求他来回跑Q但他一ơ只 能在一个地方出现。如果我们的应用E序只有一个线E的话,我们要他不断Cؓ(f)H口传递消息,我们怎么做?在一个@环中不断的检消息,q将他发送到适当的窗 口。窗口可以有很多个,但消息@环只有一个,而且每时每刻最多只有一个地方在执行代码。ؓ(f)什么? 看第二点?/p>

2Q因为是单线E的(E序q程 启动的时候,只有而且有一个线E,我们UCZU程),所以就像邮递员一P每次只能在某一个地方干zR什么意思呢QD个例子,?: DiapatchMessagezN消息,在窗口处理过E?WinProc,H口函数)q回之前Q他是阻塞的,不会(x)立即q回Q也是消息循环此时不能再从 消息队列中读取消息,直到::DispatchMessageq回。如果你在窗口函C执行一个死循环操作Q就你用PostQuitMessage函数 退出,E序也会(x)down掉?br>while(1)
{
    PostQuitMessage(0); //E序照样down.
}
所 以,当窗口函数处理没有返回的时候,消息循环是不?x)从消息队列中读取消息的。这也是Z么在模式对话框中要自q无限循环来l消息@环,因ؓ(f)q个无限?环阻塞了原来的消息@环,所以,在这个无限@环中要用GetMessage,PeekMessage,DispatchMessage来从消息队列中读?消息q派送消息了。要不然E序׃?x)响应了Q这不是我们所希望的?br>所以说Q消息@环放在程序的什么的地方都基本上是过的去的,比如攑֜DLL?面。但是,最好在M时候,只有一个消息@环在工作(其他的都被阻塞了)。然后,我们要作好的一件事情,是怎么从消息@环中退出!当然用WM_QUIT 是可以拉~(PostThreadMessage也是个好L)Q这个消息@环退出后Q可能程序退出,也可能会(x)Ȁzd外一个被d的消息@环,E序l箋q?行。这要看你怎么惻I怎么d。最后一个消息@环结束的时候,也许是E序快结束的时候,因ؓ(f)ȝE的执行代码也快要完?除非BT的再作个d@??/p>

NOTE: 让windowspȝ知道创徏一个线E的唯一Ҏ(gu)是调用API CreatThread函数(__beginthreadex之类的都要在内部调用他创建新U程)。好像windows核心~程_(d)在win2000下, pȝ用CreateRemoteThread函数来创建线E,CreateThread在内部调用CreateRemoteThread。不q这不是争论 的焦点,臛_win98下CreateRemoteThreadq不能正常工作,q是CreateThreadL大局?/font>

3Q在整个消息循环的机制中Q还必须谈到H口函数的可重入性。什么意思?是H口函数(他是个回调函?的代码什么时候都可以被系l?调用者一般是user32模块)调用。比如在H口q程中,向自qH口SendMessage(***);那么执行q程是怎样的?
我们知道QSendMessage是要{到消息发送ƈ被目标窗口执行完之后才返回的。那么窗口在处理消息Q然后又{待刚才发送到本窗口的消息被处理后之后(SendMessageq回)才l往下执行,E序不就互相死锁了吗Q?
?实是不会(x)的。windows设计一套适合SendMessage的算法,他判断如果发送的消息是属于本U程创徏的窗口的Q那么直接由user32模块调用 H口函数(可能有H口重入)Qƈ消息的处理l果l果q回。这样做体现了窗口重入。上面的例子Q我们调用SendMessage(***)发送消息到?H口Q那么窗口过E再ơ被调用Q处理完消息之后结果返回,然后SendMessage之后的程序接着执行。对于非队列消息Q如果没有窗口重入,不知道会(x) 是什么样子?/p>

NOTE: ׃H口的可重入性。在win32 SDKE序中应量用全局变量和静态变量,因ؓ(f)在窗口函数执行过E中可能H口重入Q如果重入后这些变量改了,但你的程序在H口重入q回之后l箋执行Q?可能是使用已经改变的全局或静态变量。在MFC?所有窗口的H口函数基本上都是AfxWndProc)Q按照类的思想q行了组l,一般变量都是类?的,好管理的多?/font>

4,MFC中窗口类(比如C**View,CFrameWnd{?中的MessageBox函数Q以?AfxMessageBox函数都是d原有的消息@环的。由消息框内部的一个消息@环来从消息队列中d消息QƈzN消?和模式对话框cM)。实?上,q些消息函数最l调用的?:MessageBoxQ它在消息框内部实现了一个消息@?原有的主E序消息循环被阻塞了)。论坛中到q几ơ关于计?器和消息框的问题Q看下面的代码:(x)
void CTest_recalclayoutView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
MessageBox("abc");
while(1); //设计一个死循环
CView::OnTimer(nIDEvent);
}
?让OnTimer大约5U钟弹出一个消息框。那么,消息框不断的被弹出来Q只要消息框不被关闭Q那么程序就不会(x)q入d@环。实际上Q每ơ弹出对话框Q都?最上层的那个消息框掌握着消息循环Q其他的消息循环被阻塞了。只要不关闭最上面的消息框Qwhile(1);得不到执行。如果点了关闭,E序p入了?循环Q只能用ctrl+alt+del来解决问题了?/p>

5Q消息@环在很多地方都有应用。比如应用在U程池中。一个线E的执行周期一般在U程 函数q回之后l束Q那么怎么廉U程的生命周期呢Q一U方法就是按照消息@环的思想Q在U程中加入消息@环,不断CU程队列d消息Qƈ处理消息Q线E?的生命周期就保持着直到q个消息循环的退出?/p>

NOTEQ只要线E有界面元素或者调用GetMessage,或者有U程消息发送过来,pȝ׃(x)为线E创Z个消息队列?/font>

 

6, 在单U程E序中,如果要执行一个长旉的复杂操作而且界面要有相应的话Q可以考虑用自q消息c(din)比如,可以一个阻塞等待操作放在一个@环中Qƈ超?D|得比较?yu),然后每个{待的片D中用消息܇l箋消息循环Q界面能够响应用户操作。等{之c,都可以应用消息܇(调用一个类DL(fng)函数)Q?br>BOOL CChildView::PeekAndPump()
{
MSG msg;
while(::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
{
   if(!AfxGetApp()->PumpMessage())
   {
    ::PostQuitMessage(0);
    return false;
   }
}
return true;
}
其实Q用多线E也能解军_杂运时的界面问题,但是没有q么方便Q而且一般要加入U程通信和同步,考虑的事情更多一炏V?/p>

 

lg所qͼMFC消息循环那么回事,主要思想q是和SDK中差不多。这U思想主要的特点表现在q合MFC整个框架上,为整个框架服务,为应用和功能服务。这是我的理解。呵呵~



]]>
用VC.NET制作启动屏幕http://www.shnenglu.com/twzheng/articles/20818.html谭文?/dc:creator>谭文?/author>Mon, 02 Apr 2007 03:36:00 GMThttp://www.shnenglu.com/twzheng/articles/20818.htmlhttp://www.shnenglu.com/twzheng/comments/20818.htmlhttp://www.shnenglu.com/twzheng/articles/20818.html#Feedback0http://www.shnenglu.com/twzheng/comments/commentRss/20818.htmlhttp://www.shnenglu.com/twzheng/services/trackbacks/20818.html
[源] http://upschool.com.cn/edu/1333/2006/85/10du135181_1.shtml

基本原理是利用对话框H口的特性,在启动时首先创徏对话框,讄一个获得位图文件的句柄Q利用Picture控g的SetBitmap(HBITMAP hBitmap)Ҏ(gu)Q位图文g充满整个Picture控gH口Q最后设|定时器Q整个启动屏q就制作完成?br>  下面介绍具体实现步骤?br>
  1. 打开VS.net的开发环境,新徏VC++.net中的MFC应用E序Q输入工E名UMySampleQ点?#8220;定”Q?#8220;完成”Q?br>
  2. 打开资源视图Q添加对话框Q更改ID为ID_DIALOG_SPLASHQ设|对话框Center属性ؓ(f)TrueQBorder属性ؓ(f)“?#8221;Q?br>
  3. 在对话框中添加Picture控gQ设|Picture控g的ID号ؓ(f)ID_PICQType属性ؓ(f)“位图”QCenter image属性ؓ(f)TrueQ然后调整标Z对话框没有外框,调整对话框的大小以适应启动屏幕的要求,调整Picture的宽高其充满整个对话框H口Q?br>
  4. 双击对话框窗口,弹出cd导对话框Q在cd中键入CSplashQ选择基类为CdialogQ点ȝ定,定义控gPicture的控件变量ؓ(f)m_picQ?br>
  5. 在CsplashcM重蝲OnInitDialog()函数Q添加消息WM_CHARQW(xu)M_TIMERQW(xu)M_LBUTTONUPQW(xu)M_MBUTTONUPQW(xu)M_RBUTTONUPQ?br>
  6. 在OnInitDialog()函数中添加代码如下:(x)

BOOL CSplash::OnInitDialog()
{
 CDialog::OnInitDialog();
 //讄启动H口背景,在整个窗口中充满位图
 CRect lRect;
 m_pic.GetClientRect(&lRect);//得到Picture控g的窗口大?br> lRect.NormalizeRect();
 //讄位图句柄
 HBITMAP hbitmap=(HBITMAP)LoadImage(NULL,"splash.bmp",//更改你喜Ƣ的位图文g
 IMAGE_BITMAP,lRect.Width(),lRect.Height(),
 LR_LOADFROMFILE|LR_CREATEDIBSECTION);
 m_pic.SetBitmap(hbitmap);

 //讄定时?br> SetTimer(1,500,NULL);
 return TRUE;
}

  7. 在OnTimer(UINT nIDEvent) 函数中添加代码如下:(x)

void CSplash::OnTimer(UINT nIDEvent)
{
 static int i;
 i++;
 if(i > 3)
 {
  //销毁定时器
  KillTimer(1);
  this->OnOK();
 }
 CDialog::OnTimer(nIDEvent);
}

  8. 在OnLButtonUpQOnLButtonUpQOnLButtonUpQOnChar函数中加入以下代码:(x)

{
 KillTimer(1);
 this->OnOK();
}

  9. 在MySample.Cpp中引入头文g

#include "Splash.h"

  在InitInstance()函数中加入代码:(x)

BOOL CMySampleApp::InitInstance()
{
 …
 AfxEnableControlContainer();
 CSplash splash;
 splash.DoModal();
 …
}


]]>
字符串函?strtok(char *s, char *delim)http://www.shnenglu.com/twzheng/articles/21052.html谭文?/dc:creator>谭文?/author>Sun, 01 Apr 2007 10:09:00 GMThttp://www.shnenglu.com/twzheng/articles/21052.htmlhttp://www.shnenglu.com/twzheng/comments/21052.htmlhttp://www.shnenglu.com/twzheng/articles/21052.html#Feedback1http://www.shnenglu.com/twzheng/comments/commentRss/21052.htmlhttp://www.shnenglu.com/twzheng/services/trackbacks/21052.html strtok
  原型Qextern char *strtok(char *s, char *delim);
                        用法Q?include <string.h>
                        功能Q分解字W串Zl标C。s分解的字W串Qdelim为分隔符字符丌Ӏ?
                        说明Q首ơ调用时Qs必须指向要分解的字符Ԍ随后调用要把s设成NULL?
                        strtok在s中查扑֌含在delim中的字符q用NULL('\0')来替换,直到N整个字符丌Ӏ?
                        q回指向下一个标C。当没有标记串时则返回空字符NULL?
                        举例Q?
                        // strtok.c
                        #include <syslib.h>
                        #include <string.h>
                        #include <stdio.h>
                        main()
                        {
                        char *s="Golden Global View";
                        char *d=" ";
                        char *p;
                        clrscr();
                        p=strtok(s,d);
                        while(p)
                        {
                        printf("%s\n",s);
                        strtok(NULL,d);
                        }
                        getchar();
                        return 0;
                        }
                        相关函数Qstrcspn , strpbrk


]]>
ASCII Tablehttp://www.shnenglu.com/twzheng/articles/21050.html谭文?/dc:creator>谭文?/author>Sun, 01 Apr 2007 08:39:00 GMThttp://www.shnenglu.com/twzheng/articles/21050.htmlhttp://www.shnenglu.com/twzheng/comments/21050.htmlhttp://www.shnenglu.com/twzheng/articles/21050.html#Feedback0http://www.shnenglu.com/twzheng/comments/commentRss/21050.htmlhttp://www.shnenglu.com/twzheng/services/trackbacks/21050.html

ASCII table and description
ASCII stands for American Standard Code for Information Interchange. Computers can only understand numbers, so an ASCII code is the numerical representation of a character such as 'a' or '@' or an action of some sort. ASCII was developed a long time ago and now the non-printing characters are rarely used for their original purpose. Below is the ASCII character table and this includes descriptions of the first 32 non-printing characters. ASCII was actually designed for use with teletypes and so the descriptions are somewhat obscure. If someone says they want your CV however in ASCII format, all this means is they want 'plain' text with no formatting such as tabs, bold or underscoring - the raw format that any computer can understand. This is usually so they can easily import the file into their own applications without issues. Notepad.exe creates ASCII text, or in MS Word you can save a file as 'text only'

Extended ASCII Codes

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

Ç

ü

é

â

ä

à

å

ç

ê

ë

è

ï

î

ì

Ä

Å

É

æ

Æ

ô

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

ö

ò

û

ù

ÿ

Ö

Ü

ø

£

Ø

×

ƒ

á

í

ó

ú

ñ

Ñ

ª

º

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

¿

®

¬

½

¼

¡

«

»

_

_

_

¦

¦

Á

Â

À

©

¦

¦

+

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

+

¢

¥

+

+

-

-

+

-

+

ã

Ã

+

+

-

-

¦

-

+

¤

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

ð

Ð

Ê

Ë

È

i

Í

Î

Ï

+

+

_

_

¦

Ì

_

Ó

ß

Ô

Ò

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

õ

Õ

µ

þ

Þ

Ú

Û

Ù

ý

Ý

¯

´

­

±

_

¾

§

÷

¸

248

249

250

251

252

253

254

255

 

 

 

 

 

 

 

 

 

 

 

 

°

¨

·

¹

³

²

_

 

fine

 

 

 

 

 

 

 

 

 

 

 

 

Extended ASCII Codes
As people gradually required computers to understand additional characters and non-printing characters the ASCII set became restrictive. As with most technology, it took a while to get a single standard for these extra characters and hence there are few varying 'extended' sets. The most popular is presented below.

.

IBM Scan Codes
The following table is nothing to do with ASCII, but has been requested by a number of you out there. When a key on your keyboard is pressed, a code is sent which can be recognised by software. Programmers will find the most use for this table to map keys to actions for the function keys etc.

.

EBCDIC Codes
ASCII is not the only format in use out there. IBM adopted EBCDIC (Extended Binary Coded Decimal Interchange Code) developed for punched cards in the early 1960s and still uses it on mainframes today. It is probably the next most well known character set due to the proliferation of IBM mainframes. It comes in at least six slightly differing forms, so again here is the most common.

 

 ----------------------------------------------------------------------------------------------------

ASCII Table (7-bit)
( ASCII = A merican S tandard C ode for I nformation I nterchange)
(also see
Related Links below)

       Decimal   Octal   Hex    Binary     Value       postil
------- ----- --- ------ -----      --------
000 000 000 00000000 NUL    (Null char.)
001 001 001 00000001 SOH    (Start of Header)
002 002 002 00000010 STX    (Start of Text)
003 003 003 00000011 ETX (End of Text)
004 004 004 00000100 EOT (End of Transmission)
005 005 005 00000101 ENQ (Enquiry)
006 006 006 00000110 ACK (Acknowledgment)
007 007 007 00000111 BEL (Bell)
008 010 008 00001000 BS (Backspace)
009 011 009 00001001 HT (Horizontal Tab)
010 012 00A 00001010 LF (Line Feed)
011 013 00B 00001011 VT (Vertical Tab)
012 014 00C 00001100 FF (Form Feed)
013 015 00D 00001101 CR (Carriage Return)
014 016 00E 00001110 SO (Shift Out)
015 017 00F 00001111 SI (Shift In)
016 020 010 00010000 DLE (Data Link Escape)
017 021 011 00010001 DC1 (XON) (Device Control 1)
018 022 012 00010010 DC2 (Device Control 2)
019 023 013 00010011 DC3 (XOFF)(Device Control 3)
020 024 014 00010100 DC4 (Device Control 4)
021 025 015 00010101 NAK (Negative Acknowledgement)
022 026 016 00010110 SYN (Synchronous Idle)
023 027 017 00010111 ETB (End of Trans. Block)
024 030 018 00011000 CAN (Cancel)
025 031 019 00011001 EM (End of Medium)
026 032 01A 00011010 SUB (Substitute)
027 033 01B 00011011 ESC (Escape)
028 034 01C 00011100 FS (File Separator)
029 035 01D 00011101 GS (Group Separator)
030 036 01E 00011110 RS (Request to Send)(Record Separator)
031 037 01F 00011111 US (Unit Separator)
032 040 020 00100000 SP (Space)
033 041 021 00100001 ! (exclamation mark)
034 042 022 00100010 " (double quote)
035 043 023 00100011 # (number sign)
036 044 024 00100100 $ (dollar sign)
037 045 025 00100101 % (percent)
038 046 026 00100110 & (ampersand)
039 047 027 00100111 ' (single quote)
040 050 028 00101000 ( (left/opening parenthesis)
041 051 029 00101001 ) (right/closing parenthesis)
042 052 02A 00101010 * (asterisk)
043 053 02B 00101011 + (plus)
044 054 02C 00101100 , (comma)
045 055 02D 00101101 - (minus or dash)
046 056 02E 00101110 . (dot)
047 057 02F 00101111 / (forward slash)
048 060 030 00110000 0
049 061 031 00110001 1
050 062 032 00110010 2
051 063 033 00110011 3
052 064 034 00110100 4
053 065 035 00110101 5
054 066 036 00110110 6
055 067 037 00110111 7
056 070 038 00111000 8
057 071 039 00111001 9
058 072 03A 00111010 : (colon)
059 073 03B 00111011 ; (semi-colon)
060 074 03C 00111100 < (less than)
061 075 03D 00111101 = (equal sign)
062 076 03E 00111110 > (greater than)
063 077 03F 00111111 ? (question mark)
064 100 040 01000000 @ (AT symbol)
065 101 041 01000001 A
066 102 042 01000010 B
067 103 043 01000011 C
068 104 044 01000100 D
069 105 045 01000101 E
070 106 046 01000110 F
071 107 047 01000111 G
072 110 048 01001000 H
073 111 049 01001001 I
074 112 04A 01001010 J
075 113 04B 01001011 K
076 114 04C 01001100 L
077 115 04D 01001101 M
078 116 04E 01001110 N
079 117 04F 01001111 O
080 120 050 01010000 P
081 121 051 01010001 Q
082 122 052 01010010 R
083 123 053 01010011 S
084 124 054 01010100 T
085 125 055 01010101 U
086 126 056 01010110 V
087 127 057 01010111 W
088 130 058 01011000 X
089 131 059 01011001 Y
090 132 05A 01011010 Z
091 133 05B 01011011 [ (left/opening bracket)
092 134 05C 01011100 \ (back slash)
093 135 05D 01011101 ] (right/closing bracket)
094 136 05E 01011110 ^ (caret/cirumflex)
095 137 05F 01011111 _ (underscore)
096 140 060 01100000 `
097 141 061 01100001 a
098 142 062 01100010 b
099 143 063 01100011 c
100 144 064 01100100 d
101 145 065 01100101 e
102 146 066 01100110 f
103 147 067 01100111 g
104 150 068 01101000 h
105 151 069 01101001 i
106 152 06A 01101010 j
107 153 06B 01101011 k
108 154 06C 01101100 l
109 155 06D 01101101 m

110 156 06E 01101110 n
111 157 06F 01101111 o
112 160 070 01110000 p
113 161 071 01110001 q
114 162 072 01110010 r
115 163 073 01110011 s
116 164 074 01110100 t

117 165 075 01110101 u
118 166 076 01110110 v

119 167 077 01110111 w
120 170 078 01111000 x
121 171 079 01111001 y
122 172 07A 01111010 z
123 173 07B 01111011 { (left/opening brace)
124 174 07C 01111100 | (vertical bar)
125 175 07D 01111101 } (right/closing brace)
126 176 07E 01111110 ~ (tilde)
127 177 07F 01111111 DEL (delete)




]]>
友元函数和友元类http://www.shnenglu.com/twzheng/articles/21020.html谭文?/dc:creator>谭文?/author>Sat, 31 Mar 2007 13:35:00 GMThttp://www.shnenglu.com/twzheng/articles/21020.htmlhttp://www.shnenglu.com/twzheng/comments/21020.htmlhttp://www.shnenglu.com/twzheng/articles/21020.html#Feedback10http://www.shnenglu.com/twzheng/comments/commentRss/21020.htmlhttp://www.shnenglu.com/twzheng/services/trackbacks/21020.html


友元函数和友元类


        采用cȝ机制后实C数据的隐藏与装Q类的数据成员一般定义ؓ(f)U有成员Q成员函C般定义ؓ(f)公有的,依此提供cM外界间的通信接口。但是,有时需要定义一些函敎ͼq些函数不是cȝ一部分Q但又需要频J地讉Kcȝ数据成员Q这时可以将q些函数定义函数的友元函数。除了友元函数外Q还有友元类Q两者统UCؓ(f)友元。友元的作用是提高了E序的运行效率(卛_了cd查和安全性检查等都需要时间开销Q,但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员?br>

友元函数 Q?/strong>
      友元函数是可以直接访问类的私有成员的非成员函数。它是定义在cd的普通函敎ͼ它不属于Mc,但需要在cȝ定义中加以声明,声明时只需在友元的名称前加上关键字friendQ其格式如下Q?br>      friend  cd 函数?形式参数);

      友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的Q都说明是该cȝ一个友元函数?br>
      一个函数可以是多个cȝ友元函数Q只需要在各个cM分别声明?br>      友元函数的调用与一般函数的调用方式和原理一致?/font>

友元c?/strong> Q?/strong>
      友元cȝ所有成员函数都是另一个类的友元函敎ͼ都可以访问另一个类中的隐藏信息Q包括私有成员和保护成员Q?nbsp;      
      当希望一个类可以存取另一个类的私有成员时Q可以将该类声明为另一cȝ友元cR定义友元类的语句格式如下:(x)
      friend class cd;
      其中Qfriend和class是关键字Q类名必LE序中的一个已定义q的cR?br>
      例如Q以下语句说明类B是类A的友元类Q?br>
      class A
      {
             …
      public:
             friend class B;
             …
      };
      l过以上说明后,cB的所有成员函数都是类A的友元函敎ͼ能存取类A的私有成员和保护成员?br>
      使用友元cL注意Q?br>            (1) 友元关系不能被ѝ?/font>
            (2) 友元关系是单向的Q不h交换性?/font>若类B是类A的友元,cA不一定是cB的友元,要看在类中是否有相应的声明?br>            (3) 友元关系不具有传递性?/font>若类B是类A的友元,cC是B的友元,cC不一定是cA的友元,同样要看cM是否有相应的x



]]>
[转]VC~程l验汇?/title><link>http://www.shnenglu.com/twzheng/articles/20615.html</link><dc:creator>谭文?/dc:creator><author>谭文?/author><pubDate>Mon, 26 Mar 2007 06:34:00 GMT</pubDate><guid>http://www.shnenglu.com/twzheng/articles/20615.html</guid><wfw:comment>http://www.shnenglu.com/twzheng/comments/20615.html</wfw:comment><comments>http://www.shnenglu.com/twzheng/articles/20615.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/twzheng/comments/commentRss/20615.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/twzheng/services/trackbacks/20615.html</trackback:ping><description><![CDATA[[源] <a >http://henrycgf.bokee.com/2662860.html</a><br><br><br> <h2 class=diaryTitle>VC~程l验汇?/h2>                                        <p> </p> <div id="1616611" class=postTitle><script language="javascript"></script></div> <div id="6166611" class=postText> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto">1. </span></strong><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">H口最大化、最化的实?/span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt"></span></strong></p> <p> </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'"><font size=3>当我们不能用标题栏的最大化、最化?qing)恢复按钮而又需在其他的地方实现q些功能Q可以在指定的消息处理函数里dQ?/font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>WINDOWPLACEMENT wndpl;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>WINDOWPLACEMENT *pwndpl;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>pwndpl = &wndpl;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>GetWindowPlacement(pwndpl);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US>pwndpl->showCmd = SW_SHOWMINMIZED; //</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实现H口最化</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>SetWindowPlacement(pwndpl);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其中</span><span lang=EN-US>GetWindowPlacement()</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数获取当前H口布局的结?/span><span lang=EN-US>WINDOWPLACEMENT</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的结构变量指针,l构</span><span lang=EN-US>WINDOWPLACEMENT</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">定义为:(x)</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>typedef struct tagWINDOWPLACEMENT{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">    </span>UINT length;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">    </span>UINT flags;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">    </span>UINT showCmd;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">    </span>POINT ptMinPosition;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">    </span>POINT ptMaxPosition;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">    </span>RECT rcNormalPosition;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>}WINDOWPLACEMENT;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其中的成员变?/span><span lang=EN-US>showCmd</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">定当前H口的状态,取g般ؓ(f)Q?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">·</span><span lang=EN-US>SW_HIDE</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q隐藏窗?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">·</span><span lang=EN-US>SW_MINIMIZE</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q最化指定的窗?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">·</span><span lang=EN-US>SW_RESTORE</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q恢复原来的大小</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">·</span><span lang=EN-US>SW_SHOW</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q以原来的大激zdƈ昄</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">·</span><span lang=EN-US>SW_SHOWMAXIMIZED</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q激zdƈ最大化H口</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US>SetWindowPlacement()</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数是?/span><span lang=EN-US>WINDOWPLACEMENT</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的设|来昄H口</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto">2. </span></strong><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Z么要使用</span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto">GetSafeHwnd()</span></strong><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数</span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto"></span></strong></p> <p> </p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当我们想得到一个窗口对象(</span><span lang=EN-US>CWnd</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的派生对象)指针的句柄(</span><span lang=EN-US>HWND</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q时Q最安全的方法是使用</span><span lang=EN-US>GetSafeHwnd()</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数Q通过下面的例子来看其理由Q?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US>CWnd *pwnd = FindWindow(“ExploreWClass”,NULL); //</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">希望扑ֈ资源理?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US>HWND hwnd = pwnd->m_hwnd;<span style="mso-spacerun: yes">  </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">得到它的</span><span lang=EN-US>HWND</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">q样的代码当开始得到的</span><span lang=EN-US>pwnd</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为空的时候就?x)出C?#8220;</span><span lang=EN-US>General protection error</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”</span><span lang=EN-US>,</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">q关闭应用程序,因ؓ(f)一般不能对一?/span><span lang=EN-US>NULL</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">指针讉K其成员,如果用下面的代码Q?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US>CWnd *pwnd = FindWindow(“ExploreWClass”,NULL); //</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">希望扑ֈ资源理?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US>HWND hwnd = pwnd->GetSafeHwnd();<span style="mso-spacerun: yes">  </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">得到它的</span><span lang=EN-US>HWND</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">׃?x)出现问题,因?f)管?/span><span lang=EN-US>pwnd</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">?/span><span lang=EN-US>NULL</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Ӟ</span><span lang=EN-US>GetSafeHwnd</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">仍然可以用,只是q回</span><span lang=EN-US>NULL</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q通过</span><span lang=EN-US>GetSafeHwnd()</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的实C码就更清楚了Q?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>_AFXWIN_INLINE HWND CWnd::GetSafeHwnd() const</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>return this == NULL?NULL:m_hWnd;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>}</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto">3. </span></strong><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如何使程序处于极状?/span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto"></span></strong></p> <p> </p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果我们不想让程序的H口被别人看见,可以让它保持在极小状态:(x)在恢复程序窗口的时候,</span><span lang=EN-US>Window</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">?x)发?/span><span lang=EN-US>WM_QUERYOPEN</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">消息Q只要在其消息处理函数里q回</span><span lang=EN-US>false</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以了?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>BOOL CmainFrame::OnQueryOpen()</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>return false;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>}</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto">4. </span></strong><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如何止和能用关闭按?/span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto"></span></strong></p> <p> </p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>Cmenu *pmenu = AfxGetMainWnd()->GetSystemMenu(FALSE);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>if(pmenu)</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3>pmenu->EnableMenuItem(SC_CLOSE,MF_BYCOMMAND|MF_GRAYED);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>}</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">恢复时只需?/span><span lang=EN-US>MF_GRAYED</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">改ؓ(f)</span><span lang=EN-US>MF_ENABLED</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto">5. </span></strong><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如何在程序中延时</span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto"></span></strong></p> <p> </p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Ҏ(gu)一Q?/span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto"></span></strong></p> <p> </p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US><span style="mso-spacerun: yes">  </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使用</span><span lang=EN-US>sleep</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数Q如延时</span><span lang=EN-US>2</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">U,?/span><span lang=EN-US>sleep(2000);</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Ҏ(gu)二:(x)</span></strong><span lang=EN-US style="BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto"></span></p> <p> </p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US><span style="mso-spacerun: yes">  </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使用</span><span lang=EN-US>sleep</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数的不利在于g时期间不能处理其他的消息Q如果时间太长,好象死ZP利用</span><span lang=EN-US>ColeDateTime</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">cd</span><span lang=EN-US>ColeDateTimeSpan</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">cd现g时就不会(x)出现那样的问题:(x)</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>ColeDateTime start_time = ColeDateTime::GetCurrentTime();</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>ColeDateTimeSpan end_time = ColeDateTime::GetCurrentTime()-start_time;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>While(end_time.GetTotalSeconds() <= 2)</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>MSG msg;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>GetMessage(&msg,NULL,0,0);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>PreTranslateMessage(&msg);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>End_time = ColeDateTime::GetCurrentTime-start_time;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>}</font></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'"><font size=3>q样在g时的时候我们也能够处理其他的消息?/font></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'"><font size=3></font></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'"><font size=3></font></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'"><font size=3></font></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'"><font size=3>看了论坛里的一些ȝ文章很好,我把里面没有怎么看到的也写了一点点出来,不知道有没有重复,希望能有些微的作?</font></span></p> <br><br>本文引用通告地址Q?http://blog.csdn.net/laiyiling/services/trackbacks/22293.aspx <br> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto">6. </span></strong><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如何创徏可׾~的对话?/span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto"></span></strong></p> <p> </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'"><font size=3>在进行对话框的设计时Q有时候我们需要设计可伸羃的对话框Q当用户按下某个按钮时弹出或隐藏对话框的下半部分?/font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q?/span><span lang=EN-US>1</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q、首先在对话框中建立一个图片控件把</span><span lang=EN-US>ID</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设ؓ(f)</span><span lang=EN-US>IDC_DIVIDER</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q?/span><span lang=EN-US>Type</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">讄为矩形,</span><span lang=EN-US>Color</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">讄为黑Ԍq将其设定ؓ(f)一U状Q拖攑֜适当的位|做Z׾~对话框的分割线Q属性设Z可见?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q?/span><span lang=EN-US>2</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q、实现的原理Q先获取对话框的寸大小Q然后根据的位置来确定羃减后的对话框大小Q其实对话框伸羃的变化就是的|在羃减对话框后,我们要不可见的部分控g被禁止,以禁止加速键?/span><span lang=EN-US>TAB</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">键对其的操作Q在扩展对话框后Q原来被止的控件又要能?/span></font></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'"><font size=3>先在对话框上的׾~按钮添加单?yn)L息处理函敎ͼ(x)</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>void C***Dlg::OnButtonExpand()</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US><span style="mso-spacerun: yes">  </span>static int bexpand = FALSE; //</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">讑ֈ始时为已扩展?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US><span style="mso-spacerun: yes">  </span>ExpandDialog(IDC_DIVIDER,bexpand);//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">调用扩展或羃减处理函?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US><span style="mso-spacerun: yes">  </span>Bexpand = !bexpand;//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">状态取反,Zơ的单击处理准备</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>}</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在对话框中添加一个成员函?/span><span lang=EN-US>ExpandDialog</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q用于扩展或~减</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>void C***Dlg::ExpandDialog(int nResourceID,BOOL bexpand)</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><font size=3><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数</span><span lang=EN-US>nResourceID</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示分割U的</span><span lang=EN-US>ID</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><font size=3><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">参数</span><span lang=EN-US>bexpand</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">?/span><span lang=EN-US>TRUE</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">时表C扩展对话框,否则~减对话?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3>static CRect rcLarge;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3>static CRect rcSmall;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><font size=3><span lang=EN-US>if(rcLarge.IsRectNULL())<span style="mso-spacerun: yes">  </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">首次使用时记下对话框的最大、最尺?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>CRect rcLandmark;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>CWnd *pwndLand = GetDlgItem(nResourceID);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>ASSERT(pwndLand);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>GetWindowRect(rcLarge);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>pwndLand->GetWindowRect(rcLandmark);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>rcSmall = rcLarge;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>rcSmall.bottom = rcLandmark.bottom;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3>}</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3>if(bexpand)</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>SetWindowPos(NULL,0,0,rcLarge.Width(),rcLarge.Height(),</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 137.25pt; mso-char-indent-count: 13.07; mso-char-indent-size: 10.5pt"><span lang=EN-US><font size=3>SWP_NOMOVE|SWP_NOZORDER);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 37.5pt"><span lang=EN-US><font size=3>EnableVisible();</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0; mso-char-indent-size: 10.5pt"><span lang=EN-US><font size=3>}</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0; mso-char-indent-size: 10.5pt"><span lang=EN-US><font size=3>else</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0; mso-char-indent-size: 10.5pt"><span lang=EN-US><font size=3>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>SetWindowPos(NULL,0,0,rcSmall.Width(),rcSmall.Height(),</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 136.5pt; mso-char-indent-count: 13.0; mso-char-indent-size: 10.5pt"><span lang=EN-US><font size=3>SWP_NOMOVE|SWP_NOZORDER);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 37.5pt"><span lang=EN-US><font size=3>EnableVisible();</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><span lang=EN-US><font size=3>}</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>}</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3></font></span> </p> <p> </p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在对话框中添加一个成员函?/span><span lang=EN-US>EnableVisible</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q用于能用和止部分控g</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>void C***Dlg:: EnableVisible()</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>CWnd *pwnd = GetDlgItem(GW_CHILD);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>CRect retest;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>CRect rcControl;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>CRect rcShow;</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>GetWindowRect(rcShow);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>While(pwnd != NULL)</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">  </span>{</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 27pt"><span lang=EN-US><font size=3>pwnd->GetWindowRect(rcControl);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 27pt"><span lang=EN-US><font size=3>if(rcTest.IntersectRect(rcShow,rcControl))</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 27pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>pwnd->EnableWindow(TRUE);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 27pt"><span lang=EN-US><font size=3>else</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 27pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>pwnd->EnableWindow(FALSE);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 27pt"><span lang=EN-US><font size=3>pwnd = pwnd->GetWindow(GW_HWNDNEXT);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3><span style="mso-spacerun: yes">   </span>}</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>}</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto">7. </span></strong><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Z么有</span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto">RichEdit</span></strong><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">控g的对话框无法昄</span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto"></span></strong></p> <p> </p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果在对话框上放一?/span><span lang=EN-US>RichEdit</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">控gQ往往发现对话框却无法正常昄Q这是因为应用程序还没有?/span><span lang=EN-US>RichEdit</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">控g的编辑功能做好准备,解决办法是在应用程序的</span><span lang=EN-US>InitInstance()</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数调用</span><span lang=EN-US>AfxInitRichEdit()</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数初始?/span><span lang=EN-US>RichEdit</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">控g</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto">8. </span></strong><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如何指定对话框的默认按钮</span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; mso-shading: white; mso-pattern: gray-15 auto"></span></strong></p> <p> </p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当徏立一个对话框的时候,在默认条件下Q确定按钮(</span><span lang=EN-US>IDOK</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q是默认按钮Q如果需要改变默认的按钮有两U方法:(x)</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其一</span></strong><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q?/span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">直接在确定按钮(</span><span lang=EN-US>IDOK</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q的属性里L</span><span lang=EN-US>Default button</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">风格的选项</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span style="FONT-SIZE: 12pt; BACKGROUND: #d9d9d9; FONT-FAMILY: 宋体; mso-shading: white; mso-pattern: gray-15 auto; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其二</span></strong><font size=3><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q?/span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在运行的时候用代码实现Q如Q?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US><span style="mso-spacerun: yes">  </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">L定按钮Q?/span><span lang=EN-US>IDOK</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">Q的默认按钮</span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>CButton *pokbutton = (CButton *)GetDlgItem(IDOK);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>Pokbutton->ModifyStyle(BS_DEFPUSHBUTTON,0);</font></span></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=3><span lang=EN-US><span style="mso-spacerun: yes">  </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">d</span><span lang=EN-US>IDCANCEL</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的默认按钮风?/span></font></p> <p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=3>CButton *pcancelbutton = (CButton *)GetDlgItem(IDCANCEL);</font></span></p> <span lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-fareast-font-family: 宋体; mso-bidi-font-size: 12.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">pcancelbutton->SetButtonStyle(BS_DEFPUSHBUTTON);</span><br><br>本文引用通告地址Q?http://blog.csdn.net/laiyiling/services/trackbacks/22294.aspx <p>1. 昄和隐藏标题栏</p> <p>Ҏ(gu)一Q用API实现 </p> <p>//隐藏TitleBar<br>LONG lStyle = ::GetWindowLong(this->m_hWnd, GWL_STYLE);<br>::SetWindowLong(this->m_hWnd, GWL_STYLE, lStyle & ~WS_CAPTION);<br>::SetWindowPos(this->m_hWnd, NULL, 0, 0, 0, 0,<br>SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);</p> <p>// 昄TitleBar<br>::SetWindowLong(this->m_hWnd, GWL_STYLE, lStyle | WS_CAPTION);<br>::SetWindowPos(this->m_hWnd, NULL, 0, 0, 0, 0,??SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);<br>Ҏ(gu)二:(x)使用CWnd成员函数ModifyStyle实现<br>// 隐藏TitleBar<br>ModifyStyle(WS_CAPTION, 0, SWP_FRAMECHANGED);<br>// 昄TitleBar<br>ModifyStyle(0, WS_CAPTION, SWP_FRAMECHANGED);<br></p> <p>2 . 怎么用SendMessage(Q来发送消息来清空它的内容Q? <br>HWND hEditWnd=GetDlgItem(IDC_EDIT1)->GetSafeHwnd();<br>::SendMessage(hEditWnd,WM_SETTEXT,(WPARAM)0,(LPARAM)"");</p> <p>3. 弹出文g的属性窗?br>SHELLEXECUTEINFO ShExecInfo ={0};<br>ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);<br>ShExecInfo.fMask = SEE_MASK_INVOKEIDLIST ;<br>ShExecInfo.hwnd = NULL;<br>ShExecInfo.lpVerb = "properties";<br>ShExecInfo.lpFile = "c:\"; //也可以是文g<br>ShExecInfo.lpParameters = ""; <br>ShExecInfo.lpDirectory = NULL;<br>ShExecInfo.nShow = SW_SHOW;<br>ShExecInfo.hInstApp = NULL; <br>ShellExecuteEx(&ShExecInfo);</p> <p>4. 删除一个目录下的所有文?/p> <p>BOOL DeleteDirectory(LPCTSTR DirName)<br>{<br>  CFileFind tempFind; //声明一个CFileFindcd量,以用来搜?br>  char tempFileFind[200]; //用于定义搜烦格式<br>  sprintf(tempFileFind,"%s\\*.*",DirName);<br>  //匚w格式?.*,卌目录下的所有文?nbsp;<br> <br>  BOOL IsFinded=(BOOL)tempFind.FindFile(tempFileFind);<br>  //查找W一个文?br>   while(IsFinded)<br>  {<br>     IsFinded=(BOOL)tempFind.FindNextFile(); //递归搜烦其他的文?nbsp;<br>    if(!tempFind.IsDots()) //如果不是"."目录<br>{<br> char foundFileName[200];<br> strcpy(foundFileName,tempFind.GetFileName().GetBuffer(200));<br>if(tempFind.IsDirectory()) //如果是目录,则递归地调?br>{ //DeleteDirectory<br> char tempDir[200];<br>sprintf(tempDir,"%s\\%s",DirName,foundFileName);<br>DeleteDirectory(tempDir);<br>}<br>else<br> { //如果是文件则直接删除?br> char tempFileName[200];<br>sprintf(tempFileName,"%s\\%s",DirName,foundFileName);<br>DeleteFile(tempFileName);<br>}<br>}<br>}<br> tempFind.Close();<br>if(!RemoveDirectory(DirName)) //删除目录<br> {<br>AfxMessageBox("删除目录p|Q?,MB_OK);<br> return FALSE;<br> }<br>return TRUE;<br>}</p> <p>5.? lib和dll文g的区别和联系 </p> <p>.dll是在你的E序q行的时候才q接的文Ӟ因此它是一U比较小的可执行文g格式Q?dllq有其他的文件格式如.ocx{,所有的.dll文g都是可执行?/p> <p>.lib是在你的E序~译q接的时候就q接的文Ӟ因此你必d知编译器q接的lib文g在那里。一般来_(d)与动态连接文件相Ҏ(gu)Qlib文g也被UCؓ(f)是静态连接库。当你把代码~译成这几种格式的文件时Q在以后他们׃可能再被更改。如果你想用lib文gQ就必须Q?br>1? 包含一个对应的头文件告知编译器lib文g里面的具体内?br>2? 讄lib文g允许~译器去查找已经~译好的二进制代?/p> <p>如果你想从你的代码分M个dll文g出来代替静态连接库Q仍焉要一个lib文g。这个lib文g被q接到程序告诉操作系l在q行的时候你想用C么dll文gQ一般情况下Qlib文g里有相应的dll文g的名字和一个指明dll输出函数入口的顺序表。如果不想用lib文g或者是没有lib文gQ可以用WIN32 API函数LoadLibrary、GetProcAddress。事实上Q我们可以在Visual C++ IDE中以二进制Ş式打开lib文gQ大多情况下?x)看到ASCII码格式的C++函数或一些重载操作的函数名字?/p> <p>一般我们最主要的关于lib文g的麻烦就是出现unresolved symble q类错误Q这是lib文gq接错误或者没有包?c?cpp文g到工E里Q关键是如果在C++工程里用了C语言写的lib文gQ就必需要这样包含:(x)<br>extern "C"<br>{<br>#include "myheader.h"<br>}<br>q是因ؓ(f)C语言写的lib文g没有C++所必须的名字破坏,C函数不能被重载,因此q接器会(x)出错?/p> </div> <img src ="http://www.shnenglu.com/twzheng/aggbug/20615.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/twzheng/" target="_blank">谭文?/a> 2007-03-26 14:34 <a href="http://www.shnenglu.com/twzheng/articles/20615.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>#pragma 预处理命令详?/title><link>http://www.shnenglu.com/twzheng/articles/20540.html</link><dc:creator>谭文?/dc:creator><author>谭文?/author><pubDate>Sat, 24 Mar 2007 11:49:00 GMT</pubDate><guid>http://www.shnenglu.com/twzheng/articles/20540.html</guid><wfw:comment>http://www.shnenglu.com/twzheng/comments/20540.html</wfw:comment><comments>http://www.shnenglu.com/twzheng/articles/20540.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/twzheng/comments/commentRss/20540.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/twzheng/services/trackbacks/20540.html</trackback:ping><description><![CDATA[<p><font face="Courier New" size=2>#pragma  预处理指令详?br>[源]http://oracle-db2.popo.blog.163.com/blog/static/108510472006112774732311/    <br>     <br> <br>    在所有的预处理指令中Q?pragma 指o(h)可能是最复杂的了Q它的作用是讑֮~译器的状态或者是指示~译器完成一些特定的动作?br>#pragma指o(h)Ҏ(gu)个编译器l出了一个方?在保持与C和C++语言完全兼容的情况下,l出L或操作系l专有的特征?br>依据定义,~译指示是机器或操作pȝ专有?且对于每个编译器都是不同的?nbsp; <br>    其格式一般ؓ(f): #pragma  para  <br>    其中para为参敎ͼ下面来看一些常用的参数?nbsp; <br> </font> </p> <p><font face="Courier New" size=2>(1)message 参数</font> </p> <p><font face="Courier New" size=2>    message参数是我最喜欢的一个参敎ͼ它能够在~译信息输出H口中输出相应的信息Q?br>q对于源代码信息的控制是非常重要的。其使用Ҏ(gu)为:(x)  <br>    #pragma  message("消息文本")  <br>    当编译器遇到q条指o(h)时就在编译输出窗口中消息文本打印出来?nbsp; <br>    当我们在E序中定义了许多宏来控制源代码版本的时候,我们自己有可能都?x)忘记有没有正确的设|这些宏Q?br>此时我们可以用这条指令在~译的时候就q行查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86q个?<br>可以用下面的Ҏ(gu):<br>    #ifdef  _X86  <br>    #pragma  message("_X86  macro  activated!")  <br>    #endif  <br>    我们定义了_X86q个宏以后,应用E序在编译时׃(x)在编译输出窗口里昄"_86  macro  activated!"?br>我们׃?x)因Z记得自己定义的一些特定的宏而抓x腮了?nbsp; <br>       </font></p> <p><font face="Courier New" size=2>(2)另一个用得比较多的pragma参数是code_seg</font> </p> <p><font face="Courier New" size=2>    格式如:(x)  <br>    #pragma  code_seg( ["section-name" [, "section-class"] ] )  <br>    它能够设|程序中函数代码存放的代码段Q当我们开发驱动程序的时候就?x)用到它?nbsp; <br> </font> </p> <p><font face="Courier New" size=2>(3)#pragma once  (比较常用)  </font></p> <p><font face="Courier New" size=2>    只要在头文g的最开始加入这条指令就能够保证头文件被~译一ơ,q条指o(h)实际上在VC6中就已经有了Q?br>但是考虑到兼Ҏ(gu)ƈ没有太多的用它?nbsp; </font></p> <p><font face="Courier New" size=2>       <br>(4)#pragma  hdrstop</font> </p> <p><font face="Courier New" size=2>    表示预编译头文g到此为止Q后面的头文件不q行预编译。BCB可以预编译头文g以加快链接的速度Q?br>但如果所有头文g都进行预~译又可能占太多盘I间Q所以用这个选项排除一些头文g?nbsp;   <br>    有时单元之间有依赖关p,比如单元A依赖单元BQ所以单元B要先于单元A~译?br>你可以用#pragma  startup指定~译优先U,如果使用?pragma  package(smart_init)Q?br>BCB׃(x)Ҏ(gu)优先U的大小先后~译?nbsp;   </font></p> <p><font face="Courier New" size=2>       <br>(5)#pragma  resource  "*.dfm"</font> </p> <p><font face="Courier New" size=2>    表示?.dfm文g中的资源加入工程?.dfm中包括窗?nbsp; <br>外观的定义?nbsp;   </font></p> <p><font face="Courier New" size=2>         <br>(6)#pragma  warning( disable: 4507 34; once: 4385; error: 164 )<br>  <br>    {h(hun)于:(x)  <br>    #pragma  warning( disable: 4507 34 )    //  不显C?507?4可告信?nbsp; <br>    #pragma  warning( once: 4385 )          //  4385可告信息仅报告一?nbsp; <br>    #pragma  warning( error: 164 )          //  ?64可告信息作Z个错误?nbsp; </font></p> <p><font face="Courier New" size=2>    同时q个pragma  warning  也支持如下格式:(x)  <br>    #pragma  warning( push [, n ] )  <br>    #pragma  warning( pop )  <br>    q里n代表一个警告等U?1---4)?nbsp; <br>    #pragma  warning( push )保存所有警告信息的现有的警告状态?nbsp; <br>    #pragma  warning( push, n )保存所有警告信息的现有的警告状态,q且把全局警告{讑֮为n?nbsp;   <br>    #pragma  warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的一切改动取消。例如:(x)  <br>    #pragma  warning( push )  <br>    #pragma  warning( disable: 4705 )  <br>    #pragma  warning( disable: 4706 )  <br>    #pragma  warning( disable: 4707 )  <br>    //.......  <br>    #pragma  warning(  pop  )    <br>    在这D代码的最后,重新保存所有的警告信息(包括4705Q?706?707)?nbsp; </font></p> <p><br><font face="Courier New" size=2>(7)#pragma  comment(...)  </font></p> <p><font face="Courier New" size=2>    该指令将一个注释记录放入一个对象文件或可执行文件中?nbsp; <br>常用的lib关键字,可以帮我们连入一个库文g。如Q?br>    #pragma  comment(lib, "comctl32.lib")<br>    #pragma  comment(lib, "vfw32.lib")<br>    #pragma  comment(lib, "wsock32.lib")<br> <br>   <br>   <br>每个~译E序可以?pragma指o(h)ȀzLl止该编译程序支持的一些编译功能?/font> </p> <p><font face="Courier New" size=2>例如Q对循环优化功能Q?nbsp; <br>#pragma  loop_opt(on)     //  Ȁz?nbsp; <br>#pragma  loop_opt(off)    //  l止  </font></p> <p><font face="Courier New" size=2>有时Q程序中?x)有些函C(x)使编译器发出你熟知而想忽略的警告,<br>?#8220;Parameter  xxx  is  never  used  in  function  xxx”Q可以这P(x)  <br>#pragma  warn  ?00         //  Turn  off  the  warning  message  for  warning  #100  <br>int  insert_record(REC  *r)  <br>{  /*  function  body  */  }  <br>#pragma  warn  +100          //  Turn  the  warning  message  for  warning  #100  back  on  <br>函数?x)生一条有唯一特征?00的警告信息,如此可暂时终止该警告?nbsp; </font></p> <p><font face="Courier New" size=2>每个~译器对#pragma的实C同,在一个编译器中有效在别的~译器中几乎无效。可从编译器的文档中查看?/font> </p> <p><font face="Courier New" size=2></font></p> <p><font face="Courier New" size=2>补充 —?#pragma pack ?内存寚w问题</font> </p> <p><br><font face="Courier New" size=2>    许多实际的计机pȝ对基本类型数据在内存中存攄位置有限Ӟ它们?x)要求这些数据的首地址的值是某个数k<br>(通常它ؓ(f)4?)的倍数Q这是所谓的内存寚wQ而这个k则被UCؓ(f)该数据类型的寚w模数(alignment modulus)?/font> </p> <p><font face="Courier New" size=2>    Win32q_下的微YC~译?cl.exe for 80x86)在默认情况下采用如下的对齐规? <br>    M基本数据cdT的对齐模数就是T的大,即sizeof(T)。比如对于doublecd(8字节)Q?br>p求该cd数据的地址L8的倍数Q而charcd数据(1字节)则可以从M一个地址开始?/font> </p> <p><font face="Courier New" size=2>    Linux下的GCC奉行的是另外一套规?在资料中查得Qƈ未验证,如错误请指正):<br>    M2字节大小(包括单字节吗?)的数据类?比如short)的对齐模数是2Q而其它所有超q?字节的数据类?br>(比如long,double)都以4为对齐模数?/font> </p> <p><font face="Courier New" size=2>    ANSI C规定一U结构类型的大小是它所有字D늚大小以及(qing)字段之间或字D尾部的填充区大之和?br>填充区就是ؓ(f)了ɾl构体字D|_存对齐要求而额外分配给l构体的I间。那么结构体本n有什么对齐要求吗Q?br>有的QANSI C标准规定l构体类型的寚w要求不能比它所有字D中要求最严格的那个宽松,可以更严根{?/font> </p> <p><br><font face="Courier New" size=2>如何使用c/c++中的寚w选项</font> </p> <p><font face="Courier New" size=2>    vc6中的~译选项?/Zp[1|2|4|8|16] Q?Zp1表示?字节边界寚wQ相应的Q?Zpn表示以n字节边界寚w?br>n字节边界寚w的意思是_(d)一个成员的地址必须安排在成员的寸的整数倍地址上或者是n的整数倍地址上,取它们中的最倹{?br>也就是:(x)<br>    min ( sizeof ( member ),  n)</font> </p> <p><font face="Courier New" size=2>    实际上,1字节边界寚w也就表示了结构成员之间没有空z?br>    /Zpn选项是应用于整个工程的,影响所有的参与~译的结构?br>    要用这个选项Q可以在vc6中打开工程属性页Qc/c++,选择Code Generation分类Q在Struct member alignment可以选择?/font> </p> <p><font face="Courier New" size=2>    要专门针Ҏ(gu)些结构定义用对齐选项Q可以?pragma pack~译指o(h):</font> </p> <p><br><font face="Courier New" size=2>(1) #pragma  pack( [ n ] )</font> </p> <p><font face="Courier New" size=2>    该指令指定结构和联合成员的紧凑对齐。而一个完整的转换单元的结构和联合的紧凑对齐由/Zp 选项讄?br>紧凑寚w用pack~译指示在数据说明层讄。该~译指示在其出现后的W一个结构或联合说明处生效?br>该编译指C对定义无效?br>    当你使用#pragma  pack ( n ) ? q里n ???? ?6?br>    W一个结构成员之后的每个l构成员都被存储在更的成员cd或n 字节界限内?br>如果你用无参量?pragma  pack, l构成员被紧凑ؓ(f)?Zp 指定的倹{该~省/Zp 紧凑gؓ(f)/Zp8 ?/font> </p> <p><br><font face="Courier New" size=2>(2) ~译器也支持以下增强型语?<br>    #pragma  pack( [ [ { push | pop } , ] [ identifier, ] ] [ n] )</font> </p> <p><font face="Courier New" size=2>    若不同的lg使用pack~译指示指定不同的紧凑对? q个语法允许你把E序lgl合Z个单独的转换单元?br>带push参量的pack~译指示的每ơ出现将当前的紧凑对齐存储到一个内部编译器堆栈中?br>    ~译指示的参量表从左到右d。如果你使用push, 则当前紧凑D存储h; <br>如果你给Z个n 的? 该值将成ؓ(f)新的紧凑倹{若你指定一个标识符, 即你选定一个名U? <br>则该标识W将和这个新的的紧凑Dpv来?/font> </p> <p><font face="Courier New" size=2>    带一个pop参量的pack~译指示的每ơ出现都?x)检索内部编译器堆栈的?q且使该gؓ(f)新的紧凑寚w倹{?br>如果你用pop参量且内部编译器堆栈是空?则紧凑gؓ(f)命o(h)行给定的? q且生一个警告信息?br>若你使用pop且指定一个n的? 该值将成ؓ(f)新的紧凑倹{若你用p o p 且指定一个标识符, <br>所有存储在堆栈中的值将从栈中删? 直到扑ֈ一个匹配的标识W? q个与标识符相关的紧凑g从栈中移? <br>q且q个仅在标识W入栈之前存在的紧凑值成为新的紧凑倹{如果未扑ֈ匚w的标识符, <br>用命令行讄的紧凑? q且生一个一U警告。缺省紧凑对齐ؓ(f)8 ?/font> </p> <p><font face="Courier New" size=2>   pack~译指示的新的增强功能让你编写头文g, 保在遇到该头文件的前后?br>紧凑值是一L(fng)?/font> </p> <p><br><font face="Courier New" size=2>(3) 栈内存对?/font> </p> <p><font face="Courier New" size=2>    在vc6中栈的对齐方式不受结构成员对齐选项的媄响。它L保持寚wQ而且寚w?字节边界上?/font> </p> <img src ="http://www.shnenglu.com/twzheng/aggbug/20540.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/twzheng/" target="_blank">谭文?/a> 2007-03-24 19:49 <a href="http://www.shnenglu.com/twzheng/articles/20540.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.fanerge.cn" target="_blank">Ʒľþþþþþ </a>| <a href="http://www.z9432.cn" target="_blank">ɫɫۺϾþҹҹ</a>| <a href="http://www.dgtspcb.com.cn" target="_blank">ѾƷþ</a>| <a href="http://www.nmbm.com.cn" target="_blank">þþƷ˹ҹ</a>| <a href="http://www.kt813.cn" target="_blank">ŷһþþƷ</a>| <a href="http://www.msomso.cn" target="_blank">Ʒһþ</a>| <a href="http://www.4gbbs.cn" target="_blank">ѾƷպȾþ</a>| <a href="http://www.xfb55.cn" target="_blank">91ƷɫۺϾþ</a>| <a href="http://www.szsantong.com.cn" target="_blank">Ʒþþþþ벻</a>| <a href="http://www.jiqirenedu.cn" target="_blank">91Ʒþþþþù۲ </a>| <a href="http://www.aigoou.cn" target="_blank">þ޾Ʒ˳ۺ</a>| <a href="http://www.lihengzhe.cn" target="_blank">þþþþ޾Ʒ</a>| <a href="http://www.yyyart.cn" target="_blank">Ʒþþþ9999</a>| <a href="http://www.o7xcp.cn" target="_blank">޹Ʒþ</a>| <a href="http://www.jihejingjia.cn" target="_blank">þһŷպ</a>| <a href="http://www.rcipbrdgydr.cn" target="_blank">þó˹Ʒ</a>| <a href="http://www.hjzz.net.cn" target="_blank">vavavaþ</a>| <a href="http://www.shequjingying.cn" target="_blank">պŷۺϾþӰԺDs </a>| <a href="http://www.rojie.cn" target="_blank">һձ˾þۺӰ</a>| <a href="http://www.ppmov.cn" target="_blank">ձþþþƷĻ</a>| <a href="http://www.pf925.cn" target="_blank">þþžžƷ99Ʒ</a>| <a href="http://www.baodecai.cn" target="_blank">þ°Ҳȥ</a>| <a href="http://www.qxmsv.cn" target="_blank">þù޾ƷӰԺ</a>| <a href="http://www.chaohu8.cn" target="_blank">þþþۺþ</a>| <a href="http://www.sdxingying.com.cn" target="_blank">þþþ99ƷƬֱ</a>| <a href="http://www.acmpm.cn" target="_blank">㽶þۺӰ </a>| <a href="http://www.338z.cn" target="_blank">þþžѾƷ6</a>| <a href="http://www.huizegufen.cn" target="_blank">þ޵Ӱ</a>| <a href="http://www.tsz114.cn" target="_blank">þþwww˳</a>| <a href="http://www.dqezb.cn" target="_blank">þþƷĻ</a>| <a href="http://www.hzyzhongyuan.cn" target="_blank">99þۺϺݺۺϾþ</a>| <a href="http://www.fx40.cn" target="_blank">Ʒ99þþþþwww</a>| <a href="http://www.qwqsd.cn" target="_blank">AAƬѿƵþ</a>| <a href="http://www.girlsp.cn" target="_blank">ƷþþӰ㽶</a>| <a href="http://www.madouwang.cn" target="_blank">þþƷһ</a>| <a href="http://www.zzc40.cn" target="_blank">þùƷ-þþƷ</a>| <a href="http://www.v1175.cn" target="_blank">þþƷƷapp</a>| <a href="http://www.disidai.cn" target="_blank">99ھƷþþþþþ</a>| <a href="http://www.117shop.cn" target="_blank">99þùһ</a>| <a href="http://www.youxi011.cn" target="_blank">ѾþþƷ99þ</a>| <a href="http://www.js157.cn" target="_blank">þþWWW˳ɾƷ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>