﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-我风</title><link>http://www.cppblog.com/kyelin/</link><description>收集,记录,整理,回收</description><language>zh-cn</language><lastBuildDate>Sat, 18 Apr 2026 19:11:28 GMT</lastBuildDate><pubDate>Sat, 18 Apr 2026 19:11:28 GMT</pubDate><ttl>60</ttl><item><title>sqlite备忘</title><link>http://www.cppblog.com/kyelin/archive/2011/06/10/148434.html</link><dc:creator>我风</dc:creator><author>我风</author><pubDate>Fri, 10 Jun 2011 08:08:00 GMT</pubDate><guid>http://www.cppblog.com/kyelin/archive/2011/06/10/148434.html</guid><wfw:comment>http://www.cppblog.com/kyelin/comments/148434.html</wfw:comment><comments>http://www.cppblog.com/kyelin/archive/2011/06/10/148434.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kyelin/comments/commentRss/148434.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kyelin/services/trackbacks/148434.html</trackback:ping><description><![CDATA[<p>int sqlite3_open(<br />&nbsp; const char *filename,&nbsp;&nbsp; /* Database filename (UTF-8) */<br />&nbsp; sqlite3 **ppDb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* OUT: SQLite db handle */<br />);<br />功能:打开数据库,如果不存在则自动创建.<br />PARAM1(IN):&nbsp;数据库文件名,UTF-8格式<br />PARAM2(OUT):&nbsp;&nbsp;返回的数据库句柄<br />返回值:返回SQLITE_OK成功,反之失败(数据库句柄ppDb为空),失败值见具体SQLITE_*定义.<br />=====================================================================================</p>
<p>int sqlite3_close(sqlite3 *);<br />功能:关闭数据库<br />PARAM1(IN):打开的数据库句柄<br />返回值:返回SQLITE_OK成功,反之失败.<br />=====================================================================================</p>
<p>int sqlite3_exec(<br />&nbsp; sqlite3*,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* An open database */<br />&nbsp; const char *sql,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* SQL to be executed */<br />&nbsp; sqlite3_callback,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Callback function */<br />&nbsp; void *,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 1st argument to callback function */<br />&nbsp; char **errmsg&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Error msg written here */<br />);<br />功能:执行SQL<br />PARAM1(IN):数据库句柄<br />PARAM2(IN):sql语句,以\0结尾.<br />PARAM3(IN):回调函数<br />PARAM4(IN):回调参数<br />PARAM5(OUT):输出错误信息<br />返回值:SQLITE_OK成功,反之失败,失败后错误信息见PARAM5;<br />说明：如果有多条SQL语句,中间用分号(;)隔开.回调函数和回调参数通常在查询语句会用到,<br />对每条查询结果结果都会调用回调函数一次.<br />回调函数格式:<br />typedef int(*sqlite3_callback)(void *,int ,char **,char **);<br />参数1:sqlite3_exec中传入的参数<br />参数2:总列数.<br />参数3:列数据(char*)<br />参数4:列名称(char*)</p>
<p>=====================================================================================<br />int sqlite3_get_table(<br />&nbsp; sqlite3*,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* An open database */<br />&nbsp; const char *sql,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* SQL to be executed */<br />&nbsp; char ***resultp,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Result written to a char *[]&nbsp; that this points to */<br />&nbsp; int *nrow,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Number of result rows written here */<br />&nbsp; int *ncolumn,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Number of result columns written here */<br />&nbsp; char **errmsg&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Error msg written here */<br />);<br />功能:查询表<br />PARAM1(IN):数据库句柄<br />PARAM2(IN):sql语句,以\0结尾.<br />PARAM3(OUT):查询结果<br />PARAM4(OUT):返回行数(多少条数据)<br />PARAM5(OUT):返回列数(多少字段)<br />PARAM6(OUT):返回错误信息<br />返回值:SQLITE_OK成功,房子失败见错误信息</p>
<p>=====================================================================================<br />void sqlite3_free_table(char **result);<br />功能:释放通过sqlite3_get_table查询保存的结果数据<br />PARAM1(IN):要释放的数据指针</p>
<p><br />=====================================================================================<br />int sqlite3_prepare(<br />&nbsp; sqlite3 *db,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Database handle */<br />&nbsp; const char *zSql,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* SQL statement, UTF-8 encoded */<br />&nbsp; int nBytes,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Length of zSql in bytes. */<br />&nbsp; sqlite3_stmt **ppStmt,&nbsp; /* OUT: Statement handle */<br />&nbsp; const char **pzTail&nbsp;&nbsp;&nbsp;&nbsp; /* OUT: Pointer to unused portion of zSql */<br />);<br />功能:构造查询<br />PARAM1(IN):数据库句柄<br />PARAM2(IN):sql语句<br />PARAM3(IN):sql语句长度,设置成-1则自动按字符串计算sql语句长度<br />PARAM4(OUT):保存的查询结构体,<br />PARAM5(OUT):NULL即可<br />返回值:SQLITE_OK成功.</p>
<p><br />=====================================================================================<br />int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));<br />功能:为查询结构体绑定数据<br />PARAM1(IN):查询结构体<br />PARAM2(IN):绑定第几个数据(sql语句中的第几个问号(?))<br />PARAM3(IN):二进制数据指针<br />PARAM4(IN):二进制数据长度<br />PARAM5(IN):析构回调函数,通常设置NULL,结束后自己释放<br />返回值:S_OK成功.<br />说明:绑定函数必须要在sqlite3_step前,sqlite3_prepare或者sqlite3_reset之后调用.<br />未绑定的参数缺省为NULL,类似的绑定函数还有以下<br />int sqlite3_bind_double(sqlite3_stmt*, int, double);<br />int sqlite3_bind_int(sqlite3_stmt*, int, int);<br />int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite_int64);<br />int sqlite3_bind_null(sqlite3_stmt*, int);<br />int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));<br />int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));<br />int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);</p>
<p>&nbsp;</p>
<p>=====================================================================================<br />int sqlite3_reset(sqlite3_stmt *pStmt);<br />功能:重置所有绑定的值,回到刚刚调用sqlite3_prepare后的状态</p>
<p><br />=====================================================================================<br />int sqlite3_step(sqlite3_stmt*);<br />功能:执行查询<br />PARAM1:查询结构体<br />返回值:<br />SQLITE_BUSY:数据库被锁,可以等待释放后重新调用该函数<br />SQLITE_DONE:成功<br />SQLITE_ROW:成功并且有数据返回,对每查询到一条数据都会返回该值,<br />&nbsp;&nbsp;&nbsp;可以调用sqlite3_column_*函数获取数据后重新调用处理下一条数据<br />SQLITE_ERROR:失败<br />SQLITE_MISUSE:错误的调用,比如已经返回了SQLITE_DONE或者SQLITE_ERROR后还继续调用该函数</p>
<p><br />=====================================================================================<br />int sqlite3_finalize(sqlite3_stmt *pStmt);<br />功能:释放查询结构体</p>
<p>=====================================================================================<br />int sqlite3_key(<br />&nbsp; sqlite3 *db,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Database to be rekeyed */<br />&nbsp; const void *pKey, int nKey&nbsp;&nbsp;&nbsp;&nbsp; /* The key */<br />);<br />功能:为加密的数据库指定密码,改函数在sqlite3_open之后调用</p>
<p>=====================================================================================<br />int sqlite3_rekey(<br />&nbsp; sqlite3 *db,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Database to be rekeyed */<br />&nbsp; const void *pKey, int nKey&nbsp;&nbsp;&nbsp;&nbsp; /* The new key */<br />);<br />功能:重设数据库密码,如果pKey = 0 或者 nKey = 0,这数据库不加密</p>
<p><br />=====================================================================================</p>
<p>&nbsp;</p>
<p><br />const char *sqlite3_libversion(void);<br />int sqlite3_libversion_number(void);<br />功能:获取版本号</p>
<p>sqlite_int64 sqlite3_last_insert_rowid(sqlite3*);<br />功能:获取最后插入的行标示.</p>
<p>int sqlite3_changes(sqlite3*);<br />功能:获取最近执行的sqlite3_exec影响的行数.</p>
<p>int sqlite3_total_changes(sqlite3*);<br />功能:获取自从数据库打开后有改动的函数</p>
<p>void sqlite3_interrupt(sqlite3*);<br />功能:打断或停止数据库当前操作.</p>
<p>int sqlite3_complete(const char *sql);<br />功能:判断语句是否以分号(;)结尾</p>
<p>int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);<br />功能:设置查询忙碌时的回调处理<br />说明:缺省的回调函数为空,如果回调函数为空,表锁定后sqlite3_exec()执行会直接返回SQLITE_BUSY</p>
<p>int sqlite3_busy_timeout(sqlite3*, int ms);<br />功能:设置查询超时时间(毫秒)</p>
<p>&nbsp;</p>
<p>char *sqlite3_mprintf(const char*,...);<br />char *sqlite3_vmprintf(const char*, va_list);<br />char *sqlite3_snprintf(int,char*,const char*, ...);<br />功能:格式化字符,需要用%q来代替%s.(主要是不用对分号'进行转义)</p>
<p><br />void *sqlite3_malloc(int);<br />void *sqlite3_realloc(void*, int);<br />void sqlite3_free(void*);<br />功能:内存函数</p>
<p>int sqlite3_set_authorizer(<br />&nbsp; sqlite3*,<br />&nbsp; int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),<br />&nbsp; void *pUserData<br />);<br />功能:设置数据库授权</p>
<p>void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);<br />void *sqlite3_profile(sqlite3*,<br />&nbsp;&nbsp; void(*xProfile)(void*,const char*,sqlite_uint64), void*);</p>
<p>void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);<br />功能:设置执行回调函数,sqlite3_exec(),sqlite3_step() ,sqlite3_get_table()时会调用</p>
<p>void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);<br />功能:设置事务回调函数</p>
<p>int sqlite3_errcode(sqlite3 *db);<br />const char *sqlite3_errmsg(sqlite3*);<br />功能:获取错误码和错误消息</p>
<p>int sqlite3_bind_parameter_count(sqlite3_stmt*);<br />功能:返回需要绑定的参数数目(sql语句中问号?数量)</p>
<p>const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);<br />功能:获取绑定参数名字,?参数返回NULL</p>
<p>int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);<br />功能:获取绑定参数索引</p>
<p>int sqlite3_clear_bindings(sqlite3_stmt*);<br />功能:清除绑定的参数</p>
<p><br />int sqlite3_column_count(sqlite3_stmt *pStmt);<br />功能:获取列数<br />const char *sqlite3_column_name(sqlite3_stmt*,int);<br />功能:获取列名</p>
<p><br />const char *sqlite3_column_database_name(sqlite3_stmt*,int);<br />const void *sqlite3_column_database_name16(sqlite3_stmt*,int);<br />const char *sqlite3_column_table_name(sqlite3_stmt*,int);<br />const void *sqlite3_column_table_name16(sqlite3_stmt*,int);<br />const char *sqlite3_column_origin_name(sqlite3_stmt*,int);<br />const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);<br />功能:返回列信息?</p>
<p>const char *sqlite3_column_decltype(sqlite3_stmt *, int i);<br />功能:返回列数据类型</p>
<p>int sqlite3_data_count(sqlite3_stmt *pStmt);<br />功能:返回数据数量(行数)</p>
<p>&nbsp;</p>
<p>const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);<br />int sqlite3_column_bytes(sqlite3_stmt*, int iCol);<br />int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);<br />double sqlite3_column_double(sqlite3_stmt*, int iCol);<br />int sqlite3_column_int(sqlite3_stmt*, int iCol);<br />sqlite_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);<br />const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);<br />const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);<br />int sqlite3_column_type(sqlite3_stmt*, int iCol);<br />int sqlite3_column_numeric_type(sqlite3_stmt*, int iCol);<br />sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);<br />功能:获取列数据</p>
<p><br />int sqlite3_create_function(<br />&nbsp; sqlite3 *,<br />&nbsp; const char *zFunctionName,<br />&nbsp; int nArg,<br />&nbsp; int eTextRep,<br />&nbsp; void*,<br />&nbsp; void (*xFunc)(sqlite3_context*,int,sqlite3_value**),<br />&nbsp; void (*xStep)(sqlite3_context*,int,sqlite3_value**),<br />&nbsp; void (*xFinal)(sqlite3_context*)<br />);<br />功能:</p>
<p>const void *sqlite3_value_blob(sqlite3_value*);<br />int sqlite3_value_bytes(sqlite3_value*);<br />int sqlite3_value_bytes16(sqlite3_value*);<br />double sqlite3_value_double(sqlite3_value*);<br />int sqlite3_value_int(sqlite3_value*);<br />sqlite_int64 sqlite3_value_int64(sqlite3_value*);<br />const unsigned char *sqlite3_value_text(sqlite3_value*);<br />const void *sqlite3_value_text16(sqlite3_value*);<br />const void *sqlite3_value_text16le(sqlite3_value*);<br />const void *sqlite3_value_text16be(sqlite3_value*);<br />int sqlite3_value_type(sqlite3_value*);<br />int sqlite3_value_numeric_type(sqlite3_value*);<br />功能:类似sqlite3_column_*函数</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p><img src ="http://www.cppblog.com/kyelin/aggbug/148434.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kyelin/" target="_blank">我风</a> 2011-06-10 16:08 <a href="http://www.cppblog.com/kyelin/archive/2011/06/10/148434.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>chtmlview的疑惑</title><link>http://www.cppblog.com/kyelin/archive/2011/04/20/144694.html</link><dc:creator>我风</dc:creator><author>我风</author><pubDate>Wed, 20 Apr 2011 12:08:00 GMT</pubDate><guid>http://www.cppblog.com/kyelin/archive/2011/04/20/144694.html</guid><wfw:comment>http://www.cppblog.com/kyelin/comments/144694.html</wfw:comment><comments>http://www.cppblog.com/kyelin/archive/2011/04/20/144694.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kyelin/comments/commentRss/144694.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kyelin/services/trackbacks/144694.html</trackback:ping><description><![CDATA[一个对话框项目中需要显示网页,遂创建chtmlview对象后加载网页,本机win7测试ok,然而到放到xp裸机上测试,直接报错.创建chtmlview窗口失败.而后测试发现如果cchtmlview是在主对话框窗口上的则又没问题,只有在子对话框上创建chtmlview则裸机上报错.原因???
<img src ="http://www.cppblog.com/kyelin/aggbug/144694.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kyelin/" target="_blank">我风</a> 2011-04-20 20:08 <a href="http://www.cppblog.com/kyelin/archive/2011/04/20/144694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 经典开源代码(转)</title><link>http://www.cppblog.com/kyelin/archive/2011/03/24/142660.html</link><dc:creator>我风</dc:creator><author>我风</author><pubDate>Thu, 24 Mar 2011 09:22:00 GMT</pubDate><guid>http://www.cppblog.com/kyelin/archive/2011/03/24/142660.html</guid><wfw:comment>http://www.cppblog.com/kyelin/comments/142660.html</wfw:comment><comments>http://www.cppblog.com/kyelin/archive/2011/03/24/142660.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kyelin/comments/commentRss/142660.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kyelin/services/trackbacks/142660.html</trackback:ping><description><![CDATA[在如下的库支持下，开发的系统可以很方便移植到当前大部分平台上运行
而无需改动，只需在对应的平台下 用你喜欢的编译器 重新编译即可 
经典的C++库
   STLport-------SGI STL库的跨平台可移植版本，在以前有些编译器离符合
         标准比较远的情况下 那时还是有用的，当然目前vc71已经比较接近标准了，
         故目前不怎么用它了。
   Boost---------准标准库， 功能强大 涉及能想的到的大部分非特别领域的算法，
         有一个大的C++社区支持
   WxWindows-----功能强大的跨平台GUI库  ，它的功能和结构都类似 MFC，故原则上
      可以通过WxWindows把现有MFC程序移植到非Win平台下
   Blitz---------高效率的数值计算函数库 ,你可以订制补充你需要的算法
   Log4cpp-------日志处理  ，功能类似java中的log4j
   ACE-----------自适应通讯环境， 重量级的通讯环境库。
   Crypto++ -----加/解密算法库, 非常专业的C++ 密码学函式库
   CppUnit  ---  一个c++的单元测试框架  类似 java  的JUnit 
   Loki -------  一个实验性质的库，尝试把类似设计模式这样思想层面的东西通过
        库来提供,他是C++的一个模板库,系C++"贵族"， 它把C++模板的功能发挥到了极致

学术性的C++库: 
   FC++ --------The Functional C++ Library  ,用库来扩充语言的一个代表作 ,模板库
   CGAL ------- Computational Geometry Algorithms Library计算几何方面的大部分重要的
     解决方案和方法以C++库的形式提供给工业和学术界的用户。


其它目前我感觉还不是很爽的C++库：  
   Doxygen  ----注释文档生成工具 ,可恨的是 我找不到 windows版本
   QT ----------大名顶顶的一个多平台的C++图形用户界面应用程序框架（GUI库）
          可气的是他的 Windows版 是商业发布的要付费
   xml4c--------IBM开发的XML Parser，系超重量级的， 适用大型应用中， 其DLL有 12M，恐怖吧
   Xerces c++ --Apache的XML项目， 但 只支持少数的字符编码，如ASCII，UTF-8，UTF-16等，
           不能处理包含中文字符的XML文档
   XMLBooster -----  也是一种  XML的 解析工具
   Fox   -------又一种开放源代码（C++）的GUI库，功能不是很强


C++开发环境(Win平台下除了 Visual C++ 和 Borland C++以外的)：
   Cygwin  --------Windows下的一个Unix仿真环境
   MinGW   --------GCC的一个Windows移植版本
   Dev C++ -------- 一个C/C++ 的集成开发环境，在Windows上的C++编译器一直和标准有着一
        段距离的时候，GCC就是一个让Windows下开发者流口水的编译器。
   Eclipse-CDT  ----IMB 开发的一个集成开发环境，一般用来作为Java 开发环境，但由于
         Eclipse 是通过插件体系来扩展功能，这里我们 安装 CDT插件后，就可以用来作为
         C++ 的集成开发环境


-----------------------------------------------------------------------------------------
经典的C++库
-----------------------------------------------------------------------------------------
以下以 vc71环境 为例，其他环境 见各软件包的说明文档。

1.  STLport (SGI STL库的跨平台可移植版本。) 
    -------http://www.stlport.org


vc71环境中编译安装
 版本：STLport-4.6.2.tar.gz
 copy vc71.mak makefile
 nmake clean all

头文件在 %STLport_root%/include\stlport
库文件在 %STLport_root%/lib

头文件添加方法如：
＃i nclude   需要链接lib库



2  WxWindows  (跨平台的GUI库)
       --------http://www.wxwindows.org
       --------http://sourceforge.net/projects/wxwindows
       --------http://i18n.linux.net.cn/others/wxWindowstut/wxTutorial.html

  因为其类层次极像MFC，所以有文章介绍从MFC到WxWindows的代码移植以实现跨平台的功能。
通过多年的开发也是一个日趋完善的GUI库，支持同样不弱于前面两个库。并且是完全开放源代码的。新近
的C++ Builder X的GUI设计器就是基于这个库的。


vc71环境中编译安装
  版本：wxMSW-2.6.0-Setup.exe
  copy makefile.vc makefile
  通过 配置 config.vc 的 SHARED = 0 和 BUILD = debug
  确定 nmake clean all 的四种编译结果：

include头文件： include\wx
Lib库文件:  lib\vc_dll  和 lib\vc_lib
DLL: lib\vc_dll 

头文件在 %wxWidgets_root%/include\wx
库文件在 %wxWidgets_root%/lib\vc_dll  和 %wxWidgets_root%/lib\vc_lib

头文件添加方法如：
＃i nclude   需要链接lib库


3   boost  (“准”标准库)
   ------http://www.boost.org/
   ------http://sourceforge.net/projects/boost/

    Boost库是一个经过千锤百炼、可移植、提供源代码的C++库，作为标准库的后备，是C++标准化进程
的发动机之一。 Boost库由C++标准委员会库工作组成员发起，在C++社区中影响甚大，其成员已近2000人
。 Boost库为我们带来了最新、最酷、最实用的技术，是不折不扣的“准”标准库。

vc71环境中编译安装
  版本：boost_1_32_0.exe

首先进入 tools\build\jam_src 运行 build.bat  得到一个工具： bjam.exe
将其复制到 boost_root 目录下
执行 bjam "-sTOOLS=vc-7_1" stage 开始编译  （bjam "-sTOOLS=vc-7_1" install）


头文件在 %boost_root%/boost
库文件在 %boost_root%/stage\lib 

头文件添加方法如：
＃i nclude   有时要链接lib库


Boost中比较有名气的有这么几个库：
Regex
正则表达式库
Spirit
LL parser framework，用C++代码直接表达EBNF
Graph
图组件和算法
Lambda
在调用的地方定义短小匿名的函数对象，很实用的functional功能
concept check
检查泛型编程中的concept
Mpl
用模板实现的元编程框架
Thread
可移植的C++多线程库
Python
把C++类和函数映射到Python之中
Pool
内存池管理
smart_ptr
    5个智能指针，学习智能指针必读，一份不错的参考是来自CUJ的文章：
Smart Pointers in Boost,哦，这篇文章可以查到，CUJ是提供在线浏览的。

    Boost总体来说是实用价值很高，质量很高的库。并且由于其对跨平台的强调，对标准C++的
强调，是编写平台无关，现代C++的开发者必备的工具。但是Boost中也有很多是实验性质的东西，
在实际的开发中实用需要谨慎。并且很多Boost中的库功能堪称对语言功能的扩展，其构造用尽精
巧的手法，不要贸然的花费时间研读。Boost另外一面，比如Graph这样的库则是具有工业强度，
结构良好，非常值得研读的精品代码，并且也可以放心的在产品代码中多多利用。


3   blitz  (高效率的数值计算函数库) 
   ------http://folk.uio.no/patricg/blitz/html/index.html
   ------http://www.oonumerics.org/blitz/
   ------http://sourceforge.net/projects/blitz/

Blitz++ 是一个高效率的数值计算函数库，它的设计目的是希望建立一套既具像C++ 一样方便，同时
又比Fortran速度更快的数值计算环境。通常，用C++所写出的数值程序，比 Fortran慢20%左右，因
此Blitz++正是要改掉这个缺点。方法是利用C++的template技术，程序执行甚至可以比Fortran更快。
Blitz++目前仍在发展中，对于常见的SVD，FFTs，QMRES等常见的线性代数方法并不提供，不过使用
者可以很容易地利用Blitz++所提供的函数来构建。

vc71环境中编译安装
  版本：blitz-0.8.tar.gz

将 blitz-0.8/Blitz-VS.NET.zip 解压到当前目录下
打开 Blitz-Library.sln  编译即可

头文件在 %blitz_root%/blitz
         %blitz_root%/random
库文件在 %blitz_root%/lib    （静态库）

头文件添加方法如：
＃i nclude   有时要链接lib库
＃i nclude   不需要lib库



4   log4cpp   (日志处理)
    -------http://sourceforge.net/projects/log4cpp/
    -------http://log4cpp.hora-obscura.de/index.php/Main_Page


   Log4cpp 是 Log4J 的 C++ 移植版本，开放源代码并且完全免费。与 Log4J 能够跨平台一样，Log4cpp 
也致力于写出跨平台的 C++ 程序。Log4cpp 主要是用于 C++ 程序中写 log 文件，与此同时，Log4cpp 中
有很多有用的类库，对于写跨平台 C++ 程序的人来说，可以直接拿来用，或者作为自己写跨平台类的参考。
   Log4cpp 中的跨平台类库有明显的 Java 痕迹，比如 Class、Object 、Loader、Locale 等类。 Log4cpp
中的类都可以根据类名 new 出一个 instance，其实现的方式和 MFC 如出一辙：通过 C++ 强大的宏来实现。
   Log4cpp 中的跨平台类库主要有:
        信号类：Condition（broadcast，signal，wait），CriticalSection （lock，unlock），WaitAccess，
    Event（set，reset，wait），Mutex（lock，unlock）， Semaphore（wait，tryWait，post）
        网络类：InetAddress，Socket，ServerSocket，DatagramSocket，SocketInputStream，
    SocketOutputStream
        日期类：DateFormat，DateTimeDateFormat，System（currentTimeMillis）
        文件类：FileWatchdog（doOnChange）
        内存操作类：基于引用计数机制的智能指针 ObjectPtrT
        字符串操作类：StrictMath，StringHelper（toUpperCase，toLowerCase，trim，equalsIgnoreCase
    ，endsWith，format），StringTokenizer
        线程类：Thread（start，run，join）
      
   使用以上的类不用考虑 thread handle, event handle, socket handle 之类的 handle 问题，所有这些文
件已经被封装了。很好用，对不对？
   不足之处在于没有 GUI 类。ANSI C++ 中对于目录等文件系统的处理功能较弱，这里面也没有目录处理类。
另外 Socket 的 read(void * buf, size_t len) 不能设置 timeout，并且如果读取数据个数小于 len 那么 
read 函数将一直堵塞，不太好用，很可惜。实际的使用上面，可以考虑做一个 Socket 子类，重写 read() 函数。


vc71环境中编译安装
  版本：log4cpp-0.3.5rc1.tar.gz

   打开 msvc6  编译即可

头文件在 %log4cpp_root%/include\log4cpp
库文件在 %log4cpp_root%/lib

头文件添加方法如：
＃i nclude   需要链接lib库


5   Crypto++   加/解密算法库
   ---http://sourceforge.net/projects/cryptopp/
   ---http://www.eskimo.com/~weidai/cryptlib.html
   ---http://www.cryptopp.com

   提供处理密码，消息验证，单向hash，公匙加密系统等功能的免费库。
Crypto++ 是一个非常专业的C++ 密码学函式库，几乎在密码学里头常见的演算法都可以在Crypto++ 
找到实作的函式，如：block 与stream  ciphers，hash functions，MACs，random number generators，
public key 加密...等方法

vc71环境中编译安装
  版本：cryptopp521.zip

直接通过 cryptest.dsw 相关的库

头文件在 %cryptopp_root%
库文件在 %cryptopp_root%/lib

头文件添加方法如：
＃i nclude &lt;*.h&gt;  需要链接lib库

6   ACE

    ------http://www.cs.wustl.edu/~schmidt/ACE.html

    C+ +库的代表，超重量级的网络通信开发框架。ACE自适配通信环境（Adaptive Communication Environment）
是可以自由使用、开放源代码的面向对象框架，在其中实现了许多用于并发通信软件的核心模式。ACE提供了一组
丰富的可复用C++ 包装外观（Wrapper Facade）和框架组件，可跨越多种平台完成通用的通信软件任务，其中包括：
事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通信、共享内存管理、消息路由、分布式服务动
态（重）配置、并发执行和同步，等等。

7. CppUnit
    -------http://sourceforge.net/projects/cppuint/

　　一个c++的单元测试框架，可以通过派生测试类的方式，定制具体的测试方案。xUnit家族的一员，
从JUnit移植而来，JUnit是Java语言的单元测试框架。

vc71环境中编译安装
  版本：cppunit-1.10.2.tar.gz

直接通过 CppUnitLibraries.dsw  编译相关的库

头文件在 %cppunit_root%/cppunit
库文件在 %cppunit_root%/lib

头文件添加方法如：
＃i nclude   需要链接lib库

8    Loki
       -----http://moderncppdesign.com
       -----http://sourceforge.net/projects/loki-lib/
       -----http://sourceforge.net/projects/loki-exp/

     其实可和Boost一起介绍它，一个实验性质的库。作者在loki中把C++模板的功能发
挥到了极致。并且尝试把类似设计模式这样思想层面的东西通过库来提供。同时还提供
了智能指针这样比较实用的功能。

   该库系模板库，库本身无需编译，在你的工程文件中 引用头文件就可以使用，
如果 你直接或间接使用了small object，那你需要在你的工程文件 加上 SmallObj.cpp
如果 你直接或间接使用了Singletons，那你需要在你的工程文件 加上 Singleton.cpp


-----------------------------------------------------------------------------------------
学术性的C++库:
-----------------------------------------------------------------------------------------
1     FC++: The Functional C++ Library
     --------http://www.cc.gatech.edu/~yannis/fc++/

  这个库提供了一些函数式语言中才有的要素。属于用库来扩充语言的一个代表作。如果想要在OOP之外寻找另
一分的乐趣，可以去看看函数式程序设计的世界。大师Peter Norvig在 “Teach Yourself Programming in 
Ten Years”一文中就将函数式语言列为至少应当学习的6类编程语言之一。

   当前版本：FC++.1.5.zip
    模板库,在实际工程中 ，加上要用的头文件 就可以编译。

2     CGAL
      -----http://www.cgal.org

    Computational Geometry Algorithms Library的目的是把在计算几何方面的大部分重要的解决方案和方
法以C++库的形式提供给工业和学术界的用户。

    当前版本：CGAL-3.1.zip
   这是一个已编译的版本，当然也包括完整的源码

头文件在 %CGAL_root%/include/CGAL
库文件在 %CGAL_root%/lib/msvc7

头文件添加方法如：
＃i nclude   需要链接lib库




-----------------------------------------------------------------------------------------
其它目前我感觉还不是很爽的C++库：
-----------------------------------------------------------------------------------------
1  Doxygen
     ------http://sourceforge.net/projects/doxygen/
     ------http://www.stack.nl/~dimitri/doxygen/

　　注释文档生成工具，较之Doc++功能更为齐全，可以生成包括HTML、PDF、RTF在内的多种格式的文档，
并有GUI界面，除了支持c/c++语言外，还支持IDL、java、PHP、c#等。


2、   QT(windows版要付钱) 
     -------http://www.trolltech.com/
     -------http://www.qiliang.net/qt.html

   Qt是Trolltech公司的一个多平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形
用户界面所需的所用功能。Qt是完全面向对象的很容易扩展，并且允许真正地组件编程。自从1996年早些时候，
Qt进入商业领域，它已经成为全世界范围内数千种成功的应用程序的基础。Qt也是流行的Linux桌面环境KDE 
的基础，同时它还支持Windows、Macintosh、Unix/X11等多种平台。


3、Fox
   ---------http://www.fox-toolkit.org/
   开放源代码的GUI库。作者从自己亲身的开发经验中得出了一个理想的GUI库应该是什么样子的感受
出发，从而开始了对这个库的开发。有兴趣的可以尝试一下。


4  xml4c
    ------http://www.alphaworks.ibm.com/tech/xml4c

　　IBM的XML Parser，用c++语言写就，功能超级强大。号称支持多达100种字符编码，能够支持中文，
适合于大规模的xml应用。若只是很小范围的应用，则非最佳选择，毕竟，你需要“背负”约12M左右的
dll的沉重负担

5    Xerces c++
       -------http://xml.apache.org/xerces-c

　　Apache的XML项目，同样是c++ 实现，来源于IBM的xml4c，因此编程接口也是和xml4c一致的。但是
目前只支持少数的字符编码，如ASCII，UTF-8，UTF-16等，不能处理包含中文字符的XML文档。
   Xerces-C++ 是一个非常健壮的XML解析器，它提供了验证，以及SAX和DOM API。XML验证在文档类型定
义(Document Type Definition，DTD)方面有很好的支持，并且在2001年12月增加了支持W3C XML Schema 
的基本完整的开放标准。

6   XMLBooster
      -------http://www.xmlbooster.com/

    这个库通过产生特制的parser的办法极大的提高了XML解析的速度，并且能够产生相应的GUI程序
来修改这个parser。在DOM和SAX两大主流XML解析办法之外提供了另外一个可行的解决方案。


-----------------------------------------------------------------------------------------
C++开发环境(Win平台下除了 Visual C++ 和 Borland C++以外的)：
-----------------------------------------------------------------------------------------

1. Cygwin  （Windows下的一个Unix仿真环境）
    这个Cygwin的一部分是GCC的另外一个Windows移植版本，Cygwin是Windows下的一个Unix仿真环境。
严格的说是模拟GNU的环境，这也就是"Gnu's Not Unix"要表达的意思。

    至Cygwin的網站http://www.cygwin.com/下載安裝程式setup.exe，可直接點選執行或先行下載
至個人電腦後再執行。
    目前我已经下载到本地了，直接安装即可。

2.  MinGW  （GCC的一个Windows移植版本）
     1)http://sourceforge.net/projects/mingw 直接访问的，点击 Files，然后下载以下文
件：MinGW-3.1.0-1.exe, mingw32-make-3.80.0-3.exe。
安装MinGW 到 C:/MinGW 目录下，然后安装 mingw32-make 到 C:/MinGW 下，通过浏览器
到 C:/MinGW/bin 下，将 mingw32-make.exe 改名或者另外复制为 make.exe。

（以上的设置已经足够。不过为了求新，我是同时下载了 gcc-core-3.4.2-20040916-1.tar.gz,
 mingw-runtime-3.5.tar.gz 和 w32api-3.1.tar.gz，将它们直接解压到 C:/MinGW 下更新旧的
文件。不过这对这篇文章本身没有任何影响。新旧两种配置我都测试过。）

  安装次序： 
     MinGW-3.1.0-1.exe
     mingw32-make-3.80.0-3.exe
     gcc-core-3.4.2-20040916-1.tar.gz
     mingw-runtime-3.5.tar.gz
     w32api-3.1.tar.gz
     gdb-5.2.1-1.exe
     mingw-utils-0.3.tar.gz
     binutils-2.15.91-20040904-1.tar.gz


   3)准备MinGW 用户开发的命令行环境（一个批处理）
如： mingw.bat
@rem --------------------------------------
@SET MINGW_ROOT=D:\Mingw

@rem
@echo Setting environment for using Mingw.
@rem

@set PATH=%MINGW_ROOT%\BIN;%PATH%
@set INCLUDE=%MINGW_ROOT%\INCLUDE;%MINGW_ROOT%\INCLUDE\c++\3.2.3;%MINGW_ROOT%\include\c++\3.2.3\mingw32;%MINGW_ROOT%\include\c++\3.2.3\backward;%INCLUDE%
@set LIB=MINGW_ROOT\LIB;%LIB%
@rem ----------------------------------------

3. Dev C++   （一个C/C++ 的集成开发环境）

   GCC是一个很好的编译器。在Windows上的C++编译器一直和标准有着一段距离的时候，GCC就是一个
让Windows下开发者流口水的编译器。Dev-C++就是能够让GCC跑在Windows下的工具，作为集成开发环
境，还提供了同专业IDE相媲美的语法高亮，代码提示，调试等功能。由于使用Delphi开发，占用内存
少，速度很快，比较适合轻量级的学习和使用。

   可以使用  MinGW-GCC 作为它的编译器 


4  Eclipse-CDT


游戏开发

Audio/Video 3D C++ Programming Library

  ------http://www.galacticasoftware.com/products/av/
  ------http://sourceforge.net/projects/av3d/

***3D是一个跨平台，高性能的C++库。主要的特性是提供3D图形，声效支持（SB,以及S3M），控制接口（键盘，鼠标和遥感），XMS。

KlayGE

  ------http://home.g365.net/enginedev/
  ------http://sourceforge.net/projects/klayge/

   国内游戏开发高手自己用C++开发的一个开放源代码、跨平台的游戏引擎。KlayGE是一个开放源代码、跨平台的游戏引擎，并使
用Python作脚本语言。KlayGE在LGPL协议下发行。感谢龚敏敏先生为中国游戏开发事业所做出的贡献。

OGRE

  ------http://www.ogre3d.org
  ------http://www.ogre3d.org/docs/manual/
  ------http://sourceforge.net/projects/ogre

 

  OGRE（面向对象的图形渲染引擎）是用C++开发的，使用灵活的面向对象3D引擎。它的目的是让开发者能更方便和直接地开发
基于3D硬件设备的应用程序或游戏。引擎中的类库对更底层的系统库（如：Direct3D和OpenGL）的全部使用细节进行了抽象，并提供了基于现实世界对象的接口和其它类。



from:http://www.cnblogs.com/fwycmengsoft/archive/2008/10/17/1313788.html<img src ="http://www.cppblog.com/kyelin/aggbug/142660.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kyelin/" target="_blank">我风</a> 2011-03-24 17:22 <a href="http://www.cppblog.com/kyelin/archive/2011/03/24/142660.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>winnt.h(236) : error C2146</title><link>http://www.cppblog.com/kyelin/archive/2011/01/27/139397.html</link><dc:creator>我风</dc:creator><author>我风</author><pubDate>Thu, 27 Jan 2011 01:44:00 GMT</pubDate><guid>http://www.cppblog.com/kyelin/archive/2011/01/27/139397.html</guid><wfw:comment>http://www.cppblog.com/kyelin/comments/139397.html</wfw:comment><comments>http://www.cppblog.com/kyelin/archive/2011/01/27/139397.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kyelin/comments/commentRss/139397.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kyelin/services/trackbacks/139397.html</trackback:ping><description><![CDATA[编译项目时出现如下错误:<br /> 1&gt;Stdafx.cpp 1&gt;c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(236) : error C2146: 语法错误 : 缺少“;”(在标识符“PVOID64”的前面) <br />1&gt;c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(236) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int <br />1&gt;c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(7818) : error C2146: 语法错误 : 缺少“;”(在标识符“Buffer”的前面)<br />1&gt;c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(7818) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int <br />1&gt;c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(7818) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int <br /><br />查找后发现问题出在vc包含目录顺序问题.<br />调整DXSDK/Inclue到最后面,问题解决. <br />参考:http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/51043152-3ab6-4a9e-b3c1-2dba8300d9bb/<img src ="http://www.cppblog.com/kyelin/aggbug/139397.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kyelin/" target="_blank">我风</a> 2011-01-27 09:44 <a href="http://www.cppblog.com/kyelin/archive/2011/01/27/139397.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ShockwaveFlash控件详解(转载)</title><link>http://www.cppblog.com/kyelin/archive/2010/12/24/137390.html</link><dc:creator>我风</dc:creator><author>我风</author><pubDate>Fri, 24 Dec 2010 09:27:00 GMT</pubDate><guid>http://www.cppblog.com/kyelin/archive/2010/12/24/137390.html</guid><wfw:comment>http://www.cppblog.com/kyelin/comments/137390.html</wfw:comment><comments>http://www.cppblog.com/kyelin/archive/2010/12/24/137390.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kyelin/comments/commentRss/137390.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kyelin/services/trackbacks/137390.html</trackback:ping><description><![CDATA[
		<p>ShockwaveFlash控件详解</p>
		<p>本文由<a href="http://y9j9.com/">应有尽有</a>-应有尽有网为您整理提供</p>
		<p>
		</p>
		<p align="center">
		</p>
		<p>
		</p>
		<p>
		</p>
		<font size="4">、<span class="t_tag" href="tag.php?name=%CA%F4%D0%D4">属性</span>方面<br /><br /></font>AlignMode （读写） <br />语法：AlignMode As Long <br />说明：对齐方式，与 SAlign 属性联动。当控件的 长宽比例与影片不一致且 WMode 不为 ExactFit 时，影片 （没有被放大的）在控件中显示的位置可用该属性调整。 该属性值由标志位组成。如图，将该属性值（二进制）中相 应的位标记为 1 就<span class="t_tag" href="tag.php?name=%C9%E8%D6%C3">设置</span>了相应的对齐方向。 属性值与相应的对齐方式。后面括号里是二进制数。<br /><br />1：左对齐(0001)<br />2：右对齐(0010)<br />4：顶对齐(0100)<br />8：底对齐(1000)<br /><br />也可以组合各种对齐方式，同时将两个或以上的位标记为 1，也就是将这四个基本值组合相加。比如同时左对齐 和顶对齐，属性值则设为 5（0101）。 <br />例子 ： 设置影片为右对齐： <br />movie.AlignMode = 2 <br /><br />--------------------------------------------------------<br /><br />SAlign （读写） <br />语法：SAlign As String <br />说明：对齐模式（与 AlignMode 联动）。当 AlignMode <br />代表各对齐模式的位被置“1”时，SAlign 值也相应被设为 <br />“L”（Left）、“T”（Top）、“R”（Right）、“B”（Bottom）各 <span class="t_tag" href="tag.php?name=%D7%D6%B7%FB">字符</span>的组合。‘L’、‘T’、‘R’、‘B’的先后顺序不变。<br />例子：设置影片为左对齐和顶对齐： <br />movie.SAlign = "LT" <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />BackgroundColor（读写） <br />语法：BackgroundColor As Long <br />说明：影片的背景色（与 BGColor 联动）。以（红 × 65536 ＋绿× 256 ＋蓝）计算<span class="t_tag" href="tag.php?name=%D1%D5%C9%AB">颜色</span>值。红绿蓝颜色取 值范围（0-255）。默认的影片背景色为 -1 。如果影片 设置了底色或有图片当作背景，那么看不出来该属性值的 改变会有什么影响。 <br />例子：将影片背景色设为蓝色 ： <br />movie.BackgroundColor = 255 <br /><br />--------------------------------------------------------<br /><br />BGColor （读写） <br />语法：BGColor As String <br />说明：影片的背景色（与 BackgroundColor 联动）。与 BackgroundColor 不同的是，BGColor 是一个六位的十六进制数，每两位分别代表红绿蓝颜色值。如：FFEEAA 表示 红色值为 FF、绿色值为 EE 、蓝色值为 AA 。 <br />例子：将影片背景色设为红色：<br />movie.BGColor = "FF0000"<br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Base （读写） <br />语法：Base As String <br />说明：指定用于<span class="t_tag" href="tag.php?name=%BD%E2%BE%F6">解决</span>影片中所有相对<span class="t_tag" href="tag.php?name=%C2%B7%BE%B6">路径</span>的声明的基<span class="t_tag" href="tag.php?name=%B5%D8%D6%B7">地址</span>。当影片与其需要的其他<span class="t_tag" href="tag.php?name=%CE%C4%BC%FE">文件</span>不在同一目录中的时候该 属性特别有用。如不特别指定，Base 的值默认为 "."，也就 是当前影片所在的路径。 <br />例子 ： <br />movie.Base = "Http://www.domain.com/pathname1/pathname2" <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Movie （读写） <br />语法：Movie As String <br />说明：要播放的影片路径（URL）。设置该属性为 一个 SWF 文件的 URL 将载入文件并播放它。若影片是在本地硬盘上，要写成从盘符开始的绝对路径；若影片是在某网站上，也要写全 URL 地址。 <br />例子 ： <br />movie.Movie = "http://www.domain.com/path1/path2/filename.swf" <br />或 <br />movie.Movie = "c:\temp\test.swf" <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />DeviceFont （读写） <br />语法：DeviceFont As Boolean <br />说明 ： 决定是否使用影片内嵌的字体， 默认值为 False。将该属性值设为 True 则强制播放器不使用影片中的内嵌的字体而使用本地<span class="t_tag" href="tag.php?name=%CF%B5%CD%B3">系统</span>字体。 <br />例子：<br />movie.DeviceFont = True<br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />EmbedMovie （读写） <br />语法：EmbedMovie As Boolean <br />说明：影片是否被存贮到控件所在的容器中。当你已载入一个影片后将该属性设为 True，播放影片时就不必再去读 SWF 文件了。这使得在 PowerPoint 简报或 VB <span class="t_tag" href="tag.php?name=%B3%CC%D0%F2">程序</span> 里使用 Flash 影片更容易。但将该属性设为 True 后，控件的 Movie 属性就不再接受新的值了。要想播放另一个影片（给 Movie 属性赋新值），必须先将 EmbedMovie 属 性设为 False 。 <br />例子 ： <br />movie.EmbedMovie = True<br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />FrameNum （读写） <br />语法：FrameNum As Long <br />说明：影片当前帧的编号 （从 0 开始计数）。设置 该属性值将使影片停在由 FrameNum 指定的帧处。 <br />例子 ： 显示当前帧数：<br />MsgBox " 当前显示的是第 " &amp; movie.FrameNum &amp; " 帧。" <br /><br />使影片显示第 10 帧：<br />Bomovie.FrameNum = 9 <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />TotalFrames（只读） <br />语法：TotalFrames As Long <br />说明：返回影片中总帧数。该参数要到影片载入完成才有效（ReadyState=4）。 <br />例子 ： <br />If movie.ReadyState = 4 Then MsgBox " 本影片共有 " &amp; movie.TotalFrames &amp; " 帧。" <br /><br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Loop （读写） <br />语法：Loop As Boolean <br />说明：是否循环播放。设为 True 是循环播放，设为 False 则只播放一次。 <br />例子 ： <br />movie.Loop = True <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Menu （读写） <br />语法：Menu As Boolean <br />说明：是否显示<span class="t_tag" href="tag.php?name=%B2%CB%B5%A5">菜单</span>。设为 True 显示所有菜单，设为 False 菜单被屏蔽，但仍有一项“About Macromedia Flash Player...”。如果你实在不喜欢这个菜单，应该在程序中通过拦截<span class="t_tag" href="tag.php?name=%CA%F3%B1%EA">鼠标</span>消息的方法来达到目的。与在独立的 Flash 播放器中不同的是，在控件的右键菜单里点  <br />“About...”的话，就会打开浏览器到 Macromedia 的网站上去 看 About 。<img alt="" src="http://www.vbgood.com/images/smilies/default/run.gif" border="0" smilieid="52" /><br />例子 ： <br />movie.Menu = False <br /><br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Playing （只读） <br />语法：Playing As Boolean <br />说明：当前播放状态。如果影片正在播放，该属性 值为 True ，否则为 False 。 <br />例子 ： <br />If movie.Playing = False Then MsgBox " 影片已停止播放！"<br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Quality （读写） <br />语法：Quality As Long <br />说明：画面质量（与 Quality2 联动）。Quality 可以取: <br />0 ——相当于 Quality2 取 "Low" <br />1 ——相当于 Quality2 取 "High" <br />2 ——相当于 Quality2 取 "AutoLow" <br />3 ——相当于 Quality2 取 "AutoHigh" <br /><br />例子 ： <br />movie.Quality = 1 <br /><br />--------------------------------------------------------<br /><br />Quality2（读写） <br />语法：Quality As String <br />说明：画面质量(与 Quality 联动)。Quality2 可以取：<br /><font color="#ff0000">Low：</font>偏重于播放速度而不管显示<span class="t_tag" href="tag.php?name=%D0%A7%B9%FB">效果</span>，而且不启用 <br />消锯齿<span class="t_tag" href="tag.php?name=%B9%A6%C4%DC">功能</span> 。 <br /><font color="#ff0000">High：</font>偏重于画面而不管播放速度，并且总是启用 消锯齿功能。如果影片中不包含动画就平滑处理位图；如 果有动画，那么位图就不被平滑处理。（这里的动画应该 是把一张图片做平移或旋转） <br /><font color="#ff0000">AutoLow：</font>先着重于播放速度，但只要有可能就改 善显示效果。一开始播放时先禁用消锯齿功能。如果播放 器检测到处理器能承受得了 ，就启用消锯齿功能 。 <br /><font color="#ff0000">AutoHigh：</font>一开始是播放速度和显示效果并重，但 如有必要就牺牲画质确保速度。开始播放时就启用消锯齿 功能。但如果实际的帧速率比设计时指定的速率慢了，就 禁用消锯齿功能来提高播放速度。 <br />例子 ： <br />movie.Quality2 = "High" <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />ReadyState（只读） <br />语法：ReadyState As Long <br />说明：影片的当前状态。ReadyState 可以取： <br />0 ——正在载入 <br />1 ——未初始化 <br />2 ——已载入 <br />3 ——正在交互 <br />4 ——完成 例子 ： <br />If movie.ReadyState = 4 Then MsgBox " 影片载入完成！"<br /><br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Scale （读写） <br />语法：scale As String <br />说明：缩放模式（与 ScaleMode 联动）。Scale 可以 取: <br />ShowAll ——在控件内显示全部影片区域，保持影片 长宽比例不变，影片的大小决定于控件长或宽中较小的一 边 。 <br />NoBorder ——在控件内显示部分影片区域，保持影片 长宽比例不变，影片的大小决定于控件长或宽中较大的一 边 。 <br />ExactFit ——在控件内显示全部影片区域，将影片的长 宽比例强制等于控件的长宽比例。 <br />例子 ： <br />MsgBox " 当前的缩放模式是：" &amp; movie.Scale <br /><br />--------------------------------------------------------<br /><br />17.ScaleMode（读写） <br />语法：ScaleMode As Long <br />说明：缩放模式(与 Scale 联动)。ScaleMode 可以取： <br />0 ——相当于 Scale 取 "ShowAll" <br />1 ——相当于 Scale 取 "NoBorder" <br />2 ——相当于 Scale 取 "ExactFit" <br />例子：使影片的缩放模式改成“ExactFit ”： <br />movie.ScaleMode = 2 <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Stacking （读写） <br />语法：Stacking As String <br />说明：用于 HTML，将 Flash Player 当成 HTML 中 的一种“行为”使用时，该属性决定 Flash 影片相对于与其 参照的 HTML 内容如何显示。（有关“行为”请参阅样式表 的资料）。Stacking 可以取： <br />none ——“行为”不显示。 <br />replaceall ——“行为”的显示取代全部其他元素的内容，包括背景 。 <br />content ——“行为”的显示只取代其他元素的内 容。 <br />background ——“行为”的显示只取代其他元素的背景 。 <br />below ——“行为”在所有其他元素内容的下面显示。 <br />belowflow ——“行为”以反向 Z 顺序显示在其他元素 的子<span class="t_tag" href="tag.php?name=%B6%D4%CF%F3">对象</span>之上，但在该元素主要内容之上。 <br />aboveflow ——“行为”以正向 Z 顺序显示在其他元素 的子对象之下，但在该元素主要内容之上。 <br />above ——“行为”显示在所有其他元素的内容之上。 <br />top ——“行为”的显示置于整个页面内容之上。<br /><br />例子 ： <br />movie.Stacking = "below" <br /><br /><br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />20.WMode （读写） <br />语法：WMode As String <br />说明：控件的<span class="t_tag" href="tag.php?name=%B4%B0%BF%DA">窗口</span>模式。WMode 可以取： Window —— WMode 属性的默认值，按 Flash 播放器 <br />典型的方式工作，即在控件的矩形窗口中播放影片，这样一 般都能提供最快的动画效果。 <br />Opaque ——使影片不透明。 Transparent ——创建一个透明的影片。如果影片中有 <br />透明的片段，放到这里时，就可以看到控件下面的背景。但 使用此属性值，动画的播放速度可能会慢一些。 <br />例子 ： <br />movie.WMode = "Transparent"<br /><br /><br />写到这里 累残我了======<br /><br /><font color="#808080">======================================== 白金分割线 0.618 ========================================</font><br /><br /><br /><font size="4">二、控件方法</font><br /><br /><br />下面中的方法不返回值：<br /><br />Back <br />语法：Back()  <br />说明 ： 影片后退一帧 ， 并且停止播放 。 例子 ： <br />movie.Back <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Forward <br />语法：Forward() <br />说明 ： 影片前进一帧， 并且停止播放。<br />例子 ： <br />movie.Forward <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />GotoFrame <br />语法：GotoFrame(FrameNum As Long) <br />说明：将影片跳转到由 FrameNum 指定的帧，并且停止播放。如果所指定的帧还未载入，播放器前进到最后的可用帧并停下，在调用过程中会产生无法预料的后果。最好使用 PercentLoaded 方法来确定是否已载入足够的影片来执行本方法。参数 FrameNum 是从 0 开始的，这和 Flash 中的 Goto 动作不一样，它是从 1 开始的。 <br />例子：跳转到影片的第 20 帧： <br />movie.GotoFrame 20 <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />LoadMovie <br />语法：LoadMovie(layer As Long, url As String) <br />说明：将由 url 指定的影片载入到由 layer 指定的层上。 <br />例子：将 movie.swf 载入至 0 层： <br />movie.LoadMovie 0, "movie.swf"<br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Pan <br />语法：Pan(x As Long, y As Long, mode As Long) <br />说明：将一个放大过的影片平移由 x 和 y 指定的距离。 x 和 y 均为相对值。即控件相对于影片来说平移的距离（你 可以想象控件是一个窗户，影片是我们从窗户里看到的放 在外面的布景, 我们看到窗户相对于布景平移了一些距离， 那是外面的布景在动，而窗户是不动的）。用 mode 参数 来指定 x 和 y 的值是像素还是窗口的百分比，当 mode=0 时 坐标系以像素为单位；mode=1 时坐标系就以窗口的百分 比来计算。 平移并不能超出影片的边框，也就是说，往 一个方向平移最多到达影片的边缘与控件对齐的程度。 <br />例子：控件相对于影片向左向上各平移 5 个像素（当 然控件不会动 ，是影片向右向下平移了 ）： <br />movie.Pan 5,5,0 <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Play <br />语法：Play() <br />说明：开始播放影片。<br />例子：<br />movie.Play<br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />Rewind <br />语法：Rewind() <br />说明：倒带。返回到影片的第一帧。<br />例子：<br />movie.Rewind <br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />SetVariable <br />语法：SetVariable(name As String, value As String) <br />说明：将由 name 指定的 Flash <span class="t_tag" href="tag.php?name=%B1%E4%C1%BF">变量</span>值设为 value。<br />例子：<br />movie.SetVariable "/Form:UserName", "John Smith"<br /><br /><font color="#808080">======================================== 白金分割线 0.618 ========================================</font><br /><br /><font size="4">三、事件方面</font><br /><br />FSCommand<br />语法：ShockwaveFlash1_FSCommand(ByVal command As String, ByVal args As String)<br />说明：在flash中调用fscommand()触发的事件<br />参数：<br />command ：代表<span class="t_tag" href="tag.php?name=%C3%FC%C1%EE">命令</span>标识<br />args ：代表参数<br /><br />例子：<br /><br />Select Case command '这里可以用 if<br />                         '但command多了之后就不好 if 用了<br />                         '我是做个示范<br />       Case "command1"<br />         <br />         If args = "123" Then<br />            <br />            ...<br />            <br />         Else<br />            <br />            ...<br />            <br />         End If<br />         <br />       Case ...<br />      <br />End Select<br /><br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br /><br />FlashCall<br />语法：ShockwaveFlash1_FlashCall(ByVal request As String)<br />说明：可能很少人知道这个事件的用处，其实这个跟 FSCommand 事件是差不多的。与 FSCommand 不同的是，这个事件可以有返回值（下面会谈到）<br /><br />参数是一个XML<span class="t_tag" href="tag.php?name=%B8%F1%CA%BD">格式</span>的字符串，格式是<br />"&lt;invoke name='%s' returntype='xml'&gt;&lt;arguments&gt;&lt;string&gt;%s&lt;/string&gt;&lt;/arguments&gt;&lt;/invoke&gt;"，去查查帮助就知道了。<br /><br />处理request：标准VB没有处理XML的库，你可以自己找支持XML的插件来用。下面就是按照个人需要处理request了。<br /><br />返回值：<br />事件处理<span class="t_tag" href="tag.php?name=%BA%AF%CA%FD">函数</span>是没有返回值的，但是flash player提供了一个方法：ShockwaveFlash1.SetReturnValue() 专门传递返回值，格式是&lt;string&gt;%s&lt;/string&gt;（也可以是别的AS结构，具体看帮助）。<br /><br />例子：我在这给出tinyxml的例子：<br /><br />Private Sub ShockwaveFlash1_FlashCall(ByVal request As String)<br /><br />Dim request_xml As New TiXmlDocument<br />Dim request_name As String<br /><br />request_xml.Parse request<br />request_name = request_xml.RootElement().Attribute("name")<br /><br />...自己去处理吧<br /><br />End Sub<br /><br /><br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />OnProgress<br />语法：ShockwaveFlash1_OnProgress(ByVal percentDone As Long)<br />说明：估计是flash在<span class="t_tag" href="tag.php?name=%BC%D3%D4%D8">加载</span>过程中进度改变触发的吧？<br />percentDone 则应该是个百分数~<br />反正我还没逮住这个事件一次..= =!<br /><br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />OnReadyStateChange<br />语法：ShockwaveFlash1_OnReadyStateChange(newState As Long)<br />说明：顾名思义，就是 ReadyState 改变时触发的事件，具体请看上面关于 ReadyState 属性的说明，我在这就不废话了....<br /><br /><font color="#ff8c00">======================================== 黄金分割线 0.618 ========================================</font><br /><br />至于其他事件，比如<br />GotFocus啦、LostFocus啦，我也不想废话了...<br />from:http://y9j9.com/html/jisuanjiyingyong/201003/28-336.html<img src ="http://www.cppblog.com/kyelin/aggbug/137390.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kyelin/" target="_blank">我风</a> 2010-12-24 17:27 <a href="http://www.cppblog.com/kyelin/archive/2010/12/24/137390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MFC常用调试函数(转)</title><link>http://www.cppblog.com/kyelin/archive/2010/11/25/134628.html</link><dc:creator>我风</dc:creator><author>我风</author><pubDate>Thu, 25 Nov 2010 07:06:00 GMT</pubDate><guid>http://www.cppblog.com/kyelin/archive/2010/11/25/134628.html</guid><wfw:comment>http://www.cppblog.com/kyelin/comments/134628.html</wfw:comment><comments>http://www.cppblog.com/kyelin/archive/2010/11/25/134628.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kyelin/comments/commentRss/134628.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kyelin/services/trackbacks/134628.html</trackback:ping><description><![CDATA[
		<p>
				<strong>AfxCheckMemory   </strong>
				<br />
				<br />BOOL AfxCheckMemory( );    // 检查当前分配的所有内存的完整性<br /><br />返回值：如果没有内存错误，则为非零值；否则为0。<br /><br />说明：<br />这个函数使自由内存池有效并在需要时输出错误信息。如果这个函数没有检测到内存冲突，它什么也不输出。<br />当前在堆中分配的所有内存块都会被检查，包括那些用 new分配的内存，但是不包括那些用直接调用内存分配函数分配的内存，例如malloc函数或者Windows的GlobalAlloc函数。如果发现有内存块存在错误，就会在调试器上输出错误信息。<br />如果你在程序模块中包含了下面的程序行：<br />#define new DEBUG_NEW<br />后面对AfxCheckMemory的调用都会显示发生内存分配的文件名和行号。<br />注意：<br />如果你的模块中包含了一个或多个串行化类的实现，那么你必须在最后一个IMPLEMENT_SERIAL宏之后包含#define程序行。这个函数仅在MFC的调试版本中起作用。<br /><br />示例：<br />// AfxCheckMemory的例子<br />CAge* pcage = new CAge( 21 ); // CAge 是从 CObject.继承而来的<br />Age* page = new Age( 22 ); // Age 不是从 CObject.继承的<br />*(((char*) pcage) - 1) = 99; // 破坏前面的保护字节<br />*(((char*) page) - 1) = 99; // 破坏前面的保护字节<br />AfxCheckMemory();<br /><br />程序的结果如下：<br />memory check error at $0067495F = $63, should be $FD<br />DAMAGE: before Non-Object block at $00674960<br />Non-Object allocated at file test02.cxx(48)<br />Non-Object located at $00674960 is 2 bytes long<br />memory check error at $00674905 = $63, should be $FD<br />DAMAGE: before Object block at $00674906<br />Object allocated at file test02.cxx(47)<br />Object located at $00674906 is 6 bytes long</p>
		<p>
				<strong>AfxDump</strong>
				<br />
				<br />void AfxDump(const CObject* pOb);    // 如果在调试器内调用，则转存对象的状态<br /><br />参数： pOb 指向由CObject继承的类的对象的指针。 <br /><br />说明：<br />在调试器中调用这个函数以在调试时转储对象的状态。AfxDump调用一个对象的Dump函数并且将信息发送到afxDump变量指定的位置。AfxDump仅能在MFC的调试版本中使用。<br />你的程序代码不应该调用AfxDump，而是应该调用适当对象的Dump成员函数。</p>
		<p>
				<strong>AfxDumpStack<br /></strong>
				<br />void AFXAPI AfxDumpStack(DWORD dwTarget = AFX_STACK_DUMP_TARGET_DEFAULT); // 生成当前栈的一个映像，该函数通常被静态链接<br /><br />参数： dwTarget 指出转储输出的目标。其取值可以用位或操作符（|）组合起来，可能值如下： · AFX_STACK_DUMP_TARGET_TRACE 通过TRACE宏输出。TRACE仅仅在调试版本中产生输出，在发行版本中不产生输出。同时，TRACE可以被重定向到调试器以外的目标。 <br /><br />· AFX_STACK_DUMP_TARGET_DEFAULT 将转储输出发送到缺省目标。对于调试版本，输出发送给TRACE宏。在发行版本中，输出发送到剪贴板。 <br /><br />· AFX_STACK_DUMP_TARGET_CLIPBOARD 输出仅发送到剪贴板。数据将按CF_TEXT格式以普通文本的形式放在剪贴板上。 <br /><br />· AFX_STACK_DUMP_TARGET_BOTH 同时将输出发送到剪贴板和TRACE宏。 <br /><br />· AFX_STACK_DUMP_TARGET_ODS 通过Win32函数OutputDebugString()直接将输出发送的调试器。如果连接了调试器，它在调试版本和发行版本中都会产生调试器输出。AFX_STACK_DUMP_TARGET_ODS 通常到达调试器（如果连接了调试器），并且不能被重定向。 <br /><br />说明：<br /><br />这个全局函数可以被用来生成当前栈的一个映象。下面的例子反映了MFC对话框应用程序中按钮处理函数调用AfxDumpStack所产生的单行调试输出：<br /><br />=== begin AfxDumpStack output ===<br />...<br /><br />BFF928E0: WINDOWS\SYSTEM\KERNERL32.DLL! UTUnRegister + 2492 bytes<br /><br />=== end AfxDumpStack() output ===<br /><br />BFF928E0： 最近一次函数调用的返回地址 <br /><br />WINDOWS\SYSTEM\KERNEL32.DLL! 包含函数调用的模块的完整路径名 <br /><br />UTUnRegister 调用的函数原型 <br /><br />+ 2492 bytes 以字节为单位的从函数原型地址（这个例子中为UTUnregister）到返回地址（这个例子中为BEF928E0）的偏移 <br /><br />AfxDumpStack在MFC库的调试版本和非调试版本中都可以使用。但是，这个函数通常是静态连接的，即使你的可执行文件以共享DLL的方式使用MFC。<br /><br />在共享库的实现中，可以在MFCS42.LIB库（以及它的变化形式）中找到这个函数。<br /><br />为了成功地使用这个函数： <br />        · 在你的路径中必须包含IMAGEHLP.DLL文件。如果你没有这个DLL文件，这个函数会显示一条错误信息。IMAGEHLP.DLL是随Win32 SDK和Windows一起发售的可散发的DLL。在C:\[Windows]\system[32]下查找它。有关IMAGEHLP提供的函数集的介绍可以参考“可移植的可执行文件的操作”一文。 <br /><br />        · 具有栈框架的模块必须包含调试信息。如果它不包含调试信息，这个函数仍然会生成对栈的跟踪，但是这种跟踪是很简略的。</p>
		<p>
				<strong>AfxEnableMemoryTracking</strong>
				<br />
				<br />BOOL AfxEnableMemoryTracking(BOOL bTrack); // 打开或关闭内存跟踪<br /><br />返回值：以前的跟踪允许状态设置。<br /><br />参数： bTrack 将这个值设为TRUE时就打开了内存跟踪特性。如果是FALSE则将其关闭。 <br /><br />说明：<br />诊断内存跟踪通常在MFC的调试版本中有效。利用这个函数对你的代码中正确分配内存的部分禁止跟踪。<br />有关AfxEnableMemoryTracking的更多信息请参见《Visual C++程序员指南》中的“MFC调试支持”。<br />注意：这个函数仅在MFC的调试版本中起作用。</p>
		<p>
				<strong>AfxIsMemoryBlock</strong>
				<br />
				<br />BOOL AfxIsMemoryBlock( const void* p, UINT nBytes, LONG* plRequestNumber = NULL ); // 检验一个内存块是否被正确的分配<br /><br />返回值：<br />如果内存块是现在分配的，并且其长度也是正确的，则返回非零值。否则为0。<br /><br />参数： p 指向将被测试的内存块。 <br />nBytes 包含了以字节为单位的内存块长度。 <br />plRequestNumber 指向一个长整数，它将被设为内存块的分配系列号码。由plRequestNumber指向的这个变量只有当AfxIsMemoryBlock返回非零值时才会被填充。 <br /><br />说明：<br />检测一个内存地址，确保它代表了一个由new的诊断版本分配的活动的内存块。它同时也检验指定的大小是否与最初分配的大小相符。如果这个函数返回非零值，分配的系列号码将在plRequestNumber中返回。这个号码代表了这个内存块相对于其它所有内存分配的顺序。<br /><br />示例：<br />// AfxIsMemoryBlock的例子<br />CAge* pcage = new CAge( 21 ); // CAge is derived from CObject.<br />ASSERT( AfxIsMemoryBlock( pcage, sizeof( CAge ) ) )</p>
		<p>
				<strong>AfxIsValidString</strong>
				<br />
				<br />BOOL AfxIsValidString( LPCSTR lpsz, int nLength = -1 ); // 检验一个字符串指针是否有效<br /><br /><br />如果给定的指针指向一个给定大小的字符串则返回非零值，否则返回0。<br /><br />参数： lpsz 要测试的指针。 <br />nLength 指定要测试的字符串的长度，以字节为单位。如果值为－1，表示字符串是以null结尾的。 <br /><br />说明：<br />使用这个函数来确定指向字符串的指针是否有效。</p>
		<p>
				<strong>AfxSetAllocHook<br /></strong>
				<br />AFX_ALLOC_HOOK AfxSetAllocHook( AFX_ALLOC_HOOK pfnAllocHook ); // 允许在每次进行内存分配事调用一个函数<br /><br />如果你希望允许分配，则返回非零值。否则返回0。<br /><br />参数： pfnAllocHook 指定要调用的函数名。参考关于分配函数的原型的说明。 <br /><br />说明：<br />这个函数设置一个钩子，使每次分配内存之前都会调用一个指定的函数。微软基础类库中的调试内存分配函数能够调用一个用户定义的钩子函数，使用户能够监控内存分配并控制是否允许分配内存。内存分配的钩子函数的原型如下：<br />BOOL AFXAPI AllocHook( size_t nSize, BOOL bObject, LONG lRequestNumber );<br /><br />nSize 计划分配的内存大小。 <br />bObject 如果是要为一个CObject派生类对象分配内存则为TRUE，否则为FALSE。 <br />lRequestNumber 内存分配的系列号。<br />注意，AFXAPI调用约定意味着调用者必须从栈中清除参数。</p>
		<p>
				<strong>AfxDoForAllClasses</strong>
				<br />
				<br />void AFXAPI AfxDoForAllClasses(<br />void (* pfn)(const CRuntimeClass* pClass, void* pContext),<br />void* pContext<br />); //对所有从CObject继承的支持运行时检查的类执行一个特定的功能<br /><br />参数： pfn 指向每个类都会调用的重复函数。这个参数是一个指向CRuntimeClass对象的指针以及指向调用者提供给函数的附加数据的void指针。 <br />pContext 指向调用者提供给重复函数的可选数据的指针。这个指针可以是NULL。 <br /><br />说明：<br />在应用程序的内存空间中，为所有从CObject继承的可串行化的类调用指定的重复函数。从CObject继承的可串行化的类是以DECLARE_SERIAL宏继承的。每次调用指定的重复函数时，都会将在pContext中传递给AfxDoForAllClasses的指针传递给重复函数。<br />注意：这个函数仅在MFC的调试版本中起作用。</p>
		<p>
				<strong>AfxDoForAllObjects<br /></strong>
				<br />void AfxDoForAllObjects(<br />void (* pfn)(CObject* pObject, void* pContext),<br />void* pContext<br />); // 对所有从CObject继承的用new分配内存对象执行一个指定的功能<br /><br />参数：pfn 指向每个对象都执行的重复函数。函数的参数是一个指向CObject的指针以及指向调用者提供给函数的附加数据的void指针。 <br />pContext 指向调用者提供给函数的附加数据的指针。这个指针可以为NULL。 <br /><br />说明：<br />对每个用new分配的从CObject继承的对象执行指定的重复函数。栈、全局变量或嵌入对象不包括在内。每次调用指定的重复函数时，都会将在pContext中传递给AfxDoForAllObjects的指针传递给重复函数。<br />注意：这个函数仅在MFC的调试版本中起作用。<br /><br />from:http://hi.baidu.com/ice_water/blog/item/7cef04f73475c42a720eec98.html</p>
<img src ="http://www.cppblog.com/kyelin/aggbug/134628.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kyelin/" target="_blank">我风</a> 2010-11-25 15:06 <a href="http://www.cppblog.com/kyelin/archive/2010/11/25/134628.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CRichEditCtrl使用大全</title><link>http://www.cppblog.com/kyelin/archive/2010/11/03/132300.html</link><dc:creator>我风</dc:creator><author>我风</author><pubDate>Wed, 03 Nov 2010 07:51:00 GMT</pubDate><guid>http://www.cppblog.com/kyelin/archive/2010/11/03/132300.html</guid><wfw:comment>http://www.cppblog.com/kyelin/comments/132300.html</wfw:comment><comments>http://www.cppblog.com/kyelin/archive/2010/11/03/132300.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kyelin/comments/commentRss/132300.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kyelin/services/trackbacks/132300.html</trackback:ping><description><![CDATA[
		<p>richedit 常见使用问题<br />一.常见问题<br />a.可以编译,不能执行的</p>
		<p>
				<br />在需要在相应的对话框中加上InitInstance（void）函数中添加</p>
		<p>AfxInitRichEdit();</p>
		<p>b.升级默认的Riched版本(默认的有一些bug)，如<br />可在InitInstance中添加<br />LoadLibrary("RICHED20.DLL") <br />最后注意 FreeLibrary</p>
		<p>如果是CRichEditView基类的可用<br />BOOL CXXXXXXView::PreCreateWindow(CREATESTRUCT&amp; cs)<br />{<br />//装入rich edit version 2.0<br />if (LoadLibraryA("RICHED20.DLL") == NULL)<br />{<br />AfxMessageBox(_T("Fail to load \"riched20.dll\"."),MB_OK | MB_ICONERROR);<br />PostMessage(WM_QUIT,0,0);<br />return FALSE;<br />}</p>
		<p>m_strClass = RICHEDIT_CLASSA;//for 2.0 class</p>
		<p>return CRichEditView::PreCreateWindow(cs);<br />}</p>
		<p>c.最后追加行<br />richeditctrl.SetSel(-1, -1);<br />richeditctrl.ReplaceSel( (LPCTSTR)str );</p>
		<p>d.字数限制<br />CRichEditCtrl::LimitText(long nChars)</p>
		<p>e.换行切换<br />CRichEditView的OnInitialUpdate()函数中加入下面两句：<br />m_nWordWrap = WrapNone;<br />WrapChanged(); <br />WrapChanged实际上也是调用<br />ctrl.SetTargetDevice(NULL, 1); //m_nWordWrap == WrapNone<br />ctrl.SetTargetDevice(NULL, 0); //m_nWordWrap == WrapToWindow<br />还有不常用的 m_nWordWrap == WrapToTargetDevice<br />ctrl.SetTargetDevice(m_dcTarget, GetPrintWidth());<br />如果是在Dialog中，可使用SetTargetDevice，注意在属性里面加上want return</p>
		<p>f.有时候不希望带格式的数据粘贴，可通过PasteSpecial选择性粘贴<br />pmyRichEditCtrl-&gt;PasteSpecial(CF_TEXT);</p>
		<p>g.随着输入随着自动滚动条滚动到最后一行<br />int nFirstVisible = pmyRichEditCtrl-&gt;GetFirstVisibleLine();<br />if (nFirstVisible &gt; 0)<br />{<br />    pmyRichEditCtrl-&gt;LineScroll(-nFirstVisible, 0);<br />}<br />或<br />m_cRichEdit.PostMessage(WM_VSCROLL, SB_BOTTOM,0);</p>
		<p>
				<br />h.设置UNDO的次数(只能用在RICHED20以上，即默认不支持，必须升级)<br />SendMessage(EM_SETTEXTMODE,TM_MULTILEVELUNDO,0);<br />TM_MULTILEVELUNDO 支持多取消(默认值).可通过EM_SETUNDOLIMIT设置最大次数 <br />SendMessage(EM_SETUNDOLIMIT,100,0);</p>
		<p>i.响应OnChange<br />EM_SETEVENTMASK 设置 ENM_CHANGE <br />long lMask = GetEventMask();<br />lMask |= ENM_CHANGE;<br />lMask &amp;= ~ENM_PROTECTED;<br />SetEventMask(lMask);</p>
		<p>j.设置只读<br />CRichEditCtrl::SetReadOnly( BOOL bReadOnly = TRUE );<br />通过设置PROTECTED实现选中的文本只读，参见<br /><a href="http://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/">http://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/</a></p>
		<p>
				<br />二.函数应用<br />a.设置字体（主要是通过SetSelectionCharFormat）<br />CHARFORMAT cf;<br />rich.GetSelectionCharFormat(cf);<br />cf.dwMask|=CFM_BOLD;<br />cf.dwEffects|=CFE_BOLD;//设置粗体，取消用cf.dwEffects&amp;=~CFE_BOLD;<br />cf.dwMask|=CFM_ITALIC;<br />cf.dwEffects|=CFE_ITALIC;//设置斜体，取消用cf.dwEffects&amp;=~CFE_ITALIC;<br />cf.dwMask|=CFM_UNDERLINE;<br />cf.dwEffects|=CFE_UNDERLINE;//设置斜体，取消用cf.dwEffects&amp;=~CFE_UNDERLINE;<br />cf.dwMask|=CFM_COLOR;<br />cf.crTextColor = RGB(255,0,0);//设置颜色<br />cf.dwMask|=CFM_SIZE;<br />cf.yHeight =200;//设置高度<br />cf.dwMask|=CFM_FACE;<br />strcpy(cf.szFaceName ,_T("隶书"));//设置字体<br />rich.SetSelectionCharFormat(cf);</p>
		<p>b.设置字体的行间距<br />要用richedit2.0以上<br />试试<br />PARAFORMAT2 pf;<br />pf.cbSize = sizeof(PARAFORMAT2);<br />pf.dwMask = PFM_NUMBERING | PFM_OFFSET;<br />pf.wNumbering = PFN_BULLET;//注意PFM_NUMBERING <br />pf.dxOffset = 10;<br />VERIFY(SetParaFormat(pf)); <br />常用的dwMask有<br />PFM_NUMBERING 成员 wNumbering 才起作用，项目符号，默认用PFN_BULLET<br />2 使用阿拉伯数字 (1, 2, 3, ...).  <br />3 使用小写字母 (a, b, c, ...).  <br />4 使用大写字母 (A, B, C, ...).  <br />5 使用小写罗马数字 (i, ii, iii, ...).  <br />6 使用大写罗马数字 (I, II, III, ...).  <br />7 自定义，字符见成员 wNumberingStart.  <br />PFM_OFFSET 成员 dxOffset 才起作用，缩进，单位twips<br />PFM_STARTINDENT 成员 dxStartIndent 才起作用，首行缩进<br />PFM_SPACEAFTER 成员 dySpaceAfter 才起作用，段间距<br />PFM_LINESPACING 成员 dyLineSpacing 才起作用，行间距</p>
		<p>c.设置CRichEditCtrl(2.0)背景透明 <br />long style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);<br />style &amp;= WS_EX_TRANSPARENT;<br />::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);<br />或 CreateEx，然后把WS_EX_TRANSPARENT样式加上</p>
		<p>e.得到内容有三种<br />1)GetWindowText<br />2)使用EM_GETTEXTEX<br />GETTEXTEX gt;<br />gt.cb = 200;<br />gt.flags = GT_DEFAULT;<br />gt.codepage = CP_ACP ;<br />gt.lpDefaultChar = NULL; <br />gt.lpUsedDefChar = NULL;<br />SendMessage(EM_GETTEXTEX,(WPARAM)&amp;gt,(LPARAM)text);<br />3)StreamOut(主要用于RTF等格式输出)<br />static DWORD CALLBACK <br />MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)<br />{<br />    CFile* pFile = (CFile*) dwCookie;</p>
		<p>    pFile-&gt;Write(pbBuff, cb);<br />    *pcb = cb;</p>
		<p>    return 0;<br />}</p>
		<p>
				<br />    CFile cFile(TEXT("myfile.rtf"), CFile::modeCreate|CFile::modeWrite);<br />    EDITSTREAM es;<br />    es.dwCookie = (DWORD) &amp;cFile;//设置用例参数,以便回调函数调用<br />    es.pfnCallback = MyStreamOutCallback; <br />    pmyRichEditCtrl-&gt;StreamOut(SF_RTF, es);<br />读入可以此类推，SetWindowText,EM_SETTEXTEX,StreamIn</p>
		<p>f.查找字符串<br />FINDTEXTEX ft;<br />ft.chrg.cpMin = 0;<br />ft.chrg.cpMax = -1;<br />ft.lpstrText = "|";<br />long lPos = FindText(0, &amp;ft);</p>
		<p>如果要继续查找，修改cpMin,如<br />int nCount = 0;<br />do<br />{<br />long lPos = GetRichEditCtrl().FindText(0, &amp;ft);<br />if( -1 == lPos) break;<br />ft.chrg.cpMin = lPos + strlen(ft.lpstrText);<br />++nCount;<br />}while(TRUE);</p>
		<p>g.以Html格式保存<br />目前做法可先转为RTF格式，再通过RTF-to-HTML Converter</p>
		<p>
				<a href="http://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/">http://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/</a>
		</p>
		<p>h.重载OnProtected函数得到对应的消息，如粘贴等<br />void CMYichEditorView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)<br />{<br />ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;</p>
		<p>switch (pEP-&gt;msg) {<br />case WM_KEYDOWN://按键，判断pEP-&gt;wParam<br />case WM_PASTE://粘贴<br />case WM_CUT://剪切<br />case EM_SETCHARFORMAT:<br />default:<br />   break;<br />};</p>
		<p>*pResult = FALSE;<br />}</p>
		<p>三.聊天常用  <br />a.LINK 链接功能<br />1.   LoadLibrary(_T("Riched20.dll"));<br />2. 创建RichEdit2.0控件<br />CreateEx(0, _T("RichEdit20A"), NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP<br />|ES_READONLY|ES_WANTRETURN|ES_MULTILINE,<br />           rect.left, rect.top, cx, cy,<br />   pParentWnd-&gt;m_hWnd, (HMENU)nID, NULL);<br />3. 设定选中的文字为链接显示<br />CHARFORMAT2 cf2;<br />ZeroMemory(&amp;cf2, sizeof(CHARFORMAT2));//<br />cf2.cbSize = sizeof(CHARFORMAT2);<br />cf2.dwMask = CFM_LINK;<br />cf2.dwEffects |= CFE_LINK;<br />m_cRichEdit.SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&amp;cf2);<br />4.支持链接的点击响应<br />m_cRichEdit.SetEventMask(ENM_LINK);<br />5.响应链接的点击EN_LINK</p>
		<p>BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)<br />ON_NOTIFY_REFLECT(EN_LINK,OnURL)<br />END_MESSAGE_MAP()<br />......</p>
		<p>void CMyRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)<br />{<br />TCHAR LinkChar[512];<br />ENLINK *pLink = (ENLINK *)pNmhdr;<br />if (pLink-&gt;msg == WM_LBUTTONUP)<br />{<br />SetSel(penLink-&gt;chrg);//这是链接的文字范围<br />long Res = GetSelText((char *)LinkChar);//这是链接文字<br />                   //后面是你的处理过程<br />                   ......<br />          }<br />}</p>
		<p>b.插入位图<br /><a href="http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/">http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/</a><br /><a href="http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/">http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/</a></p>
		<p>自定义在RichEdit中插入对象的图标<br /><a href="http://www.blogcn.com/user3/jiangsheng/blog/1319738.html">http://www.blogcn.com/user3/jiangsheng/blog/1319738.html</a><br />方法基本同Knowledge Base文章Q220844 HOWTO: Insert a Bitmap Into an RTF Document Using the RichEdit Control<br />只是在最后插入之前调用一下IOleCache::SetData,用一个HGLOBAL作为参数，HGLOBAL里面的数据是一个METAFILEPICT结构，包含自己提供的图片</p>
		<p>使用CRichEditView::InsertFileAsObject就可以插入图像。VC++带有一个例子WordPad。<br />另外可以参考“Insert any HBITMAP (Bitmap) in your RichEdit Control”(<a href="http://www.codeguru.com/richedit/richeditrc.html">http://www.codeguru.com/richedit/richeditrc.html</a>)。</p>
		<p>c.显示GIF动画<br />常用的是通过qq的imageole.dll(也有用Gif89.dll的)<br /><a href="http://www.xiaozhou.net/cooldog/blogview.asp?logID=82">http://www.xiaozhou.net/cooldog/blogview.asp?logID=82</a><br /><a href="http://www.codeproject.com/richedit/AnimatedEmoticon.asp">http://www.codeproject.com/richedit/AnimatedEmoticon.asp</a></p>
		<p>在richedit控件中插入动态GIF (Native C++版)<br /><a href="http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx">http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx</a></p>
		<p>d.IRichEditOleCallback的使用<br /><a href="http://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022">http://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022</a></p>
		<p>类似 MSN 信息发送框的制作(上)<br /><a href="http://www.vckbase.com/document/viewdoc/?id=1087">http://www.vckbase.com/document/viewdoc/?id=1087</a><br />内容包含：实现右键菜单，图片插入，读取/写入RTF格式字符串</p>
		<p>自定义 CRichEditCtrl 控件<br /><a href="http://www.vckbase.com/document/viewdoc/?id=328">http://www.vckbase.com/document/viewdoc/?id=328</a><br />内容包含：鼠标右键消息，消息映射，字体变换</p>
		<p>PS.richedit控件升级到2.0后，先把字体设为楷体，输入汉字没有问题，但输入字母时，字母自动跳转为Arial字体，而1.0却没有这个文题，仍然是用楷体显示字母<br />是一个专门的设计 Dual-font, Smart font apply, 参见 <a href="http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778">http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778</a></p>
		<p>不能显示图片等其他OLE对象</p>
		<p>MFC提供的CRichEditCtrl没有提供直接显示图片等OLE对象的属性或方法设置，但是提供了一个接口SetOLECallback( IRichEditOleCallback* pCallback );<br />要让CRichEditCtrl显示图片，就得在IRichEditOleCallback上下功夫。<br />IRichEditOleCallback是windows中的接口，它的定义如下：<br />ContextSensitiveHelp:<br />    通过该方法通知应用程序它将以上下文关联方式调度帮助。<br />DeleteObject:<br />    通过该方法发出通知：一个对象即将从RichEdit控件中删除<br />GetClipboardData:<br />    通过该方法允许RichEdit的客户端（调用程序）提供自己的粘贴对象<br />GetContextMenu:<br />    通过该方法向应用程序提出通过鼠标右键事件来获取上下文菜单的请求<br />GetDragDropEffect:<br />    通过该方法允许RichEdit的客户端（调用程序）设置拖动操作的效果<br />GetInPlaceContext:<br />   通过该方法提供了应用程序级和文档级接口，以及必要的支持In-place激活的信息<br />GetNewStrorage:<br />    通过该方法存储从粘贴板或超文本流(RTF)中读取的新对象<br />QueryAcceptData:<br />    通过该方法决定在粘贴操作或拖放操作中引入的数据是否可以被接受。<br />QueryInsertObject:<br />    通过该方法向应用程序询问某个对象是否可以被插入<br />ShowContainerUI:<br />    通过该方法告知应用程序是否显示自己的操作界面</p>
		<p>大致了解了IRichEditOleCallback接口后，就应该清楚，要显示图片等ole对象，至少应该实现GetNewStorage方法，因为该方法是存储ole对象的接口方法。</p>
		<p>以下是接口声明的代码：<br />    interface IExRichEditOleCallback;   // forward declaration (see below in this header file)</p>
		<p>   IExRichEditOleCallback* m_pIRichEditOleCallback;<br />   BOOL m_bCallbackSet;<br />   <br />   <br />   interface IExRichEditOleCallback : public IRichEditOleCallback<br />   {<br />   public:<br />       IExRichEditOleCallback();<br />       virtual ~IExRichEditOleCallback();<br />       int m_iNumStorages;<br />       IStorage* pStorage;<br />       DWORD m_dwRef;</p>
		<p>       virtual HRESULT STDMETHODCALLTYPE GetNewStorage(LPSTORAGE* lplpstg);<br />       virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);<br />       virtual ULONG STDMETHODCALLTYPE AddRef();<br />       virtual ULONG STDMETHODCALLTYPE Release();<br />       virtual HRESULT STDMETHODCALLTYPE GetInPlaceContext(LPOLEINPLACEFRAME FAR *lplpFrame,<br />           LPOLEINPLACEUIWINDOW FAR *lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo);<br />        virtual HRESULT STDMETHODCALLTYPE ShowContainerUI(BOOL fShow);<br />        virtual HRESULT STDMETHODCALLTYPE QueryInsertObject(LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp);<br />        virtual HRESULT STDMETHODCALLTYPE DeleteObject(LPOLEOBJECT lpoleobj);<br />        virtual HRESULT STDMETHODCALLTYPE QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT FAR *lpcfFormat,<br />           DWORD reco, BOOL fReally, HGLOBAL hMetaPict);<br />        virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);<br />        virtual HRESULT STDMETHODCALLTYPE GetClipboardData(CHARRANGE FAR *lpchrg, DWORD reco, LPDATAOBJECT FAR *lplpdataobj);<br />        virtual HRESULT STDMETHODCALLTYPE GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect);<br />        virtual HRESULT STDMETHODCALLTYPE GetContextMenu(WORD seltyp, LPOLEOBJECT lpoleobj, CHARRANGE FAR *lpchrg,<br />           HMENU FAR *lphmenu);<br />   };</p>
		<p>-----------------------------------------------------------------------</p>
		<p>注：<br />        m_edit1代表ID为IDC_EDIT1的CEdit控件的control类型的变量<br />        m_richedit1代表ID为IDC_RICHEDIT1的CRichEditCtrl控件的control类型的变量</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />1.设置edit只读属性</p>
		<p>    方法一：<br />                m_edit1.SetReadOnly(TRUE);<br />    方法二：<br />                ::SendMessage(m_edit1.m_hWnd, EM_SETREADONLY, TRUE, 0);</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />2.判断edit中光标状态并得到选中内容(richedit同样适用)</p>
		<p>        int nStart, nEnd;<br />        CString strTemp;</p>
		<p>        m_edit1.GetSel(nStart, nEnd);<br />        if(nStart == nEnd)<br />        {<br />            strTemp.Format(_T("光标在%d"), nStart);<br />            AfxMessageBox(strTemp);<br />        }<br />        else<br />        {<br />            //得到edit选中的内容    <br />            m_edit1.GetWindowText(strTemp);<br />            strTemp = strTemp.Mid(nStart) - strTemp.Mid(nEnd);<br />            AfxMessageBox(strTemp);<br />        }<br />    注：GetSel后，如果nStart和nEnd，表明光标处于某个位置（直观来看就是光标在闪动）；<br />             如果nStart和nEnd不相等，表明用户在edit中选中了一段内容。</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />3.在edit最后添加字符串</p>
		<p>        CString str;<br />        m_edit1.SetSel(-1, -1);<br />        m_edit1.ReplaceSel(str);</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />4.随输入自动滚动到最后一行(richedit同样适用)</p>
		<p>    方法一：（摘自msdn）<br />        // The pointer to my edit.<br />        extern CEdit* pmyEdit;<br />        int nFirstVisible = pmyEdit-&gt;GetFirstVisibleLine();</p>
		<p>        // Scroll the edit control so that the first visible line<br />        // is the first line of text.<br />        if (nFirstVisible &gt; 0)<br />        {<br />            pmyEdit-&gt;LineScroll(-nFirstVisible, 0);<br />        }<br />    方法二：<br />        m_richedit.PostMessage(WM_VSCROLL, SB_BOTTOM, 0);</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />5.如何限制edit输入指定字符</p>
		<p>   可以从CEdit派生一个类，添加WM_CHAR消息映射。下面一个例子实现了限定输入16进制字符的功能。</p>
		<p>   void CMyHexEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) <br />   {<br />        if ( (nChar &gt;= '0' &amp;&amp; nChar &lt;= '9') ||<br />             (nChar &gt;= 'a' &amp;&amp; nChar &lt;= 'f') ||<br />             (nChar &gt;= 'A' &amp;&amp; nChar &lt;= 'F') ||<br />              nChar == VK_BACK || <br />              nChar == VK_DELETE)    //msdn的virtual key<br />       {<br />            CEdit::OnChar(nChar, nRepCnt, nFlags);<br />        }     <br />   }</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />6.如何使用richedit</p>
		<p>    添加AfxInitRichEdit();<br />       CxxxApp::InitInstance()<br />        {<br />             AfxInitRichEdit();<br />          .............<br />       }</p>
		<p>   AfxInitRichEdit()功能：装载 RichEdit 1.0 Control (RICHED32.DLL).</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />7.如何使用richedit2.0 or richedit3.0</p>
		<p>    使用原因：由于RichEdit2.0A自动为宽字符（WideChar），所以它可以解决中文乱码以及一些汉字问题</p>
		<p>    方法一：（msdn上的做法，适用于用VC.NET及以后版本创建的工程）<br />            To update rich edit controls in existing Visual C++ applications to version 2.0,<br />            open the .RC file as text, change the class name of each rich edit control from   "RICHEDIT" to  "RichEdit20a".<br />            Then replace the call to AfxInitRichEdit with AfxInitRichEdit2.<br />    方法二：以对话框为例：<br />       (1)    增加一全局变量 HMODULE hMod;<br />       (2)    在CxxxApp::InitInstance()中添加一句hMod = LoadLibrary(_T("riched20.dll"));<br />              在CxxxApp::ExitInstance()中添加一句FreeLibrary(hMod);<br />       (3)      在对话框上放一个richedit，文本方式打开.rc文件修改该richedit控件的类名"RICHEDIT" to  "RichEdit20a".<br />       (4)      在对话框头文件添加 CRichEditCtrl m_richedit;<br />              在OnInitDialog中添加 m_richedit.SubclassDlgItem(IDC_RICHEDIT1, this);</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />8.改变richedit指定区域的颜色及字体</p>
		<p>        CHARFORMAT cf;<br />        ZeroMemory(&amp;cf, sizeof(CHARFORMAT));<br />        cf.cbSize = sizeof(CHARFORMAT);<br />        cf.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE |<br />                            CFM_ITALIC | CFM_SIZE | CFM_UNDERLINE;<br />        cf.dwEffects = 0;<br />        cf.yHeight = 12*12;//文字高度<br />        cf.crTextColor = RGB(200, 100, 255); //文字颜色<br />        strcpy(cf.szFaceName ,_T("隶书"));//设置字体<br />    <br />        m_richedit1.SetSel(1, 5); //设置处理区域<br />        m_richedit1.SetSelectionCharFormat(cf);</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />9.设置行间距（只适用于richedit2.0）</p>
		<p>        PARAFORMAT2 pf;<br />        pf2.cbSize = sizeof(PARAFORMAT2);<br />        pf2.dwMask = PFM_LINESPACING | PFM_SPACEAFTER;<br />        pf2.dyLineSpacing = 200;<br />        pf2.bLineSpacingRule  = 4;<br />        m_richedit.SetParaFormat(pf2);</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />10.richedit插入位图</p>
		<p>Q220844：How to insert a bitmap into an RTF document using the RichEdit control in Visual C++ 6.0<br /><a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;220844">http://support.microsoft.com/default.aspx?scid=kb;en-us;220844</a><br /><a href="http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/">http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/</a><br /><a href="http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/">http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/</a></p>
		<p>
				<br />--------------------------------------------------------------------------------<br />11.richedit插入gif动画</p>
		<p>
				<a href="http://www.codeproject.com/richedit/AnimatedEmoticon.asp">http://www.codeproject.com/richedit/AnimatedEmoticon.asp</a>
		</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />12.richedit嵌入ole对象</p>
		<p>
				<a href="http://support.microsoft.com/kb/141549/en-us">http://support.microsoft.com/kb/141549/en-us</a>
		</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />13.使richedit选中内容只读</p>
		<p>
				<a href="http://www.codeguru.com/cpp/controls/richedit/article.php/c2401/">http://www.codeguru.com/cpp/controls/richedit/article.php/c2401/</a>
		</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />14.打印richedit</p>
		<p>
				<a href="http://www.protext.com/MFC/RichEdit3.htm">http://www.protext.com/MFC/RichEdit3.htm</a>
		</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />15.richeidt用于聊天消息窗口</p>
		<p>
				<a href="http://www.vckbase.com/document/viewdoc/?id=1087">http://www.vckbase.com/document/viewdoc/?id=1087</a>
				<br />
				<a href="http://www.codeproject.com/richedit/chatrichedit.asp">http://www.codeproject.com/richedit/chatrichedit.asp</a>
				<br />
				<a href="http://www.codeguru.com/Cpp/controls/richedit/article.php/c2395/">http://www.codeguru.com/Cpp/controls/richedit/article.php/c2395/</a>
		</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />16.解决richedit的EN_SETFOCUS和EN_KILLFOCUS无响应的问题</p>
		<p>
				<a href="http://support.microsoft.com/kb/181664/en-us">http://support.microsoft.com/kb/181664/en-us</a>
		</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />17.richedit拼写检查</p>
		<p>
				<a href="http://www.codeproject.com/com/AutoSpellCheck.asp">http://www.codeproject.com/com/AutoSpellCheck.asp</a>
		</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />18.改变edit背景色</p>
		<p>Q117778：How to change the background color of an MFC edit control<br /><a href="http://support.microsoft.com/kb/117778/en-us">http://support.microsoft.com/kb/117778/en-us</a></p>
		<p>
				<br />--------------------------------------------------------------------------------<br />19.当edit控件的父窗口属性是带标题栏WS_CAPTION和子窗口WS_CHILD时，不能设置焦点SetFocus</p>
		<p>Q230587：PRB: Can't Set Focus to an Edit Control When its Parent Is an Inactive Captioned Child Window</p>
		<p>
				<a href="http://support.microsoft.com/kb/230587/en-us">http://support.microsoft.com/kb/230587/en-us</a>
		</p>
		<p>--------------------------------------------------------------------------------<br />20. 在Edit中回车时，会退出对话框 </p>
		<p>选中Edit的风格Want Return。</p>
		<p>MSDN的解释如下：<br />ES_WANTRETURN   Specifies that a carriage return be inserted when the user presses the ENTER key while entering text into a multiple-line edit control in a dialog box. Without this style, pressing the ENTER key has the same effect as pressing the dialog box's default pushbutton. This style has no effect on a single-line edit control.</p>
		<p>
				<br />--------------------------------------------------------------------------------<br />21. 动态创建的edit没有边框的问题</p>
		<p>    m_edit.Create(....);<br />    m_edit.ModifyStyleEx(0, WS_EX_CLIENTEDGE, SWP_DRAWFRAME);</p>
		<p>--------------------------------------------------------------------------------<br />22. 一个能显示RTF，ole（包括gif， wmv，excel ，ppt）的例子</p>
		<p>
				<a href="http://www.codeproject.com/richedit/COleRichEditCtrl.asp">http://www.codeproject.com/richedit/COleRichEditCtrl.asp</a>
		</p>
		<p>
				<br />本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/qsycn/archive/2009/11/10/4793461.aspx">http://blog.csdn.net/qsycn/archive/2009/11/10/4793461.aspx</a></p>
		<p> </p>
		<p>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/abcpanpeng/archive/2010/04/21/5509680.aspx">http://blog.csdn.net/abcpanpeng/archive/2010/04/21/5509680.aspx</a></p>
<img src ="http://www.cppblog.com/kyelin/aggbug/132300.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kyelin/" target="_blank">我风</a> 2010-11-03 15:51 <a href="http://www.cppblog.com/kyelin/archive/2010/11/03/132300.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个xp系统dll说明网站</title><link>http://www.cppblog.com/kyelin/archive/2010/10/29/131756.html</link><dc:creator>我风</dc:creator><author>我风</author><pubDate>Fri, 29 Oct 2010 07:33:00 GMT</pubDate><guid>http://www.cppblog.com/kyelin/archive/2010/10/29/131756.html</guid><wfw:comment>http://www.cppblog.com/kyelin/comments/131756.html</wfw:comment><comments>http://www.cppblog.com/kyelin/archive/2010/10/29/131756.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kyelin/comments/commentRss/131756.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kyelin/services/trackbacks/131756.html</trackback:ping><description><![CDATA[
		<a href="http://xpdll.nirsoft.net/">
				<br />http://xpdll.nirsoft.net/</a>
<img src ="http://www.cppblog.com/kyelin/aggbug/131756.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kyelin/" target="_blank">我风</a> 2010-10-29 15:33 <a href="http://www.cppblog.com/kyelin/archive/2010/10/29/131756.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dump文件生成(转)</title><link>http://www.cppblog.com/kyelin/archive/2010/10/13/129758.html</link><dc:creator>我风</dc:creator><author>我风</author><pubDate>Wed, 13 Oct 2010 08:35:00 GMT</pubDate><guid>http://www.cppblog.com/kyelin/archive/2010/10/13/129758.html</guid><wfw:comment>http://www.cppblog.com/kyelin/comments/129758.html</wfw:comment><comments>http://www.cppblog.com/kyelin/archive/2010/10/13/129758.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kyelin/comments/commentRss/129758.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kyelin/services/trackbacks/129758.html</trackback:ping><description><![CDATA[
		<p>生成minidump目的是保存程序异常时的调用栈信息，便于寻找问题原因。</p>
		<p>1, 添加下面得函数，</p>
		<p>#include &lt;dbghelp.h&gt;<br />#include &lt;shellapi.h&gt;<br />#include &lt;shlobj.h&gt;</p>
		<p>LONG WINAPI GenerateDump(struct _EXCEPTION_POINTERS *pExceptionPointers)<br />{<br />LONG ret = EXCEPTION_EXECUTE_HANDLER;<br />BOOL bMiniDumpSuccessful;<br />TCHAR szPath[MAX_PATH];<br />TCHAR szFileName[MAX_PATH];<br />TCHAR* szAppName = TEXT(“AppName”);<br />TCHAR* szVersion = TEXT(“v1.0″);<br />DWORD dwBufferSize = MAX_PATH;<br />HANDLE hDumpFile;<br />SYSTEMTIME stLocalTime;<br />MINIDUMP_EXCEPTION_INFORMATION ExpParam;</p>
		<p>GetLocalTime( &amp;stLocalTime );<br />GetTempPath( dwBufferSize, szPath );</p>
		<p>_stprintf( szFileName, TEXT(“%s%s”), szPath, szAppName );<br />CreateDirectory( szFileName, NULL );</p>
		<p>_stprintf( szFileName, TEXT(“c:\\aaaa.dmp”));<br />hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE,<br />FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);</p>
		<p>ExpParam.ThreadId = GetCurrentThreadId();<br />ExpParam.ExceptionPointers = pExceptionPointers;<br />ExpParam.ClientPointers = TRUE;</p>
		<p>bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),<br />hDumpFile, MiniDumpWithDataSegs, &amp;ExpParam, NULL, NULL);</p>
		<p>int i = GetLastError();<br />HRESULT hr = HRESULT_FROM_WIN32(i);</p>
		<p>return ret;<br />}</p>
		<p>2，在project setting中加入dbghelp.lib作为library的input，这是MiniDumpWriteDump需要的。<strong>在Debug Information Format</strong>设置<strong>Program Database (/Zi)</strong>。设置<strong>Generate Debug Info</strong>为<strong>Yes (/DEBUG)。在</strong><strong>Optimization</strong>设置<strong>References</strong>为 <strong>Eliminate Unreferenced Data (/OPT:REF)</strong>。设置 <strong>Enable COMDAT Folding</strong>为 <strong>Remove Redundant COMDATs (/OPT:ICF)</strong>。后面两项设置可以大大缩小exe文件大小。</p>
		<p>3，使用如下：</p>
		<p>void SomeFunction()<br />{<br />int *pBadPtr = NULL;<br />*pBadPtr = 0;<br />}<br />void Ctest2Dlg::OnBnClickedButton1()<br />{<br />__try<br />{<br />SomeFunction();<br />}<br />__except(GenerateDump(GetExceptionInformation()))<br />{<br />}<br />}</p>
		<p>4，使用windbg打开dmp文件，就可以看到出错时的call stack了。</p>
		<p>
				<strong>几点要注意的</strong>：1）网上有文章介绍使用 SetUnhandledExceptionFilter设置异常过滤，保证出现异常时能调用minidump函数，但是这有些问题，这个函数会导致debugger失效，而且好像跟drwatson有些冲突，感觉用起来比较危险。在程序的关键部分加入__try – __exception，这样缩小捕捉范围，应该就足够用了。2）必须是用__try – __exception这样的形式，才能保证GetExceptionInformation()能正常使用。3）MiniDumpWithDataSegs这个参数我试着换成另外几个，好像都不好用。返回值都是0，经过解析lasterror都是E_INVALIDARG，奇怪。</p>
		<p>update: 关于使用windbg</p>
		<p>windbg下载地址在这里<a href="http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx">http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx</a></p>
		<p>下载安装最新版本即可，我没有搞清楚的一点是必须要设置windows的symbol目录，否则光有pdb是没法看到调用栈信息的。</p>
		<p>使用windbg过程如下：安装。然后打开菜单file-&gt; symbol file path，添加如下</p>
		<p>srv*c:\symbol_local*http://msdl.microsoft.com/download/symbols;c:\debug</p>
		<p>其中srv*c:\symbol_local*http://msdl.microsoft.com/download/symbols;指明从网上下载操作系统使用的symbol存放到c盘symbol_local目录，另外程序的symbol（pdb文件）可以放在c盘debug目录下。</p>
		<p>windbg会显示一段时间busy或者retrieving..，然后就可以看到详细的dump信息了</p>
<img src ="http://www.cppblog.com/kyelin/aggbug/129758.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kyelin/" target="_blank">我风</a> 2010-10-13 16:35 <a href="http://www.cppblog.com/kyelin/archive/2010/10/13/129758.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC++ SMTP协议电子邮件传送剖析(转)</title><link>http://www.cppblog.com/kyelin/archive/2010/10/11/129427.html</link><dc:creator>我风</dc:creator><author>我风</author><pubDate>Mon, 11 Oct 2010 06:05:00 GMT</pubDate><guid>http://www.cppblog.com/kyelin/archive/2010/10/11/129427.html</guid><wfw:comment>http://www.cppblog.com/kyelin/comments/129427.html</wfw:comment><comments>http://www.cppblog.com/kyelin/archive/2010/10/11/129427.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kyelin/comments/commentRss/129427.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kyelin/services/trackbacks/129427.html</trackback:ping><description><![CDATA[要：本文介绍了一种采用SMTP协议规范并通过直接使用SMTP协议命令而在程序中实现电子邮件传送的方法。并在VC++开发环境下给出了部分关键的实现代码。<br /><br />　　<b><font color="#ac000">前言</font></b><br /><br />　　电子邮件服务作为Internet上应用最多和最广的服务项目得到了非常广泛的应用，在网络应用中也起到非常重要的作用。如同其他的网络服务，电子邮件系统也有其使用的传输协议，包括SMTP（Simple Mail Transfer Protocol，简单邮件传输协议）、POP（Post Office Protocol，邮局协议）和IMAP（Internet Message Access Protocal，消息访问协议）等，这些协议应用于电子邮件的发送和接收。一些邮件处理软件如OutLook Express和FoxMail等就是按照SMTP和POP3 协议结合Windows Sockets套接字进行设计来收发邮件的。本文以SMTP协议为研究对象，在Visual C++ 6.0编程环境下按照SMTP协议通过套接字发送SMTP命令，接收并处理邮件服务器的反馈信息，从而实现对电子邮件的发送。<br /><br />　　<b><font color="#ac000">SMTP协议的通讯模型和会话流程</font></b><br /><br />　　<b>SMTP协议通讯模型</b><br /><br />　　SMTP协议是TCP/IP协议族中的一员，主要对如何将电子邮件从发送方地址传送到接收方地址，也即是对传输的规则做了规定。SMTP协议的通信模型并不复杂，主要工作集中在发送SMTP和接收SMTP上：首先针对用户发出的邮件请求，由发送SMTP建立一条连接到接收SMTP的双工通讯链路，这里的接收SMTP是相对于发送SMTP而言的，实际上它既可以是最终的接收者也可以是中间传送者。发送SMTP负责向接收SMTP发送SMTP命令，而接收SMTP则负责接收并反馈应答。可大致用下面的通讯模型示意图来表示：<br /><br /><table width="100%"><tbody><tr><td><img height="191" src="http://www.5dmail.net/pic/2005/5/31/1311001.gif" width="393" /></td></tr></tbody></table><br />　　<b>SMTP协议的命令和应答</b><br /><br />　　从前面的通讯模型可以看出SMTP协议在发送SMTP和接收SMTP之间的会话是靠发送SMTP的 SMTP命令和接收SMTP反馈的应答来完成的。在通讯链路建立后，发送SMTP发送MAIL命令指令邮件发送者，若接收SMTP此时可以接收邮件则作出OK的应答，然后发送SMTP继续发出RCPT命令以确认邮件是否收到，如果接收到就作出OK的应答，否则就发出拒绝接收应答，但这并不会对整个邮件操作造成影响。双方如此反复多次，直至邮件处理完毕。SMTP协议共包含10个SMTP命令，列表如下：<br /><br /><table cellspacing="0" width="600" align="center" border="1"><tbody><tr><td width="250">SMTP命令</td><td width="340">命令说明</td></tr><tr><td width="250">HELLO ＜domain＞ ＜CRLF＞</td><td width="340">识别发送方到接收SMTP的一个HELLO命令</td></tr><tr><td width="250">MAIL FROM:＜reverse-path＞＜CRLF＞ </td><td width="340">＜reverse-path＞为发送者地址。此命令告诉接收方一个新邮件发送的开始，并对所有的状态和缓冲区进行初始化。此命令开始一个邮件传输处理，最终完成将邮件数据传送到一个或多个邮箱中。</td></tr><tr><td width="250">RCPT TO:＜forward-path＞＜CRLF＞ </td><td width="340">＜forward-path＞标识各个邮件接收者的地址</td></tr><tr><td width="250">DATA ＜CRLF＞ </td><td width="340"><br />接收SMTP将把其后的行为看作邮件数据去处理，以＜CRLF＞.＜CRLF＞标识数据的结尾。</td></tr><tr><td width="250">REST ＜CRLF＞</td><td width="340">退出/复位当前的邮件传输</td></tr><tr><td width="250">NOOP ＜CRLF＞</td><td width="340">要求接收SMTP仅做OK应答。（用于测试）</td></tr><tr><td width="250">QUIT ＜CRLF＞</td><td width="340">要求接收SMTP返回一个OK应答并关闭传输。</td></tr><tr><td width="250">VRFY ＜string＞ ＜CRLF＞ </td><td width="340">验证指定的邮箱是否存在，由于安全因素，服务器多禁止此命令。</td></tr><tr><td width="250">EXPN ＜string＞ ＜CRLF＞ </td><td width="340">验证给定的邮箱列表是否存在，扩充邮箱列表，也常禁止使用。</td></tr><tr><td width="250">HELP ＜CRLF＞</td><td width="340">查询服务器支持什么命令</td></tr></tbody></table><br />注：＜CRLF＞为回车、换行，ASCII码分别为13、10（十进制）。<br /><br />　　SMTP协议的每一个命令都会返回一个应答码，应答码的每一个数字都是有特定含义的，如第一位数字为2时表示命令成功；为5表失败；3表没有完成。一些较复杂的邮件程序利用该特点，首先检查应答码的首数字，并根据其值来决定下一步的动作。下面将SMTP的应答码列表如下：<br /><br /><table cellspacing="0" width="600" align="center" border="1"><tbody><tr><td>应答码</td><td>说明</td></tr><tr><td>501 </td><td>参数格式错误</td></tr><tr><td>502 </td><td>命令不可实现</td></tr><tr><td>503 </td><td>错误的命令序列</td></tr><tr><td>504 </td><td>命令参数不可实现</td></tr><tr><td>211 </td><td>系统状态或系统帮助响应</td></tr><tr><td>214 </td><td>帮助信息</td></tr><tr><td>220</td><td>＜domain＞服务就绪</td></tr><tr><td>221 </td><td>＜domain＞服务关闭</td></tr><tr><td>421 </td><td>＜domain＞服务未就绪，关闭传输信道</td></tr><tr><td>250</td><td>要求的邮件操作完成</td></tr><tr><td>251 </td><td>用户非本地，将转发向＜forward-path＞</td></tr><tr><td>450 </td><td>要求的邮件操作未完成，邮箱不可用</td></tr><tr><td>550 </td><td>要求的邮件操作未完成，邮箱不可用</td></tr><tr><td>451 </td><td>放弃要求的操作；处理过程中出错</td></tr><tr><td>551 </td><td>用户非本地，请尝试＜forward-path＞ </td></tr><tr><td>452 </td><td>系统存储不足，要求的操作未执行</td></tr><tr><td>552 </td><td>过量的存储分配，要求的操作未执行</td></tr><tr><td>553 </td><td>邮箱名不可用，要求的操作未执行</td></tr><tr><td>354 </td><td>开始邮件输入，以"."结束</td></tr><tr><td>554 </td><td>操作失败</td></tr></tbody></table><span class="txt">　　<b><font color="#ac000">在应用程序中使用SMTP协议</font></b><br /><br />　　<b>SMTP协议的会话流程</b><br /><br />　　在进行程序设计之前有必要弄清SMTP协议的会话流程，其实前面介绍的内容已经可以大致勾勒出用SMTP发送邮件的框架了，对于一次普通的邮件发送，其过程大致为：先建立TCP连接，随后客户端发出HELLO命令以标识发件人自己的身份，并继续由客户端发送MAIL命令，如服务器应答为"OK"，可继续发送RCPT命令来标识电子邮件的收件人，在这里可以有多个RCPT行，而服务器端则表示是否愿意为收件人接受该邮件。在双方协商结束后，用命令DATA将邮件发送出去，其中对表示结束的"."也一并发送出去。随后结束本次发送过程，以QUIT命令退出。下面通过一个实例，从langrui@sohu.com发送邮件到renping@sina.com来更详细直观地描述此会话流程：<br /><br /><table width="100%" bgcolor="#ffffff"><tbody><tr><td>R:220 sina.com Simple Mail Transfer Service Ready<br />S:HELLO sohu.com<br />R:250 sina.com<br />S:MAIL FROM:＜langrui@sohu.com＞<br />R:250 OK<br />S:RCPT TO:＜renping@sina.com＞<br />R:250 OK<br />S:DATA<br />R:354 Start mail input;end with "＜CRLF＞.＜CRLF＞"<br />S:……<br />R:250 OK<br />S:QUIT<br />R:221 sina.com Service closing transmission channel</td></tr></tbody></table><br />　　<b>邮件的格式化</b><br /><br />　　由于电子邮件结构上的特殊性，在传输时是不能当作简单的文本来直接处理的，而必须按照一定的格式对邮件头和邮件体进行格式化处理之后才可以被发送。需要进行格式化的部分主要有：发件人地址、收件人地址、主题和发送日期等。在RFC文档的RFC 822里对邮件的格式化有详尽的说明，有关详情请参阅该文档。下面通过VC++6.0按照RFC 822文档规定将格式化邮件的部分编写如下（部分代码）：<br /><br /><table width="100%" bgcolor="#ffffff"><tbody><tr><td>//邮件头准备<br />strTemp = _T( "From: " ) + m_strFrom; file://发件人地址<br />add_header_line( (LPCTSTR)strTemp );<br />strTemp = _T( "To: " ) + m_strTo; file://收件人地址<br />add_header_line( (LPCTSTR)strTemp );<br />m_tDateTime = m_tDateTime.GetCurrentTime();//发送时间<br />strTemp = _T( "Data: " );<br />strTemp += m_tDateTime.Format( "%a, %d %b %y %H:%M:%S %Z" );<br />add_header_line( (LPCTSTR)strTemp );<br />strTemp = _T( "Subject: " ) + m_strSubject; file://主题<br />add_header_line( (LPCTSTR)strTemp );<br />file://邮件头结束<br />m_strHeader += _T( "\r\n" );<br />file://邮件体准备<br />if( m_strBody.Right( 2 ) != _T( "\r\n" ) ) file://确认最后以回车换行结束<br />m_strBody += _T( "\r\n" ); </td></tr></tbody></table><br />　　其中add_header_line(LPCTSTR szHeaderLine)函数用于把szHeaderLine指向的字串追加到m_strHeader后面。其中，格式化后的邮件头保存在m_strHeader里，格式化后的邮件体保存在m_strBody中。<br /><br />　　<b>由Socket套接字为SMTP提供网络通讯基础</b><br /><br />　　许多网络程序都是采用Socket套接字实现的，对于一些标准的网络协议如HTTP、FTP和SMTP等协议的编程也是基于套接字程序的，只是端口号不再是随意设定而要由协议来指定，比如HTTP端口在80、FTP是21，而SMTP则是25。Socket只是提供在指定的端口上同指定的服务器从事网络上的通讯能力，至于客户和服务器之间是如何通讯的则由网络协议来规定，这对于套接字是完全透明的。因此可以使用Socket套接字为程序提供网络通讯的能力，而对于网络通讯连路建立好之后采取什么样的通讯应答则要按SMTP协议的规定去执行了。Socket套接字网络编程方面的文章资料非常丰富，限于本文篇幅，在此不再赘述，有关详情请参阅相关文档。为简便起见，没有采用编写较复杂的Windows Sockets API进行编程，而是使用经过较好封装的MFC 的CSocket类。在正式使用套接字之前，也要先用AfxSocketInit()函数对套接字进行初始化，然后用Create()创建套接字对象，并由该套接字通过Connect（）建立同邮件服务器的连接。如果一切正常，再后续的工作中就是遵循SMTP协议的约定来使用Send（）、Receive()函数来发送SMTP命令和接收邮件服务器发来的应答码以完成对邮件的传送。<br /><br />　　<b>SMTP会话应答的实现</b><br /><br />　　在同邮件服务器建立好链路连接后就可以按前面介绍过的会话流程进行程序设计了，对于SMTP命令的发送，可按命令格式将其组帧完毕后用CSocket类的Send()函数将其发送到服务器，并通过CSocket类的Receive()函数接收从邮件服务器发来的应答码，并根据SMTP协议的应答码表对其做出响应的处理。下面是用于接收应答码的函数get_response()的部分实现代码：<br /><br /><table width="100%" bgcolor="#ffffff"><tbody><tr><td>BOOL CSMTP::get_response( UINT response_expected )//输入参数为希望的应答码<br />{<br />……<br />// m_wsSMTPServer为CSocket的类对象，调用Receive()将应答码接收到缓存<br />// response_buf中<br />m_wsSMTPServer.Receive( response_buf, RESPONSE_BUFFER_SIZE )<br />sResponse = response_buf;<br />sscanf( (LPCTSTR)sResponse.Left( 3 ), _T( "%d" ), &amp;response );<br />pResp = &amp;response_table[ response_expected ];<br />file://检验收到的应答码是否是所希望得到的<br />if( response != pResp-＞nResponse )<br />{<br />……//不相等的话进行错误处理<br />return FALSE;<br />}<br />return TRUE;<br />}</td></tr></tbody></table><br />　　会话的各个部分比较类似，都是命令--应答方式，而且均成对出现，下面是本文的重点也是实现的关键部分--在程序控制下完成对SMTP命令的格式化以及对命令的发送和对邮件服务器应答码的检验处理：<br /><br /><table width="100%" bgcolor="#ffffff"><tbody><tr><td>//格式化并发送HELLO命令，并接收、验证服务器应答码<br />gethostname( local_host, 80 );<br />sHello.Format( _T( "HELO %s\r\n" ), local_host );<br />m_wsSMTPServer.Send( (LPCTSTR)sHello, sHello.GetLength() );<br />if( !get_response( GENERIC_SUCCESS ) ) file://检验应答码是否为250<br />{<br />……<br />return FALSE;<br />}<br />file://格式化并发送MAIL命令，并接收、验证服务器应答码<br />sFrom.Format( _T( "MAIL From: ＜%s＞\r\n" ), (LPCTSTR)msg-＞m_strFrom );<br />m_wsSMTPServer.Send( (LPCTSTR)sFrom, sFrom.GetLength() );<br />if( !get_response( GENERIC_SUCCESS ) ) file://检验应答码是否为250<br />return FALSE;<br />file://格式化并发送RCPT命令，并接收、验证服务器应答码<br />sEmail=(LPCTSTR)msg-＞m_strTo;<br />sTo.Format( _T( "RCPT TO: ＜%s＞\r\n" ), (LPCTSTR)sEmail );<br />m_wsSMTPServer.Send( (LPCTSTR)sTo, sTo.GetLength() );<br />if(!get_response( GENERIC_SUCCESS )) file://检验应答码是否为250<br />return FALSE;<br />file://格式化并发送DATA命令，并接收、验证服务器应答码<br />sTemp = _T( "DATA\r\n" );<br />m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );<br />if( !get_response( DATA_SUCCESS ) ) file://检验应答码是否为354<br />return FALSE;<br />file://发送根据RFC 822文档规定格式化过的邮件头<br />m_wsSMTPServer.Send( (LPCTSTR)msg-＞m_strHeader, msg-＞m_strHeader.GetLength() );<br />……<br />file://发送根据RFC 822文档规定格式化过的邮件体<br />sTemp = msg-＞m_strBody;<br />if( sTemp.Left( 3 ) == _T( ".\r\n" ) )<br />sTemp = _T( "." ) + sTemp;<br />while( (nPos = sTemp.Find( szBad )) ＞ -1 )<br />{<br />sCooked = sTemp.Mid( nStart, nPos );<br />sCooked += szGood;<br />sTemp = sCooked + sTemp.Right( sTemp.GetLength() - (nPos + nBadLength) );<br />}<br />m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );<br />file://发送内容数据结束标志"＜CRLF＞.＜CRLF＞"，并检验返回应答码<br />sTemp = _T( "\r\n.\r\n" );<br />m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );<br />if( !get_response( GENERIC_SUCCESS ) )// 检验应答码是否为250<br />return FALSE;</td></tr></tbody></table><br />　　到此为止，已基本在程序中体现出了SMTP协议的会话流程，能在Socket套接字所提供的网络通讯能力基础之上实现以SMTP命令和SMTP应答码为基本会话内容的通讯交互过程，从而最终实现SMTP协议对电子邮件的发送。<br /><br />　　<b><font color="#ac000">结论</font></b><br /><br />　　电子邮件类软件作为Internet上的应用软件，其设计开发必须符合Internet上成熟的技术规范（如RFC文档系列规范）和相关协议（如POP、SMTP、IMAP以及LDAP等）。只有在遵循了上述规范和协议的基础上进行编程才能真正实现邮件类软件产品和服务的开放性和标准化。本文着重对SMTP协议及其在VC++编程中的应用做了介绍，并按照SMTP协议对电子邮件的发送进行了开放性和标准性较好的程序设计。本文所述程序在Windows 98下，由Microsoft Visual C++ 6.0编译通过。</span>, <img src ="http://www.cppblog.com/kyelin/aggbug/129427.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kyelin/" target="_blank">我风</a> 2010-10-11 14:05 <a href="http://www.cppblog.com/kyelin/archive/2010/10/11/129427.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>