<?xml version="1.0" encoding="utf-8" ?>
<!-- generator="FEEDCREATOR_VERSION" -->
<rss version="2.0" xmlns:sns="http://blog.sina.com.cn/sns">
    <channel>
        <title>Learning and Debuging</title>
        <description></description>
        <link>http://blog.sina.com.cn/zhlidol</link>
        <lastBuildDate>Sun, 06 Jul 2008 16:07:39 GMT+8</lastBuildDate>
        <generator>FEEDCREATOR_VERSION</generator>
        <language>zh-cn</language>
        <copyright>Copyright 1996 - 2008 SINA Inc. All Rights Reserved.</copyright>
        <pubDate>Sun, 06 Jul 2008 08:07:39 GMT+8</pubDate>
        <item>
            <title>VC字符串转换</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901007me0.html</link>
            <description><![CDATA[<div><font STYLE="FONT-SIZE: 16px">&nbsp;zz from
Internet</FONT></DIV>
<div>
<div CLASS="cnt">
<p><font STYLE="FONT-SIZE: 16px">一、BSTR、LPSTR和LPWSTR&nbsp;<br/>
　　&nbsp;在Visual&nbsp;C++.NET的所有编程方式中，我们常常要用到这样的一些基本字符串类型，如BSTR、LPSTR和LPWSTR等。之所以出现类似上述的这些数据类型，是因为不同编程语言之间的数据交换以及对ANSI、Unicode和多字节字符集(MBCS)的支持。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　那么什么是BSTR、LPSTR以及LPWSTR呢？</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　BSTR(Basic&nbsp;STRing，Basic字符串)是一个OLECHAR*类型的Unicode字符串。它被描述成一个与自动化相兼容的类型。由于操作系统提供相应的API函数(如SysAllocString)来管理它以及一些默认的调度代码，因此BSTR实际上就是一个COM字符串，但它却在自动化技术以外的多种场合下得到广泛使用。图1描述了BSTR的结构，其中DWORD值是字符串中实际所占用的字节数，且它的值是字符串中Unicode字符的两倍。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　LPSTR和LPWSTR是Win32和VC++所使用的一种字符串数据类型。LPSTR被定义成是一个指向以NULL(‘\0’)结尾的8位ANSI字符数组指针，而LPWSTR是一个指向以NULL结尾的16位双字节字符数组指针。在VC++中，还有类似的字符串类型，如LPTSTR、LPCTSTR等，它们的含义如图2所示。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　例如，LPCTSTR是指“long&nbsp;pointer&nbsp;to&nbsp;a&nbsp;constant&nbsp;generic&nbsp;string”，表示“一个指向一般字符串常量的长指针类型”，与C/C++的const&nbsp;char*相映射，而LPTSTR映射为&nbsp;char*。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　一般地，还有下列类型定义：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">#ifdef&nbsp;UNICODE&nbsp;<br/>

　&nbsp;typedef&nbsp;LPWSTR&nbsp;LPTSTR;<br/>

　&nbsp;typedef&nbsp;LPCWSTR&nbsp;LPCTSTR;&nbsp;<br/>

#else&nbsp;<br/>
　&nbsp;typedef&nbsp;LPSTR&nbsp;LPTSTR;&nbsp;<br/>

　&nbsp;typedef&nbsp;LPCSTR&nbsp;LPCTSTR;&nbsp;<br/>

#endif</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">二、CString、CStringA&nbsp;和&nbsp;CStringW</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　Visual&nbsp;C++.NET中将CStringT作为ATL和MFC的共享的“一般”字符串类，它有CString、CStringA和CStringW三种形式，分别操作不同字符类型的字符串。这些字符类型是TCHAR、char和wchar_t。TCHAR在Unicode平台中等同于WCHAR(16位Unicode字符)，在ANSI中等价于char。wchar_t通常定义为unsigned&nbsp;short。由于CString在MFC应用程序中经常用到，这里不再重复。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">三、VARIANT、COleVariant&nbsp;和_variant_t</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　在OLE、ActiveX和COM中，VARIANT数据类型提供了一种非常有效的机制，由于它既包含了数据本身，也包含了数据的类型，因而它可以实现各种不同的自动化数据的传输。下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">struct&nbsp;tagVARIANT&nbsp;{<br/>

　&nbsp;VARTYPE&nbsp;vt;<br/>
　&nbsp;union&nbsp;{&nbsp;<br/>

　　&nbsp;short&nbsp;iVal;&nbsp;//&nbsp;VT_I2.&nbsp;<br/>

　　&nbsp;long&nbsp;lVal;&nbsp;//&nbsp;VT_I4.&nbsp;<br/>

　　&nbsp;float&nbsp;fltVal;&nbsp;//&nbsp;VT_R4.&nbsp;<br/>

　　&nbsp;double&nbsp;dblVal;&nbsp;//&nbsp;VT_R8.&nbsp;<br/>

　　&nbsp;DATE&nbsp;date;&nbsp;//&nbsp;VT_DATE.&nbsp;<br/>

　　&nbsp;BSTR&nbsp;bstrVal;&nbsp;//&nbsp;VT_BSTR.&nbsp;<br/>

　　&nbsp;…&nbsp;<br/>
　　&nbsp;short&nbsp;*&nbsp;piVal;&nbsp;//&nbsp;VT_BYREF|VT_I2.&nbsp;<br/>

　　&nbsp;long&nbsp;*&nbsp;plVal;&nbsp;//&nbsp;VT_BYREF|VT_I4.&nbsp;<br/>

　　&nbsp;float&nbsp;*&nbsp;pfltVal;&nbsp;//&nbsp;VT_BYREF|VT_R4.&nbsp;<br/>

　　&nbsp;double&nbsp;*&nbsp;pdblVal;&nbsp;//&nbsp;VT_BYREF|VT_R8.&nbsp;<br/>

　　&nbsp;DATE&nbsp;*&nbsp;pdate;&nbsp;//&nbsp;VT_BYREF|VT_DATE.&nbsp;<br/>

　　&nbsp;BSTR&nbsp;*&nbsp;pbstrVal;&nbsp;//&nbsp;VT_BYREF|VT_BSTR.&nbsp;<br/>

　&nbsp;};&nbsp;<br/>
};&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　显然，VARIANT类型是一个C结构，它包含了一个类型成员vt、一些保留字节以及一个大的union类型。例如，如果vt为VT_I2，那么我们可以从iVal中读出VARIANT的值。同样，当给一个VARIANT变量赋值时，也要先指明其类型。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">VARIANT&nbsp;va;<br/>
::&nbsp;VariantInit(&amp;va);&nbsp;//&nbsp;初始化<br/>

int&nbsp;a&nbsp;=&nbsp;2002;<br/>

va.vt&nbsp;=&nbsp;VT_I4;&nbsp;//&nbsp;指明long数据类型<br/>

va.lVal&nbsp;=&nbsp;a;&nbsp;//&nbsp;赋值&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　为了方便处理VARIANT类型的变量，Windows还提供了这样一些非常有用的函数：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　VariantInit&nbsp;——&nbsp;将变量初始化为VT_EMPTY；</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　VariantClear&nbsp;——&nbsp;消除并初始化VARIANT；</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　VariantChangeType&nbsp;——&nbsp;改变VARIANT的类型；</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　VariantCopy&nbsp;——&nbsp;释放与目标VARIANT相连的内存并复制源VARIANT。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　COleVariant类是对VARIANT结构的封装。它的构造函数具有极为强大大的功能，当对象构造时首先调用VariantInit进行初始化，然后根据参数中的标准类型调用相应的构造函数，并使用VariantCopy进行转换赋值操作，当VARIANT对象不在有效范围时，它的析构函数就会被自动调用，由于析构函数调用了VariantClear，因而相应的内存就会被自动清除。除此之外，COleVariant的赋值操作符在与VARIANT类型转换中为我们提供极大的方便。例如下面的代码：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">COleVariant&nbsp;v1("This&nbsp;is&nbsp;a&nbsp;test");&nbsp;//&nbsp;直接构造<br/>

COleVariant&nbsp;v2&nbsp;=&nbsp;"This&nbsp;is&nbsp;a&nbsp;test";&nbsp;<br/>

//&nbsp;结果是VT_BSTR类型，值为"This&nbsp;is&nbsp;a&nbsp;test"<br/>

COleVariant&nbsp;v3((long)2002);<br/>
COleVariant&nbsp;v4&nbsp;=&nbsp;(long)2002;<br/>

//&nbsp;结果是VT_I4类型，值为2002&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　_variant_t是一个用于COM的VARIANT类，它的功能与COleVariant相似。不过在Visual&nbsp;C++.NET的MFC应用程序中使用时需要在代码文件前面添加下列两句：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　#include&nbsp;"comutil.h"</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　#pragma&nbsp;comment(&nbsp;lib,&nbsp;"comsupp.lib"&nbsp;)</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">四、CComBSTR和_bstr_t</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　CComBSTR是对BSTR数据类型封装的一个ATL类，它的操作比较方便。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">CComBSTR&nbsp;bstr1;&nbsp;<br/>

bstr1&nbsp;=&nbsp;"Bye";&nbsp;//&nbsp;直接赋值<br/>

OLECHAR*&nbsp;str&nbsp;=&nbsp;OLESTR("ta&nbsp;ta");&nbsp;//&nbsp;长度为5的宽字符<br/>

CComBSTR&nbsp;bstr2(wcslen(str));&nbsp;//&nbsp;定义长度为5<br/>

wcscpy(bstr2.m_str,&nbsp;str);&nbsp;//&nbsp;将宽字符串复制到BSTR中<br/>

CComBSTR&nbsp;bstr3(5,&nbsp;OLESTR("Hello&nbsp;World"));&nbsp;<br/>

CComBSTR&nbsp;bstr4(5,&nbsp;"Hello&nbsp;World");&nbsp;<br/>

CComBSTR&nbsp;bstr5(OLESTR("Hey&nbsp;there"));&nbsp;<br/>

CComBSTR&nbsp;bstr6("Hey&nbsp;there");&nbsp;<br/>

CComBSTR&nbsp;bstr7(bstr6);&nbsp;<br/>
//&nbsp;构造时复制，内容为"Hey&nbsp;there"&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　_bstr_t是是C++对BSTR的封装，它的构造和析构函数分别调用SysAllocString和SysFreeString函数，其他操作是借用BSTR&nbsp;API函数。与_variant_t相似，使用时也要添加comutil.h和comsupp.lib。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">五、BSTR、char*和CString转换</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　(1)&nbsp;char*转换成CString</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　若将char*转换成CString，除了直接赋值外，还可使用CString::Format进行。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">char&nbsp;chArray[]&nbsp;=&nbsp;"This&nbsp;is&nbsp;a&nbsp;test";<br/>

char&nbsp;*&nbsp;p&nbsp;=&nbsp;"This&nbsp;is&nbsp;a&nbsp;test";&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　或</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">LPSTR&nbsp;p&nbsp;=&nbsp;"This&nbsp;is&nbsp;a&nbsp;test";&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　或在已定义Unicode应的用程序中</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">TCHAR&nbsp;*&nbsp;p&nbsp;=&nbsp;_T("This&nbsp;is&nbsp;a&nbsp;test");&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　或</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">LPTSTR&nbsp;p&nbsp;=&nbsp;_T("This&nbsp;is&nbsp;a&nbsp;test");<br/>

CString&nbsp;theString&nbsp;=&nbsp;chArray;<br/>

theString.Format(_T("%s"),&nbsp;chArray);<br/>
theString&nbsp;=&nbsp;p;&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　(2)&nbsp;CString转换成char*</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　若将CString类转换成char*(LPSTR)类型，常常使用下列三种方法：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法一，使用强制转换。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">CString&nbsp;theString(&nbsp;"This&nbsp;is&nbsp;a&nbsp;test"&nbsp;);<br/>

LPTSTR&nbsp;lpsz&nbsp;=(LPTSTR)(LPCTSTR)theString;&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法二，使用strcpy。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">CString&nbsp;theString(&nbsp;"This&nbsp;is&nbsp;a&nbsp;test"&nbsp;);<br/>

LPTSTR&nbsp;lpsz&nbsp;=&nbsp;new&nbsp;TCHAR[theString.GetLength()+1];<br/>

_tcscpy(lpsz,&nbsp;theString);&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　需要说明的是，strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是&nbsp;const&nbsp;wchar_t*&nbsp;(Unicode)或const&nbsp;char*&nbsp;(ANSI)，系统编译器将会自动对其进行转换。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法三，使用CString::GetBuffer。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">CString&nbsp;s(_T("This&nbsp;is&nbsp;a&nbsp;test&nbsp;"));<br/>

LPTSTR&nbsp;p&nbsp;=&nbsp;s.GetBuffer();<br/>

//&nbsp;在这里添加使用p的代码<br/>
if(p&nbsp;!=&nbsp;NULL)&nbsp;*p&nbsp;=&nbsp;_T('\0');<br/>

s.ReleaseBuffer();&nbsp;<br/>
//&nbsp;使用完后及时释放，以便能使用其它的CString成员函数&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　(3)&nbsp;BSTR转换成char*</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法一，使用ConvertBSTRToString。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">#include&nbsp;<br/>
#pragma&nbsp;comment(lib,&nbsp;"comsupp.lib")<br/>

int&nbsp;_tmain(int&nbsp;argc,&nbsp;_TCHAR*&nbsp;argv[]){<br/>

BSTR&nbsp;bstrText&nbsp;=&nbsp;::SysAllocString(L"Test");<br/>

char*&nbsp;lpszText2&nbsp;=&nbsp;_com_util::ConvertBSTRToString(bstrText);<br/>

SysFreeString(bstrText);&nbsp;//&nbsp;用完释放<br/>

delete[]&nbsp;lpszText2;<br/>
return&nbsp;0;<br/>
}&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法二，使用_bstr_t的赋值运算符重载。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">_bstr_t&nbsp;b&nbsp;=&nbsp;bstrText;<br/>

char*&nbsp;lpszText2&nbsp;=&nbsp;b;&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　(4)&nbsp;char*转换成BSTR</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法一，使用SysAllocString等API函数。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">BSTR&nbsp;bstrText&nbsp;=&nbsp;::SysAllocString(L"Test");<br/>

BSTR&nbsp;bstrText&nbsp;=&nbsp;::SysAllocStringLen(L"Test",4);<br/>

BSTR&nbsp;bstrText&nbsp;=&nbsp;::SysAllocStringByteLen("Test",4);&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法二，使用COleVariant或_variant_t。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">//COleVariant&nbsp;strVar("This&nbsp;is&nbsp;a&nbsp;test");<br/>

_variant_t&nbsp;strVar("This&nbsp;is&nbsp;a&nbsp;test");<br/>

BSTR&nbsp;bstrText&nbsp;=&nbsp;strVar.bstrVal;&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法三，使用_bstr_t，这是一种最简单的方法。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">BSTR&nbsp;bstrText&nbsp;=&nbsp;_bstr_t("This&nbsp;is&nbsp;a&nbsp;test");&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法四，使用CComBSTR。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">BSTR&nbsp;bstrText&nbsp;=&nbsp;CComBSTR("This&nbsp;is&nbsp;a&nbsp;test");&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　或</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">CComBSTR&nbsp;bstr("This&nbsp;is&nbsp;a&nbsp;test");<br/>

BSTR&nbsp;bstrText&nbsp;=&nbsp;bstr.m_str;&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法五，使用ConvertStringToBSTR。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">char*&nbsp;lpszText&nbsp;=&nbsp;"Test";<br/>

BSTR&nbsp;bstrText&nbsp;=&nbsp;_com_util::ConvertStringToBSTR(lpszText);&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　(5)&nbsp;CString转换成BSTR</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　通常是通过使用CStringT::AllocSysString来实现。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">CString&nbsp;str("This&nbsp;is&nbsp;a&nbsp;test");<br/>

BSTR&nbsp;bstrText&nbsp;=&nbsp;str.AllocSysString();<br/>

…<br/>
SysFreeString(bstrText);&nbsp;//&nbsp;用完释放&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　(6)&nbsp;BSTR转换成CString</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　一般可按下列方法进行：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">BSTR&nbsp;bstrText&nbsp;=&nbsp;::SysAllocString(L"Test");<br/>

CStringA&nbsp;str;<br/>
str.Empty();<br/>
str&nbsp;=&nbsp;bstrText;&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　或</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">CStringA&nbsp;str(bstrText);&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　(7)&nbsp;ANSI、Unicode和宽字符之间的转换</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法一，使用MultiByteToWideChar将ANSI字符转换成Unicode字符，使用WideCharToMultiByte将Unicode字符转换成ANSI字符。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法二，使用“_T”将ANSI转换成“一般”类型字符串，使用“L”将ANSI转换成Unicode，而在托管C++环境中还可使用S将ANSI字符串转换成String*对象。例如：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">TCHAR&nbsp;tstr[]&nbsp;=&nbsp;_T("this&nbsp;is&nbsp;a&nbsp;test");<br/>

wchar_t&nbsp;wszStr[]&nbsp;=&nbsp;L"This&nbsp;is&nbsp;a&nbsp;test";<br/>

String*&nbsp;str&nbsp;=&nbsp;S”This&nbsp;is&nbsp;a&nbsp;test”;&nbsp;</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　方法三，使用ATL&nbsp;7.0的转换宏和类。ATL7.0在原有3.0基础上完善和增加了许多字符串转换宏以及提供相应的类，它具有如图3所示的统一形式：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　其中，第一个C表示“类”，以便于ATL&nbsp;3.0宏相区别，第二个C表示常量，2表示“to”，EX表示要开辟一定大小的缓冲。SourceType和DestinationType可以是A、T、W和OLE，其含义分别是ANSI、Unicode、“一般”类型和OLE字符串。例如，CA2CT就是将ANSI转换成一般类型的字符串常量。下面是一些示例代码：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">LPTSTR&nbsp;tstr=&nbsp;CA2TEX&lt;16&gt;("this&nbsp;is&nbsp;a&nbsp;test");<br/>

LPCTSTR&nbsp;tcstr=&nbsp;CA2CT("this&nbsp;is&nbsp;a&nbsp;test");<br/>

wchar_t&nbsp;wszStr[]&nbsp;=&nbsp;L"This&nbsp;is&nbsp;a&nbsp;test";<br/>

char*&nbsp;chstr&nbsp;=&nbsp;CW2A(wszStr);&nbsp;</FONT></P>
</DIV>
<br/></DIV>
]]></description>
            <author>idol</author>
            <category>编程技术</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901007me0.html#comment</comments>
            <pubDate>Wed, 26 Dec 2007 05:52:26 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901007me0.html</guid>
        </item>
        <item>
            <title>防止窗口闪烁 -- From CSDN</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901007mdt.html</link>
            <description><![CDATA[<div><font STYLE="FONT-SIZE: 16px">&nbsp;zz from
Internet</FONT></DIV>
<div>&nbsp;</DIV>
<div><font STYLE="FONT-SIZE: 16px">1、将Invalidate()替换为InvalidateRect()。<br/>
<br/>
　　Invalidate()会导致整个窗口的图象重画，需要的时间比较长，而InvalidateRect()仅仅重画Rect区域内的内容，所以所需时间会少一些。虫虫以前很懒，经常为一小块区域的重画就调用Invalidate()，不愿意自己去计算需要重画的Rect，但是事实是，如果你确实需要改善闪烁的情况，计算一个Rect所用的时间比起重画那些不需要重画的内容所需要的时间要少得多。<br/>

<br/>
2、禁止系统搽除你的窗口。<br/>
<br/>
　　系统在需要重画窗口的时候会帮你用指定的背景色来搽除窗口。可是，也许需要重画的区域也许非常小。或者，在你重画这些东西之间还要经过大量的计算才能开始。这个时候你可以禁止系统搽掉原来的图象。直到你已经计算好了所有的数据，自己把那些需要搽掉的部分用背景色覆盖掉（如：dc.FillRect(rect,&amp;brush);rect是需要搽除的区域，brush是带背景色的刷子），再画上新的图形。要禁止系统搽除你的窗口，可以重载OnEraseBkgnd()函数，让其直接返回TRUE就可以了。如<br/>

<br/>
BOOL CMyWin::OnEraseBkgnd(CDC* pDC)<br/>
{<br/>
return TRUE;<br/>
//return
CWnd::OnEraseBkgnd(pDC);//把系统原来的这条语句注释掉。<br/>
}<br/>
<br/>
3、有效的进行搽除。<br/>
<br/>
　　搽除背景的时候，不要该搽不该搽的地方都搽。比如，你在一个窗口上放了一个很大的Edit框，几乎占了整个窗口，那么你频繁的搽除整个窗口背景将导致Edit不停重画形成剧烈的闪烁。事实上你可以CRgn创建一个需要搽除的区域，只搽除这一部分。如<br/>

<br/>
GetClientRect(rectClient);<br/>
rgn1.CreateRectRgnIndirect(rectClient);<br/>
rgn2.CreateRectRgnIndirect(m_rectEdit);<br/>
if(rgn1.CombineRgn(&amp;rgn1,&amp;rgn2,RGN_XOR) ==
ERROR)//处理后的rgn1只包括了Edit框之外的客户区域，这样，Edit将不会被我的背景覆盖而导致重画。<br/>

{<br/>
ASSERT(FALSE);<br/>
return ;<br/>
}<br/>
brush.CreateSolidBrush(m_clrBackgnd);<br/>
pDC-&gt;FillRgn(&amp;rgn1,&amp;brush);<br/>
brush.DeleteObject();<br/>
<br/>
　　注意：在使用这个方法的时候要同时使用方法二。别忘了，到时候又说虫虫的办法不灵。<br/>

<br/>
4、使用MemoryDC先在内存里把图画好，再复制到屏幕上。<br/>
<br/>
　　这对于一次画图过程很长的情况比较管用。毕竟内存操作比较快，而且复制到屏幕又是一次性的，至少不会出现可以明显看出一个东东从左画到右的情况。<br/>

<br/>
void CMyWin::OnPaint()<br/>
{<br/>
CPaintDC dc1(this); // device context for painting<br/>
dcMemory.CreateCompatibleDC(&amp;dc1);<br/>
CBitmap
bmp;//这里的Bitmap是必须的，否则当心弄出一个大黑块哦。<br/>
bmp.CreateCompatibleBitmap(&amp;dc1,rectClient.Width(),rectClient.Height());<br/>

dcMemory.SelectObject(&amp;bmp);<br/>
<br/>
//接下来你想怎么画就怎么画吧。<br/>
//dcMemory.FillRect(rectClient,&amp;brush);<br/>
<br/>
dc1.BitBlt(0,0,rectClient.Width(),rectClient.Height(),&amp;dcMemory,0,0,SRCCOPY);<br/>

dcMemory.DeleteDC();<br/>
// Do not call CWnd::OnPaint() for painting messages<br/>
}</FONT></DIV>
]]></description>
            <author>idol</author>
            <category>编程技术</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901007mdt.html#comment</comments>
            <pubDate>Wed, 26 Dec 2007 05:33:41 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901007mdt.html</guid>
        </item>
        <item>
            <title>显示图形如何避免闪烁</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901007mci.html</link>
            <description><![CDATA[<p><font STYLE="FONT-SIZE: 16px">&nbsp;zz from
Internet</FONT></P>
<p>&nbsp;</P>
<p><font STYLE="FONT-SIZE: 16px">&nbsp;&nbsp;
显示图形如何避免闪烁，如何提高显示效率是问得比较多的问题。而且多数人认为MFC的绘图函数效率很低，总是想寻求其它的解决方案。MFC的绘图效率的确不高但也不差，而且它的绘图函数使用非常简单，只要使用方法得当，再加上一些技巧，用MFC可以得到效率很高的绘图程序。我想就我长期（呵呵当然也只有2年多）使用MFC绘图的经验谈谈<br/>

我的一些观点。<br/>
1、显示的图形为什么会闪烁？<br/>
我们的绘图过程大多放在OnDraw或者OnPaint函数中，OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时，总是先用背景色将显示区清除，然后才调用OnPaint，而背景色往往与绘图内容反差很大，这样在短时间内背景色与显示图形的交替出现，使得显示窗口看起来在闪。如果将背景刷设置成NULL，这样无论怎样重绘图形都不会闪了。<br/>

当然，这样做会使得窗口的显示乱成一团，因为重绘时没有背景色对原来绘制的图形进行清除，而又叠加上了新的图形。<br/>

有的人会说，闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的，其实这样说并不对，绘图的显示速度对闪烁的影响不是根本性的。例如在OnDraw(CDC
*pDC)中这样写：<br/>
pDC-&gt;MoveTo(0,0);<br/>
pDC-&gt;LineTo(100,100);<br/>
这个绘图过程应该是非常简单、非常快了吧，但是拉动窗口变化时还是会看见闪烁。其实从道理上讲，画图的过程越复杂越慢闪烁应该越少，因为绘图用的时间与用背景清除屏幕所花的时间的比例越大人对闪烁的感觉会越不明显。比如：清楚屏幕时间为1s绘图时间也是为1s，这样在10s内的连续重画中就要闪烁5次；如果清楚屏幕时间为1s不变，而绘图时间为9s，这样10s内的连续重画只会闪烁一次。这个也可以试验，在OnDraw(CDC
*pDC)中这样写：<br/>
for(int i=0;i&lt;100000;i++)<br/>
{<br/>
pDC-&gt;MoveTo(0,i);<br/>
pDC-&gt;LineTo(1000,i);<br/>
}<br/>
呵呵，程序有点变态，但是能说明问题。&nbsp;&nbsp;&nbsp;&nbsp;
说到这里可能又有人要说了，为什么一个简单图形看起来没有复杂图形那么闪呢？这是因为复杂图形占的面积大，重画时造成的反差比较大，所以感觉上要闪得厉害一些，但是闪烁频率要低。<br/>

&nbsp;&nbsp;&nbsp;&nbsp;
那为什么动画的重画频率高，而看起来却不闪？这里，我就要再次强调了，闪烁是什么？闪烁就是反差，反差越大，闪烁越厉害。因为动画的连续两个帧之间的差异很小所以看起来不闪。如果不信，可以在动画的每一帧中间加一张纯白的帧，不闪才怪呢。<br/>

2、如何避免闪烁<br/>
&nbsp;&nbsp;&nbsp;&nbsp;
在知道图形显示闪烁的原因之后，对症下药就好办了。首先当然是去掉MFC提供的背景绘制过程了。实现的方法很多，<br/>

&nbsp;&nbsp; *
可以在窗口形成时给窗口的注册类的背景刷付NULL<br/>
&nbsp;&nbsp; *
也可以在形成以后修改背景<br/>
static CBrush brush(RGB(255,0,0));<br/>
SetClassLong(this-&gt;m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);<br/>

&nbsp;&nbsp; *
要简单也可以重载OnEraseBkgnd(CDC* pDC)直接返回TRUE<br/>
&nbsp;&nbsp;&nbsp;&nbsp;
这样背景没有了，结果图形显示的确不闪了，但是显示也象前面所说的一样，变得一团乱。怎么办？这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有图形进行显示以外，在内存中也有图形在绘制。我们可以把要显示的图形先在内存中绘制好，然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去（这个过程非常快，因为是非常规整的内存拷贝）。这样在内存中绘图时，随便用什么反差大的背景色进行清除都不会闪，因为看不见。当贴到屏幕上时，因为内存中最终的图形与屏幕显示图形差别很小（如果没有运动，当然就没有差别），这样看起来就不会闪。<br/>

3、如何实现双缓冲<br/>
&nbsp;&nbsp;
首先给出实现的程序，然后再解释，同样是在OnDraw(CDC *pDC)中：<br/>
CDC MemDC; //首先定义一个显示设备对象<br/>
CBitmap MemBitmap;//定义一个位图对象<br/>
//随后建立与屏幕显示兼容的内存显示设备<br/>
MemDC.CreateCompatibleDC(NULL);<br/>
//这时还不能绘图，因为没有地方画 ^_^<br/>
//下面建立一个与屏幕显示兼容的位图，至于位图的大小嘛，可以用窗口的大小<br/>

MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);<br/>
//将位图选入到内存显示设备中<br/>
//只有选入了位图的内存显示设备才有地方绘图，画到指定的位图上<br/>
CBitmap *pOldBit=MemDC.SelectObject(&amp;MemBitmap);<br/>
//先用背景色将位图清除干净，这里我用的是白色作为背景<br/>
//你也可以用自己应该用的颜色<br/>
MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));<br/>
//绘图<br/>
MemDC.MoveTo(……);<br/>
MemDC.LineTo(……);<br/>
//将内存中的图拷贝到屏幕上进行显示<br/>
pDC-&gt;BitBlt(0,0,nWidth,nHeight,&amp;MemDC,0,0,SRCCOPY);<br/>
//绘图完成后的清理<br/>
MemBitmap.DeleteObject();<br/>
MemDC.DeleteDC();<br/>
上面的注释应该很详尽了，废话就不多说了。<br/>
4、如何提高绘图的效率<br/>
&nbsp;&nbsp;&nbsp;&nbsp;
我主要做的是电力系统的网络图形的CAD软件，在一个窗口中往往要显示成千上万个电力元件，而每个元件又是由点、线、圆等基本图形构成。如果真要在一次重绘过程重画这么多元件，可想而知这个过程是非常漫长的。如果加上了图形的浏览功能，鼠标拖动图形滚动时需要进行大量的重绘，速度会慢得让用户将无法忍受。怎么办？只有再研究研究MFC的绘图过程了。<br/>

&nbsp;&nbsp;&nbsp;
实际上，在OnDraw(CDC
*pDC)中绘制的图并不是所有都显示了的，例如：你在OnDraw中画了两个矩形，在一次重绘中虽然两个矩形的绘制函数都有执行，但是很有可能只有一个显示了，这是因为MFC本身为了提高重绘的效率设置了裁剪区。裁剪区的作用就是：只有在这个区内的绘图过程才会真正有效，在区外的是无效的，即使在区外执行了绘图函数也是不会显示的。因为多数情况下窗口重绘的产生大多是因为窗口部分被遮挡或者窗口有滚动发生，改变的区域并不是整个图形而只有一小部分，这一部分需要改变的就是pDC中的裁剪区了。因为显示（往内存或者显存都叫显示）比绘图过程的计算要费时得多，有了裁剪区后显示的就只是应该显示的部分，大大提高了显示效率。但是这个裁剪区是MFC设置的，它已经为我们提高了显示效率，在进行复杂图形的绘制时如何进一步提高效率呢？那就只有去掉在裁剪区外的绘图过程了。可以先用pDC-&gt;GetClipBox()得到裁剪区，然后在绘图时判断你的图形是否在这个区内，如果在就画，不在就不画。<br/>

如果你的绘图过程不复杂，这样做可能对你的绘图效率不会有提高。<br/>
版主点评：<br/>
本文系统地阐述了防止图形闪烁的方式，其实归根结底，防止闪烁的最终办法就是最好只重画改变的部分，决不能先用背景色擦除全部再画上来</FONT></P>
]]></description>
            <author>idol</author>
            <category>编程技术</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901007mci.html#comment</comments>
            <pubDate>Wed, 26 Dec 2007 04:13:24 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901007mci.html</guid>
        </item>
        <item>
            <title>Gdiplus::Pen</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901007mc0.html</link>
            <description><![CDATA[<div><font STYLE="FONT-SIZE: 16px">&nbsp;zz from
Internet</FONT></DIV>
<div>&nbsp;</DIV>
<div>
<table STYLE="TABLE-LAYOUT: fixed">
<tbody>
<tr>
<td>
<div CLASS="cnt"><font STYLE="FONT-SIZE: 16px">　　画笔是用来绘制各种直线和曲线的一种图形工具，GDI+的Pen类为画笔提供了丰富的方法。一般来说，我们可以通过其构造函数来指定画笔的颜色和宽度，其定义如下：<br/>

<br/>
Pen(&nbsp;const&nbsp;Color&amp;&nbsp;color,&nbsp;REAL&nbsp;width&nbsp;);<br/>

<br/>
　　其中，color是用来指定画笔颜色，width用来指定画笔宽度。REAL是一个float类型定义，而Color是GDI+的一个颜色类，它既可以指定一个ARGB颜色类型，也可以使用GDI+预定义的颜色值，甚至可以将COLORREF转换成Color类型的颜色。例如，下面的代码都是创建一个宽度为3，颜色为蓝色的画笔：<br/>

<br/></FONT>
<table WIDTH="100%" BGCOLOR="#FFFFFF">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">Pen&nbsp;newPen(&nbsp;Color(&nbsp;255,&nbsp;0,&nbsp;0,&nbsp;255&nbsp;),&nbsp;3&nbsp;);<br/>

<br/>
Pen&nbsp;newPen(Color(&nbsp;0,&nbsp;0,&nbsp;255),&nbsp;3);<br/>

//&nbsp;当Color只有三个实参时，颜色Alpha分量值为255。<br/>

<br/>
Pen&nbsp;newPen(Color::Blue,&nbsp;3);<br/>
<br/>
COLORREF&nbsp;crRef&nbsp;=&nbsp;RGB(&nbsp;0,&nbsp;0,&nbsp;255);<br/>

Color&nbsp;color;<br/>
color.SetFromCOLORREF(crRef);<br/>
Pen&nbsp;newPen(color,&nbsp;3);</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　除了颜色外，GDI+的Pen类还提供SetDashStyle和SetDashPattern方法来设置画笔的预定义风格和自定义类型。其中，预定义风格可以有：DashStyleSolid(实线)、DashStyleDash(虚线)、DashStyleDot(点线)、DashStyleDashDot(点划线)、DashStyleDashDotDot(双点划线)和DashStyleCustom(自定义类型)。例如下列代码，其结果如图7.6所示：<br/>

<br/></FONT>
<table WIDTH="100%" BGCOLOR="#FFFFFF">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">using&nbsp;namespace&nbsp;Gdiplus;<br/>

Graphics&nbsp;graphics(&nbsp;pDC-&gt;m_hDC&nbsp;);<br/>

Pen&nbsp;pen(Color(255,&nbsp;0,&nbsp;0,&nbsp;255),&nbsp;15);<br/>

<br/>
pen.SetDashStyle(DashStyleDash);<br/>
graphics.DrawLine(&amp;pen,&nbsp;0,&nbsp;50,&nbsp;400,&nbsp;150);<br/>

<br/>
pen.SetDashStyle(DashStyleDot);<br/>
graphics.DrawLine(&amp;pen,&nbsp;0,&nbsp;80,&nbsp;400,&nbsp;180);&nbsp;<br/>

<br/>
pen.SetDashStyle(DashStyleDashDot);<br/>
graphics.DrawLine(&amp;pen,&nbsp;0,&nbsp;110,&nbsp;400,&nbsp;210);&nbsp;</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px"><img HSPACE="3" SRC="http://www.yesky.com/image20010518/109886.gif" ALIGN="center" VSPACE="1" BORDER="1"></IMG><br/>
<br/>
　　但是，在工程应用中，预定义风格的画笔有时并不能满足实际的需求，而必须自己定义一些线型，这需要通过SetDashPattern函数来实现。SetDashPattern的原型如下：<br/>

<br/></FONT>
<table WIDTH="100%" BGCOLOR="#FFFFFF">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">Status&nbsp;SetDashPattern(&nbsp;const&nbsp;REAL*&nbsp;dashArray,&nbsp;INT&nbsp;count);</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　其中，dashArray是一个包含短划和间隔长度的数组，count表示数组的大小。注意，dashArray中的短划长度和间隔长度是成对出现的，例如下列代码是使用自定义类型的画笔，其结果如图7.7所示。<br/>

<br/></FONT>
<table WIDTH="100%" BGCOLOR="#FFFFFF">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">REAL&nbsp;dashVals[4]&nbsp;=&nbsp;{<br/>

2,&nbsp;//&nbsp;短划长为2<br/>
2,&nbsp;//&nbsp;间隔为2<br/>
15,&nbsp;//&nbsp;短划长为15<br/>
2};&nbsp;//&nbsp;间隔为2<br/>
Pen&nbsp;pen(Color(255,&nbsp;0,&nbsp;0,&nbsp;0),&nbsp;5);<br/>

pen.SetDashPattern(dashVals,&nbsp;4);<br/>
graphics.DrawLine(&amp;pen,&nbsp;5,&nbsp;20,&nbsp;405,&nbsp;200);&nbsp;</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px"><img HSPACE="3" SRC="http://www.yesky.com/image20010518/109888.gif" ALIGN="center" VSPACE="1" BORDER="1"></IMG><br/>
<br/>
　　需要说明的是，GDI+的Pen类还提供SetStartCap和SetEndCap方法来设置一条直线的起始端和终止端的样式。例如下面的代码，其结果如图7.8所示。<br/>

<br/></FONT>
<table WIDTH="100%" BGCOLOR="#FFFFFF">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">using&nbsp;namespace&nbsp;Gdiplus;<br/>

Graphics&nbsp;graphics(&nbsp;pDC-&gt;m_hDC&nbsp;);<br/>

<br/>
Pen&nbsp;pen(&nbsp;Color(&nbsp;255,&nbsp;0,&nbsp;0,&nbsp;255&nbsp;),&nbsp;15);&nbsp;<br/>

<br/>
pen.SetStartCap(LineCapFlat);<br/>
pen.SetEndCap(LineCapSquare);<br/>
graphics.DrawLine(&amp;pen,&nbsp;50,&nbsp;50,&nbsp;250,&nbsp;50);<br/>

<br/>
pen.SetStartCap(LineCapRound&nbsp;);<br/>
pen.SetEndCap(LineCapRoundAnchor);<br/>
graphics.DrawLine(&amp;pen,&nbsp;50,&nbsp;100,&nbsp;250,&nbsp;100);&nbsp;<br/>

<br/>
pen.SetStartCap(LineCapDiamondAnchor);<br/>
pen.SetEndCap(LineCapArrowAnchor);<br/>
graphics.DrawLine(&amp;pen,&nbsp;50,&nbsp;150,&nbsp;250,&nbsp;150);&nbsp;</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px"><img HSPACE="3" SRC="http://www.yesky.com/image20010518/109887.gif" ALIGN="center" VSPACE="1" BORDER="1"></IMG></FONT></DIV>
</TD>
</TR>
</TBODY>
</TABLE>
</DIV>
]]></description>
            <author>idol</author>
            <category>编程技术</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901007mc0.html#comment</comments>
            <pubDate>Wed, 26 Dec 2007 03:51:34 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901007mc0.html</guid>
        </item>
        <item>
            <title>在VC++中生成伪随机数祥解</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901007kpu.html</link>
            <description><![CDATA[<div><font STYLE="FONT-SIZE: 16px">&nbsp;zz from
Internet</FONT></DIV>
<div><font STYLE="FONT-SIZE: 16px">　<strong>摘 要</STRONG>
伪随机数在计算机软件设计中有很广泛的用途。本文介绍了基于数学方法的利用计算机产生伪随机数的一种方法，即线性同余法，任何伪随机数的产生都是运用递推的原理来生成的。以及在Visual
C++环境中产生伪随机数的两个重要函数，rand和srand函数，正确地使用这两个函数是产生性能良好的伪随机数的关键，最后介绍了利用伪随机数生成技术在MFC中生成基于C/S模式应用程序的随机校验码以及利用一种软件工具ImagePassword产生随机密码。<br/>

<br/>
　　 <strong>关键词</STRONG> 伪随机数生成；线性同余法；Visual
C++；随机校验码<br/>
<br/>
　　为追求真正的随机序列，人们曾采用很多种原始的物理方法用于生成一定范围内满足精度(位数)的均匀分布序列，其缺点在于：速度慢、效率低、需占用大量存储空间且不可重现等。为满足计算机模拟研究的需求，人们转而研究用算法生成模拟各种概率分布的伪随机序列。伪随机数是指用数学递推公式所产生的随机数。从实用的角度看，获取这种数的最简单和最自然的方法是利用计算机语言的函数库提供的随机数发生器。典型情况下，它会输出一个均匀分布在0和1区间内的伪随机变量的值。其中应用的最为广泛、研究最彻底的一个算法即线性同余法。<br/>

<br/>
　　线性同余法LCG(Linear Congruence Generator)<br/>
<br/>
　　选取足够大的正整数M和任意自然数n0，a，b，由递推公式：<br/>
<br/></FONT>
<table BORDERCOLOR="#CCCCCC" WIDTH="90%" ALIGN="center" BGCOLOR="#E3E3E3" BORDER="1">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">ni+1=(af(ni)+b)mod M
i=0，1，…，M-1</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　生成的数值序列称为是同余序列。当函数f(n)为线性函数时，即得到线性同余序列：<br/>

<br/></FONT>
<table BORDERCOLOR="#CCCCCC" WIDTH="90%" ALIGN="center" BGCOLOR="#E3E3E3" BORDER="1">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">ni+1=(a*ni+b)mod M
i=0，1，…，M-1</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　以下是线性同余法生成伪随机数的伪代码：<br/>
<br/></FONT>
<table BORDERCOLOR="#CCCCCC" WIDTH="90%" ALIGN="center" BGCOLOR="#E3E3E3" BORDER="1">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">Random(n，m，seed，a，b)<br/>
{<br/>
　 r0 = seed；<br/>
　 for (i = 1；i &lt;=n；i++)<br/>
　 ri = (a*ri-1 + b) mod m<br/>
}</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　其中种子参数seed可以任意选择，常常将它设为计算机当前的日期或者时间；m是一个较大数，可以把它取为2w，w是计算机的字长；a可以是0.01w和0.99w之间的任何整数。<br/>

<br/>
　　应用递推公式产生均匀分布随机数时，式中参数n0，a，b，M的选取十分重要。<br/>

<br/>
　　例如，选取M=10，a=b
=n0=7，生成的随机序列为{6，9，0，7，6，9，……}，周期为4。<br/>
<br/>
　　取M=16，a=5，b
=3，n0=7，生成的随机序列为{6，1，8，11，10，5，12，15，14，9，0，3，2，13，4，7，6，1……}，周期为16。<br/>

<br/>
　　取M=8，a=5，b
=1，n0=1，生成的随机序列为{6，7，4，5，2，3，0，1，6，7……}，周期为8。<br/>

<br/>
　　 <strong>Visual C++中伪随机数生成机制</STRONG><br/>
<br/>
　　用VC产生随机数有两个函数，分别为rand(void)和srand(seed)。rand()产生的随机整数是在0~RAND_MAX之间平均分布的，RAND_MAX是一个常量(定义为：#define
RAND_MAX
0x7fff)。它是short型数据的最大值，如果要产生一个浮点型的随机数，可以将rand()/1000.0，这样就得到一个0~32.767之间平均分布的随机浮点数。如果要使得范围大一点，那么可以通过产生几个随机数的线性组合来实现任意范围内的平均分布的随机数。<br/>

<br/>
　　其用法是先调用srand函数，如<br/>
<br/></FONT>
<table BORDERCOLOR="#CCCCCC" WIDTH="90%" ALIGN="center" BGCOLOR="#E3E3E3" BORDER="1">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">srand( (unsigned)time( NULL )
)</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　这样可以使得每次产生的随机数序列不同。如果计算伪随机序列的初始数值(称为种子)相同，则计算出来的伪随机序列就是完全相同的。要解决这个问题，需要在每次产生随机序列前，先指定不同的种子，这样计算出来的随机序列就不会完全相同了。以time函数值(即当前时间)作为种子数，因为两次调用rand函数的时间通常是不同的，这样就可以保证随机性了。也可以使用srand函数来人为指定种子数。<br/>

分析以下两个程序段，<br/>
<br/>
　　程序段1：<br/>
<br/></FONT>
<table BORDERCOLOR="#CCCCCC" WIDTH="90%" ALIGN="center" BGCOLOR="#E3E3E3" BORDER="1">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">//包含头文件<br/>
void main() {<br/>
　 int count=0;<br/>
　 for (int i=0;i &lt;10;i++){<br/>
　　 srand((unsigned)time(NULL));<br/>
　　 count++;<br/>
　　 cout
&lt;&lt;"No"&lt;&lt;count&lt;&lt;"="&lt;&lt;rand()&lt;&lt;"
";<br/>
　　 if (!(count%5)) cout &lt;&lt;endl;<br/>
　 }<br/>
}</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　程序段2：<br/>
<br/></FONT>
<table BORDERCOLOR="#CCCCCC" WIDTH="90%" ALIGN="center" BGCOLOR="#E3E3E3" BORDER="1">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">//包含头文件<br/>
void main() {<br/>
　 int count=0;<br/>
　 srand((unsigned)time(NULL));<br/>
　 for (int i=0;i &lt;10;i++){<br/>
　　 count++;<br/>
　　 cout
&lt;&lt;"No"&lt;&lt;count&lt;&lt;"="&lt;&lt;rand()&lt;&lt;"
";<br/>
　　 if (!(count%5)) cout &lt;&lt;endl;<br/>
　 }<br/>
}</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　程序段1的运行结果为：<br/>
<br/></FONT>
<table BORDERCOLOR="#CCCCCC" WIDTH="90%" ALIGN="center" BGCOLOR="#E3E3E3" BORDER="1">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">No1=9694 No2=9694 No3=9694
No4=9694 No5=9694<br/>
No6=9694 No7=9694 No8=9694 No9=9694 No10=9694</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　程序段2的运行结果为：<br/>
<br/></FONT>
<table BORDERCOLOR="#CCCCCC" WIDTH="90%" ALIGN="center" BGCOLOR="#E3E3E3" BORDER="1">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">No1=10351 No2=444 No3=11351
No4=3074 No5=21497<br/>
No6=30426 No7=6246 No8=24614 No9=22089 No10=21498</FONT></TD>
</TR>
</TBODY>
</TABLE>
<p><font STYLE="FONT-SIZE: 14px"><br/></FONT></P>
<p><font STYLE="FONT-SIZE: 16px">可以发现，以上两个程序段由于随机数生成时选择的种子的不同，运行的结果也不一样。rand()函数返回随机数序列中的下一个数(实际上是一个伪随机数序列，序列中的每一个数是由对其前面的数字进行复杂变换得到的)。为了模仿真正的随机性，首先要调用srand()函数给序列设置一个种子。为了更好地满足随机性，使用了时间函数time()，以便取到一个随时间变化的值，使每次运行rand()函数时从srand()函数所得到的种子值不相同。伪随机数生成器将作为"种子"的数当作初始整数传给函数。这粒种子会使这个球(生成伪随机数)一直滚下去。<br/>

<br/>
程序段1中由于将srand()函数放在循环体内，而程序执行的CPU时间较快，调用time函数获取的时间精度却较低(55ms)，这样循环体内每次产生随机数用到的种子数都是一样的，因此产生的随机数也是一样的。而程序段2中第1次产生的随机数要用到随机种子，以后的每次产生随机数都是利用递推关系得到的。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">　　<strong>基于MFC的随机校验码生成</STRONG><br/>

<br/>
　　
Web应用程序中经常要利用到随机校验码，校验码的主要作用是防止黑客利用工具软件在线破译用户登录密码，校验码、用户名、密码三者配合组成了进入Web应用系统的钥匙。在利用VC开发的基于客户机/浏览器(Client/Server)模式的应用软件系统中，为了防止非法用户入侵系统，通常也要运用随机校验码生成技术。<br/>

<br/>
　　本实现要用到以上介绍到的伪随机数生成技术。校验码数据将以16进制码方式显示。主要代码如下：<br/>

<br/></FONT></P>
<table BORDERCOLOR="#CCCCCC" WIDTH="90%" ALIGN="center" BGCOLOR="#E3E3E3" BORDER="1">
<tbody>
<tr>
<td><font STYLE="FONT-SIZE: 16px">void
CRandompasswordDlg::OnCreatekey() {<br/>
　 int RanCheckNum = 0;<br/>
　 char out[25]={0};<br/>
　 char keytemp[5]={0};<br/>
　 memset(out,0x30,18);<br/>
　 srand((unsigned)timeGetTime());//产生随机数种子<br/>
　 for(int i=0;i &lt;6;i++){<br/>
　　 RanCheckNum = rand();//产生随机数<br/>
　　 _itoa(RanCheckNum,keytemp,16);//将随机数转换成16进制<br/>
　　 memcpy( &amp;out[i*4],keytemp,strlen(keytemp));<br/>
　 }<br/>
　 out[24]=0x00;<br/>
　 strcpy(m_key.GetBuffer(18),out);<br/>
　 UpdateData(FALSE);<br/>
}</FONT></TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　运行结果如图1所示：<br/>
<br/></FONT>
<table WIDTH="90%" ALIGN="center" BORDER="0">
<tbody>
<tr>
<td>
<div ALIGN="center"><font STYLE="FONT-SIZE: 16px"><img SRC="http://dotnet.chinaitlab.com/UploadFiles_6597/200702/20070227111623790.jpg" BORDER="0"></IMG></FONT><br/>
图1 利用伪随机数生成随机校验码</DIV>
</TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　程序运行时，由于每一次点击"产生随机校验码"的系统时间不同，生成随机数的种子就不一样，因此产生的随机数也是不一样的，从而保证了校验码生成的随机性。<br/>

<br/>
　　 <strong>利用ImagePassword工具产生随机密码</STRONG><br/>
<br/>
　　
ImagePassword提供一个可选择的图形阵列，通过随机改变图形阵列中的阵点图形来产生随机密码。当随机点击图象阵列中的图象阵点，该阵点中的图象发生变化。其运行界面如图2所示：<br/>

<br/></FONT>
<table WIDTH="90%" ALIGN="center" BORDER="0">
<tbody>
<tr>
<td>
<div ALIGN="center"><font STYLE="FONT-SIZE: 16px"><img SRC="http://dotnet.chinaitlab.com/UploadFiles_6597/200702/20070227111623311.jpg" BORDER="0"></IMG></FONT><br/>
图2 ImagePassword运行界面</DIV>
</TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　点击OK按钮后所产生的随机密码如图3所示：<br/>
<br/></FONT>
<table WIDTH="90%" ALIGN="center" BORDER="0">
<tbody>
<tr>
<td>
<div ALIGN="center"><font STYLE="FONT-SIZE: 16px"><img SRC="http://dotnet.chinaitlab.com/UploadFiles_6597/200702/20070227111623496.jpg" BORDER="0"></IMG></FONT><br/>
图3 ImagePassword运行结果</DIV>
</TD>
</TR>
</TBODY>
</TABLE>
<br/>
<font STYLE="FONT-SIZE: 16px">　　
ImagePassword产生的密码的随机性依赖于用户对图象阵列中阵点图象的随机选择，一般来说用户在图象阵列中随机点击鼠标的次数越多，最后产生的密码的随机性越强。<br/>

<br/>
　　 <strong>结束语</STRONG><br/>
<br/>
　　伪随机数在不同的软件系统中都得到了很广泛的应用，如何选择随机数生成种子使得生成的伪随机数性能更佳是软件设计者追求的目标之一。本文提到了利用系统时间作为种子参数在一定条件下可以满足软件的随机性需要。利用所产生的随机数在游戏编程，如扑克类游戏中的随机发牌，俄罗斯方块的随机生成等等其他应用中都起到很重要的作用。</FONT></DIV>
]]></description>
            <author>idol</author>
            <category>编程技术</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901007kpu.html#comment</comments>
            <pubDate>Thu, 20 Dec 2007 11:04:19 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901007kpu.html</guid>
        </item>
        <item>
            <title>VC之美化界面篇</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901000ahy.html</link>
            <description><![CDATA[<div><font STYLE="FONT-SIZE: 16px"><font STYLE="FONT-SIZE: 16px">&nbsp;<a HREF="http://www.cnblogs.com/a-peng/archive/2007/11/21/967027.html"><font STYLE="BACKGROUND-COLOR: #ffffff">http://www.cnblogs.com/a-peng/archive/2007/11/21/967027.html</FONT></A></FONT></FONT></DIV>
<div>&nbsp;</DIV>
<div><font SIZE="3">zz</FONT></DIV>
<div>
<p><font STYLE="FONT-SIZE: 16px">本文专题讨论VC中的界面美化，适用于具有中等VC水平的读者。读者最好具有以下VC基础：</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">1.&nbsp;大致了解MFC框架的基本运作原理；</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">2.&nbsp;熟悉Windows消息机制，熟悉MFC的消息映射和反射机制；</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">3.&nbsp;熟悉OOP理论和技术；</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">本文根据笔者多年的开发经验，并结合简单的例子一一展开，希望对读者有所帮助。</FONT></P>
<p>&nbsp;</P>
<p><font STYLE="FONT-SIZE: 16px">&nbsp;</FONT></P>
</DIV>
]]></description>
            <author>idol</author>
            <category>编程技术</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901000ahy.html#comment</comments>
            <pubDate>Mon, 26 Nov 2007 08:35:21 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901000ahy.html</guid>
        </item>
        <item>
            <title>树形控件TreeCtrl的用法</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901000agz.html</link>
            <description><![CDATA[<div><font STYLE="FONT-SIZE: 16px">&nbsp;ZZ From
Internet</FONT></DIV>
<div>&nbsp;</DIV>
<div>
<p><font STYLE="FONT-SIZE: 16px">树形控件TreeCtrl和下节要讲的</FONT><a HREF="http://www.lzu.edu.cn/netteach/bcyy/newles/VC/teach_road_48.htm"><font STYLE="FONT-SIZE: 16px">列表控件
ListCtrl</FONT></A><font STYLE="FONT-SIZE: 16px">在系统中大量被使用，例如Windows资源管理器就是一个典型的例子。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">树形控件可以用于树形的结构，其中有一个根接点(Root)然后下面有许多子结点，而每个子结点上有允许有一个或多个或没有子结点。MFC中使用CTreeCtrl类来封装树形控件的各种操作。通过调用<br/>

BOOL Create( DWORD dwStyle, const RECT&amp; rect, CWnd* pParentWnd,
UINT nID
);创建一个窗口，dwStyle中可以使用以下一些树形控件的专用风格：</FONT></P>
<ul>
<li><font STYLE="FONT-SIZE: 16px"><strong>TVS_HASLINES</STRONG>
在父/子结点之间绘制连线</FONT></LI>
<li><font STYLE="FONT-SIZE: 16px"><strong>TVS_LINESATROOT</STRONG>
在根/子结点之间绘制连线</FONT></LI>
<li><font STYLE="FONT-SIZE: 16px"><strong>TVS_HASBUTTONS</STRONG>
在每一个结点前添加一个按钮，用于表示当前结点是否已被展开</FONT></LI>
<li><font STYLE="FONT-SIZE: 16px"><strong>TVS_EDITLABELS</STRONG>
结点的显示字符可以被编辑</FONT></LI>
<li><font STYLE="FONT-SIZE: 16px"><strong>TVS_SHOWSELALWAYS</STRONG>
在失去焦点时也显示当前选中的结点</FONT></LI>
<li><strong><a NAME="baidusnap0" ID="baidusnap0"></A><b STYLE="COLOR: black; BACKGROUND-COLOR: #ffff66"><font STYLE="FONT-SIZE: 16px">TVS_DISABLEDRAGDROP</FONT></B></STRONG>
<font STYLE="FONT-SIZE: 16px">不允许Drag/Drop</FONT></LI>
<li><font STYLE="FONT-SIZE: 16px"><strong>TVS_NOTOOLTIPS</STRONG>
不使用ToolTip显示结点的显示字符</FONT></LI>
</UL>
<p><font STYLE="FONT-SIZE: 16px">在树形控件中每一个结点都有一个句柄（HTREEITEM），同时添加结点时必须提供的参数是该结点的父结点句柄，（其中根Root结点只有一个，既不可以添加也不可以删除）利用<br/>

HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent =
TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST
);可以添加一个结点，pszItem为显示的字符，hParent代表父结点的句柄，当前添加的结点会排在hInsertAfter表示的结点的后面，返回值为当前创建的结点的句柄。下面的代码会建立一个如下形式的树形结构：</FONT></P>
<pre>
<font STYLE="FONT-SIZE: 16px">+--- Parent1
    +--- Child1_1
    +--- Child1_2
    +--- Child1_3
+--- Parent2
+--- Parent3


HTREEITEM hItem,hSubItem;
hItem = m_tree.InsertItem("Parent1",TVI_ROOT);<font COLOR="#008000">在根结点上添加Parent1</FONT>
hSubItem = m_tree.InsertItem("Child1_1",hItem);//在Parent1上添加一个子结点
hSubItem = m_tree.InsertItem("Child1_2",hItem,hSubItem);<font COLOR="#008000">//在Parent1上添加一个子结点，排在Child1_1后面</FONT>
hSubItem = m_tree.InsertItem("Child1_3",hItem,hSubItem);

hItem = m_tree.InsertItem("Parent2",TVI_ROOT,hItem);    
hItem = m_tree.InsertItem("Parent3",TVI_ROOT,hItem);</FONT>
</PRE>
<p><font STYLE="FONT-SIZE: 16px">如果你希望在每个结点前添加一个小图标，就必需先调用CImageList*
SetImageList( CImageList * pImageList, int nImageListType
);指明当前所使用的ImageList，nImageListType为TVSIL_NORMAL。在调用完成后控件中使用图片以设置的ImageList中图片为准。然后调用<br/>

HTREEITEM InsertItem( LPCTSTR lpszItem, int nImage, int
nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM
hInsertAfter =
TVI_LAST);添加结点，nImage为结点没被选中时所使用图片序号，nSelectedImage为结点被选中时所使用图片序号。下面的代码演示了ImageList的设置。</FONT></P>
<pre>
<font STYLE="FONT-SIZE: 16px">
m_list.Create(IDB_TREE,16,4,RGB(0,0,0));
m_tree.SetImageList(&amp;m_list,TVSIL_NORMAL);
m_tree.InsertItem("Parent1",0,1);<font COLOR="#008000">//添加，选中时显示图标1，未选中时显示图标0</FONT></FONT>
</PRE>
<p><font STYLE="FONT-SIZE: 16px">此外CTreeCtrl还提供了一些函数用于得到/修改控件的状态。<br/>

HTREEITEM GetSelectedItem( );将返回当前选中的结点的句柄。BOOL
SelectItem( HTREEITEM hItem );将选中指明结点。<br/>
BOOL GetItemImage( HTREEITEM hItem, int&amp; nImage, int&amp;
nSelectedImage ) / BOOL SetItemImage( HTREEITEM hItem, int nImage,
int nSelectedImage )用于得到/修改某结点所使用图标索引。<br/>
CString GetItemText( HTREEITEM hItem ) /BOOL SetItemText( HTREEITEM
hItem, LPCTSTR lpszItem );用于得到/修改某一结点的显示字符。<br/>
BOOL DeleteItem( HTREEITEM hItem );用于删除某一结点，BOOL
DeleteAllItems( );将删除所有结点。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">此外如果想遍历树可以使用下面的函数：<br/>
HTREEITEM GetRootItem( );得到根结点。<br/>
HTREEITEM GetChildItem( HTREEITEM hItem );得到子结点。<br/>
HTREEITEM GetPrevSiblingItem/GetNextSiblingItem( HTREEITEM hItem
);得到指明结点的上/下一个兄弟结点。<br/>
HTREEITEM GetParentItem( HTREEITEM hItem );得到父结点。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px">树形控件的消息映射使用ON_NOTIFY宏，形式如同：ON_NOTIFY(
wNotifyCode, id, memberFxn
)，wNotifyCode为通知代码，id为产生该消息的窗口ID，memberFxn为处理函数，函数的原型如同void
OnXXXTree(NMHDR* pNMHDR, LRESULT*
pResult)，其中pNMHDR为一数据结构，在具体使用时需要转换成其他类型的结构。对于树形控件可能取值和对应的数据结构为：</FONT></P>
<ul>
<li><font STYLE="FONT-SIZE: 16px">TVN_SELCHANGED
在所选中的结点发生改变后发送，所用结构：NMTREEVIEW</FONT></LI>
<li><font STYLE="FONT-SIZE: 16px">TVN_ITEMEXPANDED
在某结点被展开后发送，所用结构：NMTREEVIEW</FONT></LI>
<li><font STYLE="FONT-SIZE: 16px">TVN_BEGINLABELEDIT
在开始编辑结点字符时发送，所用结构：NMTVDISPINFO</FONT></LI>
<li><font STYLE="FONT-SIZE: 16px">TVN_ENDLABELEDIT
在结束编辑结点字符时发送，所用结构：NMTVDISPINFO</FONT></LI>
<li><font STYLE="FONT-SIZE: 16px">TVN_GETDISPINFO
在需要得到某结点信息时发送，（如得到结点的显示字符）所用结构：NMTVDISPINFO</FONT></LI>
</UL>
<p><font STYLE="FONT-SIZE: 16px">关于ON_NOTIFY有很多内容，将在以后的内容中进行详细讲解。</FONT></P>
<p><font STYLE="FONT-SIZE: 16px"><strong>关于动态提供结点所显示的字符</STRONG>：首先你在添加结点时需要指明lpszItem参数为：LPSTR_TEXTCALLBACK。在控件显示该结点时会通过发送TVN_GETDISPINFO来取得所需要的字符，在处理该消息时先将参数pNMHDR转换为LPNMTVDISPINFO，然后填充其中item.pszText。但是我们通过什么来知道该结点所对应的信息呢，我的做法是在添加结点后设置其lParam参数，然后在提供信息时利用该参数来查找所对应的信息。下面的代码说明了这种方法：</FONT></P>
<pre>
<font STYLE="FONT-SIZE: 16px">char szOut[8][3]={"No.1","No.2","No.3"};

//添加结点
HTREEITEM hItem = m_tree.InsertItem(LPSTR_TEXTCALLBACK,...)
m_tree.SetItemData(hItem, 0 );
hItem = m_tree.InsertItem(LPSTR_TEXTCALLBACK,...)
m_tree.SetItemData(hItem, 1 );
//处理消息
void CParentWnd::OnGetDispInfoTree(NMHDR* pNMHDR, LRESULT* pResult)
{
 TV_DISPINFO* pTVDI = (TV_DISPINFO*)pNMHDR;
 pTVDI-&gt;item.pszText=szOut[pTVDI-&gt;item.lParam];//通过lParam得到需要显示的字符在数组中的位置
 *pResult = 0;
}</FONT>
</PRE>
<p><font STYLE="FONT-SIZE: 16px"><strong>关于编辑结点的显示字符</STRONG>：首先需要设置树形控件的TVS_EDITLABELS风格，在开始编辑时该控件将会发送TVN_BEGINLABELEDIT，你可以通过在处理函数中返回TRUE来取消接下来的编辑，在编辑完成后会发送TVN_ENDLABELEDIT，在处理该消息时需要将参数pNMHDR转换为LPNMTVDISPINFO，然后通过其中的item.pszText得到编辑后的字符，并重置显示字符。如果编辑在中途中取消该变量为NULL。下面的代码说明如何处理这些消息：</FONT></P>
<pre>
<font STYLE="FONT-SIZE: 16px">//处理消息 TVN_BEGINLABELEDIT
void CParentWnd::OnBeginEditTree(NMHDR* pNMHDR, LRESULT* pResult)
{
 TV_DISPINFO* pTVDI = (TV_DISPINFO*)pNMHDR;
 if(pTVDI-&gt;item.lParam==0);//判断是否取消该操作
  *pResult = 1;
 else
  *pResult = 0;
}
//处理消息 TVN_BEGINLABELEDIT
void CParentWnd::OnBeginEditTree(NMHDR* pNMHDR, LRESULT* pResult)
{
 TV_DISPINFO* pTVDI = (TV_DISPINFO*)pNMHDR;
 if(pTVDI-&gt;item.pszText==NULL);//判断是否已经取消取消编辑
  m_tree.SetItemText(pTVDI-&gt;item.hItem,pTVDI-&gt;pszText);//重置显示字符
 *pResult = 0;
}</FONT>
</PRE>
<p><font STYLE="FONT-SIZE: 16px">上面讲述的方法所进行的消息映射必须在父窗口中进行（同样WM_NOTIFY的所有消息都需要在父窗口中处理）。</FONT></P>
</DIV>
]]></description>
            <author>idol</author>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901000agz.html#comment</comments>
            <pubDate>Fri, 23 Nov 2007 07:15:17 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901000agz.html</guid>
        </item>
        <item>
            <title>DLL中 PreTranslateMessage消息的实现</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901000aef.html</link>
            <description><![CDATA[<div><font STYLE="FONT-SIZE: 16px">&nbsp;zz from
Internet</FONT></DIV>
<div>&nbsp;</DIV>
<div>
<div CLASS="cnt">
<p><font STYLE="FONT-SIZE: 16px"><span STYLE="COLOR: #003300">在</SPAN><span STYLE="COLOR: #003300">MFC</SPAN><span STYLE="COLOR: #003300">里面，</SPAN><span STYLE="COLOR: #003300">Pretranslatemessage</SPAN><span STYLE="COLOR: #003300">是一个很重要的虚函数。这个函数的作用这里就不谈了，很多地方都有涉及，这里只谈一下其实现的机制。</SPAN></FONT><span STYLE="FONT-SIZE: 10.5pt"><br/>
</SPAN><font STYLE="FONT-SIZE: 16px"><span STYLE="COLOR: #003300">谈到</SPAN><span STYLE="COLOR: #003300">PretranslateMessage</SPAN><span STYLE="COLOR: #003300">的实现，便不得不谈到</SPAN><span STYLE="COLOR: #003300">MFC</SPAN><span STYLE="COLOR: #003300">消息循环的实现。</SPAN><span STYLE="COLOR: #003300">MFC</SPAN><span STYLE="COLOR: #003300">通过</SPAN><span STYLE="COLOR: #003300">CWinApp</SPAN><span STYLE="COLOR: #003300">类中的</SPAN><span STYLE="COLOR: #003300">Pumpmessage</SPAN><span STYLE="COLOR: #003300">函数实现消息循环，但是实际的消息循环代码位于</SPAN><span STYLE="COLOR: #003300">CWinThread</SPAN><span STYLE="COLOR: #003300">中，</SPAN><span STYLE="COLOR: #003300">CWinApp</SPAN><span STYLE="COLOR: #003300">只是从</SPAN><span STYLE="COLOR: #003300">CWinThread</SPAN><span STYLE="COLOR: #003300">继承过来。其简化后的代码大概如下：</SPAN></FONT><span STYLE="FONT-SIZE: 10.5pt"><br/>
</SPAN><font STYLE="FONT-SIZE: 16px"><span STYLE="COLOR: #003300">BOOL CWinThread::PumpMessage()<br/>
{<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
_AFX_THREAD_STATE *pState = AfxGetThreadState();</SPAN>

</FONT></P>
<p><font STYLE="FONT-SIZE: 16px"><span STYLE="COLOR: #003300">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
::GetMessage(&amp;(pState-&gt;m_msgCur), NULL, NULL, NULL))<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (!AfxPreTranslateMessage(&amp;(pState-&gt;m_msgCur)))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
{<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
::TranslateMessage(&amp;(pState-&gt;m_msgCur));<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
::DispatchMessage(&amp;(pState-&gt;m_msgCur));<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
return TRUE;<br/>
}<br/></SPAN><span STYLE="COLOR: #003300">可以看到，</SPAN><span STYLE="COLOR: #003300">PumpMessage</SPAN><span STYLE="COLOR: #003300">在实际的</SPAN><span STYLE="COLOR: #003300">TranslateMessage</SPAN><span STYLE="COLOR: #003300">和</SPAN><span STYLE="COLOR: #003300">DispatchMessage</SPAN><span STYLE="COLOR: #003300">发生之前会调用</SPAN><span STYLE="COLOR: #003300">AfxPreTranslateMessage</SPAN><span STYLE="COLOR: #003300">，</SPAN><span STYLE="COLOR: #003300">AfxPreTranslateMessage</SPAN><span STYLE="COLOR: #003300">又会调用</SPAN><span STYLE="COLOR: #003300">CWnd::WalkPreTranslateTree(</SPAN><span STYLE="COLOR: #003300">虽然也会调用其他函数，但是这个最为关键），其代码如下：</SPAN></FONT><span STYLE="FONT-SIZE: 10.5pt"><br/>

<span STYLE="COLOR: #003300"><font STYLE="FONT-SIZE: 16px">BOOL
PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)<br/>
{<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ASSERT(pMsg != NULL);</FONT></SPAN></SPAN></P>
<p><font STYLE="FONT-SIZE: 16px"><span STYLE="COLOR: #003300">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// walk from the target window up to the hWndStop window
checking<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if any window wants to translate this message</SPAN></FONT></P>
<p STYLE="MARGIN-BOTTOM: 12pt"><font STYLE="FONT-SIZE: 16px"><span STYLE="COLOR: #003300">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
for (HWND hWnd = pMsg-&gt;hwnd; hWnd != NULL; hWnd =
::GetParent(hWnd))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
{<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (pWnd != NULL)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
{<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// target window is a C++ window<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (pWnd-&gt;PreTranslateMessage(pMsg))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
return TRUE; // trapped by target window (eg: accelerators)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<br/>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// got to hWndStop window without interest<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if (hWnd == hWndStop)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
break;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
return
FALSE;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// no special processing<br/>
}<br/>
<br/></SPAN><span STYLE="COLOR: #003300">可以看到，代码还是很直接的。从接受到消息的窗口层层往上遍历，并调用</SPAN><span STYLE="COLOR: #003300">PretranslateMessage</SPAN><span STYLE="COLOR: #003300">看是否返回</SPAN><span STYLE="COLOR: #003300">TRUE</SPAN><span STYLE="COLOR: #003300">，是则结束，否则继续。</SPAN></FONT><span STYLE="FONT-SIZE: 10.5pt"><br/>
</SPAN><font STYLE="FONT-SIZE: 16px"><span STYLE="COLOR: #003300">这里有一个地方非常关键：</SPAN><span STYLE="COLOR: #003300">CWnd *pWnd =
CWnd::FromHandlePermanent(hWnd)</SPAN> <span STYLE="COLOR: #003300">这一句代码从当前</SPAN><span STYLE="COLOR: #003300">AfxModuleThreadState</SPAN><span STYLE="COLOR: #003300">拿到</SPAN><span STYLE="COLOR: #003300">Permanent</SPAN><span STYLE="COLOR: #003300">句柄表，从而找到</SPAN><span STYLE="COLOR: #003300">hWnd</SPAN><span STYLE="COLOR: #003300">对应的</SPAN><span STYLE="COLOR: #003300">CWnd</SPAN><span STYLE="COLOR: #003300">对象。关于</SPAN><span STYLE="COLOR: #003300">PreTranslateMessage</SPAN><span STYLE="COLOR: #003300">有一个常见的问题就是与此有关：如果编写了一个</SPAN><span STYLE="COLOR: #003300">MFC
DLL</SPAN><span STYLE="COLOR: #003300">并从另外的一个</SPAN><span STYLE="COLOR: #003300">MFC</SPAN><span STYLE="COLOR: #003300">主工程之中调用这个</SPAN><span STYLE="COLOR: #003300">MFC DLL</SPAN><span STYLE="COLOR: #003300">中的</SPAN><span STYLE="COLOR: #003300">Modeless
Dialog</SPAN><span STYLE="COLOR: #003300">的话，</SPAN><span STYLE="COLOR: #003300">Modeless Dialog</SPAN><span STYLE="COLOR: #003300">的</SPAN><span STYLE="COLOR: #003300">PreTranslateMessage</SPAN><span STYLE="COLOR: #003300">不会被调。因为</SPAN><span STYLE="COLOR: #003300">MFC DLL</SPAN><span STYLE="COLOR: #003300">和这个</SPAN><span STYLE="COLOR: #003300">MFC</SPAN><span STYLE="COLOR: #003300">工程拥有不同的</SPAN><span STYLE="COLOR: #003300">AfxModuleThreadState</SPAN><span STYLE="COLOR: #003300">，因此在</SPAN><span STYLE="COLOR: #003300">MFC
DLL</SPAN><span STYLE="COLOR: #003300">中创建的</SPAN><span STYLE="COLOR: #003300">modeless CDialog</SPAN><span STYLE="COLOR: #003300">对象不在</SPAN><span STYLE="COLOR: #003300">MFC</SPAN><span STYLE="COLOR: #003300">工程的句柄表中（</SPAN><span STYLE="COLOR: #003300">CWnd::FromhandlePermanent</SPAN><span STYLE="COLOR: #003300">返回</SPAN><span STYLE="COLOR: #003300">NULL</SPAN><span STYLE="COLOR: #003300">），因此虽然</SPAN><span STYLE="COLOR: #003300">MFC</SPAN><span STYLE="COLOR: #003300">主工程中的</SPAN><span STYLE="COLOR: #003300">CWinApp</SPAN><span STYLE="COLOR: #003300">的</SPAN><span STYLE="COLOR: #003300">Pretranslatemessage</SPAN><span STYLE="COLOR: #003300">会被调（注意此时</SPAN><span STYLE="COLOR: #003300">Dialog</SPAN><span STYLE="COLOR: #003300">的消息循环在</SPAN><span STYLE="COLOR: #003300">MFC</SPAN><span STYLE="COLOR: #003300">主工程里面），但是不会调用</SPAN><span STYLE="COLOR: #003300">MFC DLL</SPAN><span STYLE="COLOR: #003300">中创建的那个</SPAN><span STYLE="COLOR: #003300">modeless CDialog</SPAN><span STYLE="COLOR: #003300">的</SPAN><span STYLE="COLOR: #003300">PreTranslateMessage</SPAN><span STYLE="COLOR: #003300">函数。因此需要特殊处理。一般有两种方法，一种是直接在</SPAN><span STYLE="COLOR: #003300">MFC</SPAN><span STYLE="COLOR: #003300">主工程中的</SPAN><span STYLE="COLOR: #003300">CWinApp::PreTranslatemessage</SPAN><span STYLE="COLOR: #003300">里面调用</SPAN><span STYLE="COLOR: #003300">MFC
DLL</SPAN><span STYLE="COLOR: #003300">的</SPAN><span STYLE="COLOR: #003300">CWinApp::PreTranslateMessage</SPAN><span STYLE="COLOR: #003300">（可以专门在</SPAN><span STYLE="COLOR: #003300">MFC DLL</SPAN><span STYLE="COLOR: #003300">中</SPAN><span STYLE="COLOR: #003300">export</SPAN><span STYLE="COLOR: #003300">一个专门的函数来做这件事情）。另外的方法是使用钩子，在钩子消息处理函数之中，判断目标窗口是否是当前具有焦点的窗口，如果是，则直接调用目标窗口的</SPAN><span STYLE="COLOR: #003300">PreTranslateMessage</SPAN><span STYLE="COLOR: #003300">函数（前提是你有要保存这个对象的指针）。</SPAN></FONT></P>
</DIV>
<font STYLE="FONT-SIZE: 16px">1、CMusicWnd *ListWnd;<br/>
在DLL-CXXWNDAPP中用个全局的窗口指针<br/>
2、DLL中需要导出该一个接口涵数-<br/>
extern "C" _declspec(dllexport) BOOL List_PreTM(MSG
*pMsg)//PreTranslateMessage<br/>
{<br/>
//AFX_MANAGE_STATE(AfxGetStaticModuleState());<br/>
if(ListWnd!=NULL)<br/>
return ListWnd-&gt;PreTranslateMessage(pMsg);<br/>
return false;<br/>
}<br/>
3、主程序中用typedef BOOL(_cdecl *List_PreTM)(MSG
*pMsg);//导出函数<br/>
List_PreTM m_pList_PreTM;//导出函数指针<br/>
在BOOL CXXXDlg::OnInitDialog()中(主程序的对话框)<br/>
m_pList_PreTM =
(List_PreTM)GetProcAddress(hinstDll_List,"List_PreTM");<br/>
4、在主程序的<br/>
BOOL CXXXDlg::PreTranslateMessage(MSG* pMsg)<br/>
{<br/>
// TODO: Add your specialized code here and/or call the base
class<br/>
if(m_pList_PreTM(pMsg))<br/>
return true;<br/>
return CDialog::PreTranslateMessage(pMsg);<br/>
}<br/>
所有即可成功完成该过程。</FONT></DIV>
<div>&nbsp;</DIV>
]]></description>
            <author>idol</author>
            <category>编程技术</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901000aef.html#comment</comments>
            <pubDate>Thu, 15 Nov 2007 06:54:58 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901000aef.html</guid>
        </item>
        <item>
            <title>2007年周末午后茶  第十九篇</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901000a5t.html</link>
            <description><![CDATA[<DIV>
<P><FONT STYLE="FONT-SIZE: 16px" COLOR="#000000"><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff">&nbsp;zz
from Internet</FONT></FONT></P>
<P><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff"><br/>
<FONT STYLE="FONT-SIZE: 18px">重要角色</FONT></FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff">　　我邻居家的孩子一直在央求他的妈妈给他买新衣服，上衣是白衬衫，下面是黑色的短裤。</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff">　　他的妈妈说：“老师怎么会这样啊？”</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff">　　我问：“怎么了？”</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff">　　她说他们学校要搞拔河比赛，要求男孩儿一律要穿白衬衣黑短裤，但我的孩子不用啊，因为他长得瘦小，没有被选上参赛。她是不想买的。因为孩子有很多旧衣服，“我想这孩子虚荣心太强了，看见别人穿新衣服自己也要。”</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff">　　孩子哭了，边哭边说：“虽然我没有被选上参加拔河比赛，但老师说我是最重要的角色，没有我的鼓励，他们会没有力气的。”</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff">　　我一下感动了，这个老师是多么聪明而善良啊，既没有打击孩子的自信，还让他以为自己是很重要的角色，我相信这句话对这个孩子的一生都会影响甚大。</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff">　　其实，每个人都是很重要的角色啊。</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff">　　我们有时觉得自己是个可有可无的人。但是，我们有一天会终于明白，我们分明是父母最疼爱的儿女，是夫妻相濡以沫的伴侣，是同事的合作者，是朋友的倾诉者和倾听者……甚至，我们是无意间给陌生人一个微笑的过客，不也重要吗？</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px; BACKGROUND-COLOR: #ffffff">　　每个人都是重要的角色，无论你在哪个位置上。只是你该如何演好你自己的角色，那是一件更重要的事情.<br/>
</FONT></P>
<FONT SIZE="3"><SPAN LANG="EN-US" STYLE="FONT-SIZE: 12pt; COLOR: black" XML:LANG="EN-US">

</SPAN></FONT></DIV>
]]></description>
            <author>idol</author>
            <category>精彩文章</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901000a5t.html#comment</comments>
            <pubDate>Fri, 19 Oct 2007 09:11:43 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901000a5t.html</guid>
        </item>
        <item>
            <title>转弯时如何看红绿灯</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901000a5o.html</link>
            <description><![CDATA[<DIV><FONT STYLE="FONT-SIZE: 16px">右转车辆很简单，如果路口是圆灯，则随时都可以转；如果路口有右转箭头灯，则要等该灯变绿时方可右转。</FONT></DIV>
<DIV><br/>
<FONT STYLE="FONT-SIZE: 16px">左转比较复杂。如果路口只有圆灯，则待其变绿时，即可左转；如果路口有左转箭头灯，还要看地上是否有左转等待区，如果有，就可以在直行灯绿时，将车驶入等待区，待左转灯绿后，车辆左转；如果没有左转等待区，车就得一直在线后等着，一直等到左转灯绿时，才能左转。</FONT></DIV>
]]></description>
            <author>idol</author>
            <category>经验知识</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901000a5o.html#comment</comments>
            <pubDate>Fri, 19 Oct 2007 02:10:55 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901000a5o.html</guid>
        </item>
        <item>
            <title>电子警察的拍摄原理</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901000a5n.html</link>
            <description><![CDATA[<DIV><FONT STYLE="FONT-SIZE: 16px">1、电子眼采用感应线来感应路面上的汽车传来的压力，通过传感器将信号采集到中央处理器，送寄存器暂存（该数据在一个红灯周期内有效）；<br/>

2、在同一个时间间隔内（红灯周期内），如果同时产生两个脉冲信号，即视为“有效”，简单的说，就是如果当时红灯，你的头轮子过线了，而后轮子没出线，则只产生了一个脉冲，在没有连续的两个脉冲时，不拍照；<br/>

3、有些情况是：有的人开车前轮越过线了，怕被拍到，于是他又倒一下车，回到线内，结果还是被照了，什么原因？就是因为一前一后的，产生了“一对”脉冲信号（这一对脉冲是在同一个红灯周期内产生的）；<br/>

4、黄灯亮时，拍照系统延时2s后启动；红灯亮时，系统已经启动；绿灯将要亮时，提前2s关闭系统，防止误拍。所以很多的士司机都知道，差不多就可以走了，一样没事就这个道理。<br/>

<br/>
总而言之，老司机有一句话：闯红不闯绿！</FONT></DIV>
]]></description>
            <author>idol</author>
            <category>经验知识</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901000a5n.html#comment</comments>
            <pubDate>Fri, 19 Oct 2007 02:03:30 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901000a5n.html</guid>
        </item>
        <item>
            <title>学习的欲望真低</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901000a50.html</link>
            <description><![CDATA[<DIV><FONT STYLE="FONT-SIZE: 16px">　　感到周围的人都挺强的@_@，便有种强烈的学习的欲望，但是每次只能维持几分钟。。咋就没有学习的欲望呢。。。继续探索未来的定位中-_-</FONT></DIV>
]]></description>
            <author>idol</author>
            <category>随手涂鸦</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901000a50.html#comment</comments>
            <pubDate>Wed, 17 Oct 2007 08:22:55 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901000a50.html</guid>
        </item>
        <item>
            <title>十月的生活</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e901000a3r.html</link>
            <description><![CDATA[<DIV><FONT STYLE="FONT-SIZE: 16px">　　十月长假前半周去了威海，一个非常美丽的海滨城市，空气很好，没有北京那种窒息的感觉，生活安逸，节奏不是很快，所以休息的很爽，玩的很爽，把9月的郁闷一扫而光。总之，近150个小时的时间，每分钟都感到是那么的开心，那么的富有趣味。我想，很多年以后，都回想起来这段在威海的快乐时光。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　长假的后半周，在北京休息，开始逐渐适应北京的节奏，不然长假一结束，就恢复不过来了-_-开始尝试着自己烧东西吃，嘿嘿。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　结束长假后，生活按部就班，不像开学后的那个月的折腾，天气也渐渐变凉了。我喜欢这样的季节，安静，干净，晚上能看的特别远。大家也都喜欢呆在屋子里面，事情不多，有很多节日，日子过得有盼头。我喜欢样简单的规律的没多少干扰的生活，很满意，很开心~</FONT></DIV>
]]></description>
            <author>idol</author>
            <category>随手涂鸦</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e901000a3r.html#comment</comments>
            <pubDate>Mon, 15 Oct 2007 09:52:50 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e901000a3r.html</guid>
        </item>
        <item>
            <title>十一的计划</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e9010009qk.html</link>
            <description><![CDATA[<DIV><FONT STYLE="FONT-SIZE: 16px">　　去海边，踏海滩，吃海鲜。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　玩，睡，吃。</FONT></DIV>
]]></description>
            <author>idol</author>
            <category>随手涂鸦</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e9010009qk.html#comment</comments>
            <pubDate>Tue, 18 Sep 2007 05:05:20 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e9010009qk.html</guid>
        </item>
        <item>
            <title>2007年周末午后茶  第十八篇</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e9010009mx.html</link>
            <description><![CDATA[<DIV><FONT STYLE="FONT-SIZE: 16px">&nbsp;zz from
Internet</FONT></DIV>
<DIV>&nbsp;</DIV>
<P CLASS="MsoNormal" STYLE="WORD-BREAK: break-all"><FONT COLOR="black" SIZE="3"><FONT STYLE="FONT-SIZE: 16px"><SPAN>&nbsp;<SPAN STYLE="FONT-FAMILY: 宋体">&nbsp;&nbsp;</SPAN>
<FONT STYLE="FONT-FAMILY: 宋体">小时候看月亮，总觉得月亮神秘而美丽，于是仰头去追，可是我越追，月亮越是躲开我。母亲见了，对我说：“孩子，为什么</FONT></SPAN></FONT></FONT><FONT STYLE="FONT-SIZE: 16px; FONT-FAMILY: 宋体" COLOR="black" SIZE="3"><SPAN STYLE="COLOR: black; FONT-FAMILY:">要去追呢？如果你一心赶路，月亮自然会跟着你。”</SPAN></FONT></P>
<P CLASS="MsoNormal" STYLE="WORD-BREAK: break-all"><FONT STYLE="FONT-SIZE: 16px; FONT-FAMILY: 宋体" COLOR="black" SIZE="3"><SPAN STYLE="COLOR: black; FONT-FAMILY:">&nbsp;&nbsp;
一天，我赶夜路回家，突然想起来母亲的那句话，于是我回头看了一眼天上的月亮，发现月亮果然一路跟在我的身后。</SPAN></FONT></P>
<P CLASS="MsoNormal" STYLE="WORD-BREAK: break-all"><FONT STYLE="FONT-FAMILY: 宋体"><FONT STYLE="FONT-FAMILY: 黑体"><FONT STYLE="FONT-FAMILY: 宋体"><FONT STYLE="FONT-SIZE: 16px; FONT-FAMILY:"><SPAN STYLE="FONT-FAMILY:">&nbsp;
长大后，我从这件事上悟出了一些道理：如果把月亮比作一份荣耀，那么我们越是想着荣耀，越是贪婪地去追逐荣耀，荣耀反而会远离我们；如果我们能一心赶路，把人生之路走的更快更好，如果我们能专注的做好意见事情，把事情做的更加完美更加成功，属于我们的荣耀自然也就会尾随而来。</SPAN></FONT></FONT></FONT></FONT></P>
]]></description>
            <author>idol</author>
            <category>精彩文章</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e9010009mx.html#comment</comments>
            <pubDate>Fri, 07 Sep 2007 08:11:06 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e9010009mx.html</guid>
        </item>
        <item>
            <title>我的黄金时代结束了
</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e9010009mf.html</link>
            <description><![CDATA[<DIV><FONT STYLE="FONT-SIZE: 16px">　　纪念从06年9月到07年9月之间的忙碌生活。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　认识了很多人，很开心能和他们在一起做事情，一起出去玩，这种友谊在以后工作，生活中将更加弥足珍贵。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　学到了很多书本中学不到的东西，也积攒了很多经验，在视图继续下去的时候，好戏戛然终止，曾经也想到会有这种情况，但是在事实来临之前还是有点接受不了，心中的失落感倍增，不知道以后的日子将如何打发。有些东西如同鸡肋，无味但是确约束着你，让你无从适应，无法逃避。只能感叹自己生不逢时吧。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　虽然我失去了一些重要的东西，但是我仍然有对我最重要的人站在我一边，我的生活依然美好，并将继续美好。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　纪念一下我的黄金时代，相信以后会一直怀念的。</FONT></DIV>
<DIV>&nbsp;</DIV>
]]></description>
            <author>idol</author>
            <category>一点感想</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e9010009mf.html#comment</comments>
            <pubDate>Thu, 06 Sep 2007 04:35:43 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e9010009mf.html</guid>
        </item>
        <item>
            <title>抉择
</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e9010009lr.html</link>
            <description><![CDATA[<DIV><FONT STYLE="FONT-SIZE: 16px">　　明天，要经历好多事情，是好日子的继续，还是坏日子的开始，之后可以知道一些。好像命运的抉择一样，希望自己能继续保持比较好的运气，希望能尽量达到自己的目标，希望各种。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　God bless me！</FONT></DIV>
]]></description>
            <author>idol</author>
            <category>随手涂鸦</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e9010009lr.html#comment</comments>
            <pubDate>Tue, 04 Sep 2007 10:00:56 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e9010009lr.html</guid>
        </item>
        <item>
            <title>2007年周末午后茶  第十七篇</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e9010009lq.html</link>
            <description><![CDATA[<DIV>
<DIV>
<P><FONT STYLE="FONT-SIZE: 16px">zz from Internet</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px">不为薪水而工作，<FONT COLOR="black" SIZE="2">工作固然是为了生计，但是比生计更可贵的，就是在工作中充分挖掘自己的潜能，发挥自己的才干，做正直而纯正的事情。</FONT></FONT></P>
<P><FONT SIZE="2"><FONT STYLE="FONT-SIZE: 16px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
转：（美）阿尔伯特"哈伯德</FONT></FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px" COLOR="black" SIZE="2">一些年轻人，当他们走出校园时，总对自己抱有很高的期望值，认为自己一开始工作就应该得到重用，就应该得到相当丰厚的报酬。他们在工资上喜欢相互攀比，似乎工资成了他们衡量一切的标准。但事实上，刚刚踏入社会的年轻人缺乏工作经验，是无法委以重任的，薪水自然也不可能很高，于是他们就有了许多怨言。</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px" COLOR="black" SIZE="2">所以出现这种状况，原因在于人们对于薪水缺乏更深入的认识和理解。大多数人因为自己目前所得的薪水太微薄，而将比薪水更重要的东西也放弃了，实在太可惜。</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px" COLOR="black" SIZE="2">不要为薪水而工作，因为薪水只是工作的一种报偿方式，虽然是最直接的一种，但也是最短视的。一个人如果只为薪水而工作，没有更高尚的目标，并不是一种好的人生选择，受害最深的不是别人，而是他自己。</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px" COLOR="black" SIZE="2">一个以薪水为个人奋斗目标的人是无法走出平庸的生活模式的，也从来不会有真正的成就感。虽然工资应该成为工作目的之一，但是从工作中能真正获得的更多的东西却不是装在信封中的钞票。</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px" COLOR="black" SIZE="2">一些心理学家发现，金钱在达到某种程度之后就不再诱人了。即使你还没有达到那种境界，但如果你忠于自我的话，就会发现金钱只不过是许多种报酬中的一种，试着请教那些事业成功的人士，他们在没有优厚的金钱回报下，是否还继续从事自己的工作？大部人的回答是：“绝对是！我不会有丝毫改变，因为我热爱自己的工作。”想要攀上成功之阶，最明智的方法就是选择一件即使酬劳不多，也愿意做下去的工作。当你热爱自己所从事的工作时，金钱就会尾随而至。你也将成为人们竞相聘请的对象，并且获得更丰厚的酬劳。</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px" COLOR="black" SIZE="2">不要为薪水而工作。工作固然是为了生计，但是比生计更可贵的，就是在工作中充分发掘自己的潜能，发挥自己的才干，做正直而纯正的事情。如果工作仅仅是为了面包，那么生命的价值也未免太低俗了。人生的追求不仅仅只有满足生存需要，还有更高层次的需求，有更高层次的动力驱使。不要麻痹自己，</FONT></P>
</DIV>
<DIV>
<P><FONT STYLE="FONT-SIZE: 16px" COLOR="black" SIZE="2">告诉自己工人就是为赚钱-------人应该有比薪水更高的目标。</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px" COLOR="black" SIZE="2">工作的质量决定生活的质量。无论薪水高低，工作中尽心尽力、积极进取，能使自己得到内心的平安，这往往是事业成功者与失败者之间的不同之处。工作过分轻松随意的人，无论从事什么领域的工作都不可能获得真正的成功。将工作当作赚钱谋生的工具，这种想法本身就会让人蔑视。</FONT></P>
<P>&nbsp;</P>
<P><FONT STYLE="FONT-SIZE: 16px" COLOR="black" SIZE="2">事业成功人士的经验向我们揭示了这样一个真理：只有经历艰难困苦，才能获得世界上最大的幸福，才能取得最大的成就；只有经历过奋斗，才能取得成功。</FONT></P>
</DIV>
</DIV>
]]></description>
            <author>idol</author>
            <category>精彩文章</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e9010009lq.html#comment</comments>
            <pubDate>Tue, 04 Sep 2007 09:57:24 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e9010009lq.html</guid>
        </item>
        <item>
            <title>祝mm生日快乐</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e9010009jv.html</link>
            <description><![CDATA[<DIV>&nbsp;天天开心，永远幸福:)</DIV>
]]></description>
            <author>idol</author>
            <category>一点感想</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e9010009jv.html#comment</comments>
            <pubDate>Thu, 30 Aug 2007 15:08:28 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e9010009jv.html</guid>
        </item>
        <item>
            <title>住在大运村的感受</title>
            <link>http://blog.sina.com.cn/s/blog_53d9f7e9010009j3.html</link>
            <description><![CDATA[<DIV><FONT STYLE="FONT-SIZE: 16px">　　前天搬进来，住了2个晚上，说说感受。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　总体感觉挺好的，网络啥都很满意，桌子，家具都做的比较好，比较好整理，比公寓的家具啥都要好很多，顺手在旁边的格子里面放了几本书，到时候可以去看书。更要命的话，桌上还有那种感应式的台灯，在北京一年以后终于有台灯了，可以有好好学习的客观条件了，嘿嘿。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　宿舍同学也很nice，甲甲是原来宿舍的，标哥是原来其他宿舍的，人都很好，住的挺舒服的。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　不方便的是，热水需要烧了才能洗，比较费电费时间；楼层高，上下电梯需要时间；其他的暂时没发现。。。</FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT STYLE="FONT-SIZE: 16px">　　希望以后都能很开心的住下去。</FONT></DIV>
]]></description>
            <author>idol</author>
            <category>随手涂鸦</category>
            <comments>http://blog.sina.com.cn/s/blog_53d9f7e9010009j3.html#comment</comments>
            <pubDate>Tue, 28 Aug 2007 15:26:42 GMT+8</pubDate>
            <guid>http://blog.sina.com.cn/s/blog_53d9f7e9010009j3.html</guid>
        </item>
    </channel>
</rss>
