<?xml version="1.0" encoding="utf-8" ?><?xml-stylesheet type="text/xsl" title="XSL Formatting" href="/static_files/markdown/rss.xsl" media="all" ?>
<rss version="2.0">
    <channel>
        <title>stanleyxu 的秘密基地</title>
        <image>
            <link>https://blog.csdn.net/</link>
            <url>https://static-blog.csdn.net/images/logo.gif</url>
        </image>
        <description>　stay tuned ^^)</description>
        <link>https://blog.csdn.net/Stanley_Xu</link>
        <language>zh-cn</language>
        <generator>https://blog.csdn.net/</generator>
        <ttl>5</ttl>
        <copyright><![CDATA[Copyright &copy; Stanley_Xu]]></copyright>
        <pubDate>2018/03/26 01:02:52</pubDate>
                    <item>
                                <title><![CDATA[[原]Unicode 随想]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/2035925</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/2035925</guid>
                <author>Stanley_Xu</author>
                <pubDate>2008/01/11 06:48:00</pubDate>
                <description>
                    <![CDATA[
                    <p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">最近</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"> CodeGear 的工程师开始谈论[1][2][3][4][5] Delphi 全面支持 Unicode 的问题了。尽管这个是十年前的新闻，但对于 Delphi 的粉丝来说，迟到总比不到要强。本文是我对目前 Unicode 封装计划的一些看法。</span></p>
<div> </div>
<div><strong><span style="font-size:12pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">现状</span></strong></div>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">如果你不了解 </span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">AnsiString 和 WideString，请先去网上查阅相关资料。微软的 Visual C++ 在提供 Unicode 方案的时候，提供了一套宏机制[6]。在 Delphi 中也有类似的方法，比如大家最熟悉的 </span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">string/</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">Char/PChar。 </span></p>
<div align="center">
<table cellspacing="0" cellpadding="0" border="1" style="border:medium none;border-collapse:collapse;"><tbody><tr><td width="182" style="border:1pt solid #000000;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">类型</span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">/函数别名</span></strong></div>
            </td>
            <td width="182" style="border-style:solid solid solid none;border-color:#000000 #000000 #000000;border-width:1pt 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">未使用</span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">编译指令 </span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">UNICODE</span></strong></div>
            </td>
            <td width="182" style="border-style:solid solid solid none;border-color:#000000 #000000 #000000;border-width:1pt 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">使用编译指令 </span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">UNICODE[7]</span></strong></div>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">string</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">AnsiString</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">WideString</span></div>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Char</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">AnsiChar</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">WideChar</span></div>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">PChar</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">PAnsiChar</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">PWideChar</span></div>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">GetCommandLine</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">GetCommandLineA</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">GetCommandLineW</span></div>
            </td>
        </tr></tbody></table></div>
<div> </div>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">宽字节版的字符串类型和</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"> Windows API 函数很早就出现在 Delphi 中了。只是类型</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">/</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">函数别名一直只是对应到了传统的单字节</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"></span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">版本上。</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">简单来说，我们需要的是自由将类型</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">/</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">函数别名对应到单字节或者宽字节版本的数据类型上。</span></p>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">很多人想必和我一样对</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">“程序</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">全面支持</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"> Unicode</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">”</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">这个概念懵懵懂懂。这里所谓的支持，并不是说要让应用程序既可以在</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"> Windows9x 上运行，又可以在 WindowsXP 上显示 Unicode 字符。而是指一个应用程序应该针对 Windows9x 和WindowsXP 分别编译</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">单字节或者宽字节</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">版本。</span></p>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">“一版通杀”的解决方案比较的累人。首先，字符串相关的数据类型在程序内部都是以宽字节版本定义的。当在</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"> Windows9x 上调用 Windows API 的时候，开发者必须手动进行类型转换。这种做法费时费力，维护的工作量相当大。目前 Delphi 制作的兼容 Unicode 的应用程序，基本都采用这个方法。在此，要特地感谢一下牺牲最大的先驱 Troy 和他的 TntControl[8]。</span></p>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">比较可以接受的方案是编译二个版本。这样就的项目可以继续以</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"> Ansi 模式顺利编译。而新的项目，只要遵循国际化编程准则的，也都可以成功的编译出</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">单字节或者宽字节</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">版本。尽管在处理宽字节</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"> Windows API 函数的时候你需要加倍小心，比如有些数据类型要求</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">字符串指针包含</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">二个 </span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">#0</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">结束符，但比起“一版通杀”的工作量，你真的要偷笑了。</span></p>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">我实在不明白，究竟</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">CodeGear 叫苦了10年的 Unicode 的瓶颈到底在哪里？难道他们之前一直在往“一版通杀”的方向努力？</span></p>
<div> </div>
<div><strong><span style="font-size:12pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">UnicodeString  vs  WideString</span></strong></div>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">现有的 </span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">WideString (D4-D2007) 类型是个比较奇怪的东西。不同于 AnsiString，它为了兼容 COM 调用中常用的BSTR 类型，违背了引用计数原则。因此它就性能而言，完全无法与 AnsiString 相提并论[9]。想必是为了保证现有的项目能顺利在 Delphi2008 (codename Tiburon) 中通过，下个版本并不打算改造现有的 WideString，而是另起炉灶，引入一个新的类型 UnicodeString。我个人是强烈反对这个方案的。请看下面的表格</span></p>
<div align="center">
<table cellspacing="0" cellpadding="0" border="1" style="border:medium none;border-collapse:collapse;"><tbody><tr><td width="182" style="border:1pt solid #000000;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">类型别名</span></strong></div>
            </td>
            <td width="182" style="border-style:solid solid solid none;border-color:#000000 #000000 #000000;border-width:1pt 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">单字节版本</span></strong></div>
            </td>
            <td width="182" style="border-style:solid solid solid none;border-color:#000000 #000000 #000000;border-width:1pt 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">宽字节版本</span></strong></div>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">string</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">AnsiString</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">UnicodeString</span></div>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Char</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">AnsiChar</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">WideChar</span></div>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">PChar</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">PAnsiChar</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">PWideChar</span></div>
            </td>
        </tr></tbody></table></div>
<div> </div>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">显而易见，</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">UnicodeString 这个名字和 WideChar/PWideChar 是不一致的。我的想法是：CodeGear 应该把现有的WideString (D4-D2007) 命名成 BSTR，然后再引入一个全新的 WideString (即 UnicodeString) 以及一个新的类型别名 T_BSTR。</span></p>
<div align="center">
<table cellspacing="0" cellpadding="0" border="1" style="border:medium none;border-collapse:collapse;"><tbody><tr><td width="182" style="border:1pt solid #000000;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">类型别名</span></strong></div>
            </td>
            <td width="182" style="border-style:solid solid solid none;border-color:#000000 #000000 #000000;border-width:1pt 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">未使用</span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">编译指令 </span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">UNICODE</span></strong></div>
            </td>
            <td width="182" style="border-style:solid solid solid none;border-color:#000000 #000000 #000000;border-width:1pt 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">使用编译指令 </span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">UNICODE[7]</span></strong></div>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">string</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">AnsiString</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <p align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">WideString   (UnicodeString)</span></p>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Char</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">AnsiChar</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">WideChar</span></div>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">PChar</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">PAnsiChar</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">PWideChar</span></div>
            </td>
        </tr><tr><td width="182" style="border-style:none solid solid;border-color:#000000 #000000;border-width:medium 1pt 1pt;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">T_BSTR</span></div>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <p align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">WideString   (D4-D2007)</span></p>
            </td>
            <td width="182" style="border-style:none solid solid none;border-color:#000000 #000000;border-width:medium 1pt 1pt medium;padding:0in 5.4pt;">
            <div align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">BSTR</span></div>
            </td>
        </tr></tbody></table></div>
<div> </div>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">当你以单字节方式编译你的现有项目时，一切照旧，程序顺利编译。当你以宽字节方式编译同样的项目时，编译器会在</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"> BSTR 被强制转换成新的 WideString 发出警告或者错误提示。并要求开发者认真考虑是使用 BSTR 还是 WideString。 </span></p>
<div><strong><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">CodeGear 的工程师们，你们要三思后行。以前你们已经错过一次，现在不能一错再错啊！ </span></strong></div>
<div> </div>
<div><strong><span style="font-size:12pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">UTF-8  vs  UTF-16</span></strong></div>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">用 </span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">UTF-16 肯定好过 UTF-8。原因很简单，UTF-8 是一种给单字节系统提供双字节支持的权宜之计[10]。尽管它使用了可变长度定义一个字符，节约了部分的内存空间，但是它在编码和解码上需要花费更多的时间。一来一去，你说谁更加划算呢？</span></p>
<div> </div>
<div><strong><span style="font-size:12pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">Windows API 转换</span></strong></div>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">正如</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"> Delphi 的首席构架师 Allen[4] 所说，Windows API 函数别名会和 UnicodeString 一样被很好的处理。不过我希望今后的 Delphi 能有一种函数重定向指令，以方便开发者定义自己的单字节和宽字节函数版本。例如：</span></p>
<div><span style="font-size:9pt;line-height:115%;font-family:'Courier New';color:#008000;"> {$IFDEF UNICODE}</span></div>
<div><span style="font-size:9pt;line-height:115%;font-family:'Courier New';">    GetCommandLine <span style="color:#0000FF;">mapping</span> GetCommandLineA;</span></div>
<div><span style="font-size:9pt;line-height:115%;font-family:'Courier New';color:#008000;"> {$ELSE}</span></div>
<div><span style="font-size:9pt;line-height:115%;font-family:'Courier New';">    GetCommandLine <span style="color:#0000FF;">mapping</span> GetCommandLineW;</span></div>
<div><span style="font-size:9pt;line-height:115%;font-family:'Courier New';color:#008000;"> {$ENDIF}</span></div>
<div> </div>
<div><strong><span style="font-size:12pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">总结</span></strong></div>
<p><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';">在全面支持</span><span style="line-height:115%;font-family:'微软雅黑', 'sans-serif';"> Unicode 的过程中，确实会面临很多问题。既然微软在十年前就已经成功的解决了此问题，相信 CodeGear 的工程师不可能在今时今日仍然愁眉不展吧。让你的应用程序顺利支持 Unicode，你准备好了吗？</span></p>
<div> </div>
<div><strong><span style="font-size:12pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">参考资料</span></strong></div>
<div><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">[1] </span><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';"><a href="http://chrisbensen.blogspot.com/2007/11/unicode.html"><span style="line-height:115%;">http://chrisbensen.blogspot.com/2007/11/unicode.html</span></a></span></div>
<div><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">[2] </span><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';"><a href="http://chrisbensen.blogspot.com/2007/11/unicode-sizeof-is-different-than-length_15.html"><span style="line-height:115%;">http://chrisbensen.blogspot.com/2007/11/unicode-sizeof-is-different-than-length_15.html</span></a></span></div>
<div><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">[3] </span><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';"><a href="http://chrisbensen.blogspot.com/2007/11/unicode-sizeof-is-different-than-length.html"><span style="line-height:115%;">http://chrisbensen.blogspot.com/2007/11/unicode-sizeof-is-different-than-length.html</span></a></span></div>
<div><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">[4] </span><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';"><a href="http://blogs.codegear.com/abauer/2008/01/09/38845"><span style="line-height:115%;">http://blogs.codegear.com/abauer/2008/01/09/38845</span></a></span></div>
<div><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">[5] </span><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';"><a href="http://blogs.codegear.com/abauer/2008/01/09/38846"><span style="line-height:115%;">http://blogs.codegear.com/abauer/2008/01/09/38846</span></a></span></div>
<div><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">[6] </span><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';"><a href="http://msdn2.microsoft.com/en-us/library/c426s321%28VS.80%29.aspx"><span style="line-height:115%;">http://msdn2.microsoft.com/en-us/library/c426s321(VS.80).aspx</span></a></span></div>
<div><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">[7] 该编译指令目前仍然不可用。</span></div>
<div><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">[8] </span><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';"><a href="http://www.tmssoftware.com/tmsuni.htm"><span style="line-height:115%;">http://www.tmssoftware.com/tmsuni.htm</span></a></span></div>
<div><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">[9] </span><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';"><a href="http://tobias.feedian.com/2007/05/24/whats-wrong-with-delphis-widestring/"><span style="line-height:115%;">http://tobias.feedian.com/2007/05/24/whats-wrong-with-delphis-widestring/</span></a></span></div>
<div><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';">[10] </span><span style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';"><a href="http://en.wikipedia.org/wiki/Utf8"><span style="line-height:115%;">http://en.wikipedia.org/wiki/Utf8</span></a></span></div>
<div> </div>
<div style="margin:3pt 1.5pt .0001pt;"><a href="http://stanleyxu2005.blogspot.com/2008/01/random-thoughts-on-unicode_10.html"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">点击这里查看本文的英文版本</span></a></div>
<div> </div>                    <div>
                        作者：Stanley_Xu 发表于 2008/01/11 06:48:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/2035925">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/2035925                    </div>
                    <div>
                        阅读：2233 评论：1 <a href="https://blog.csdn.net/Stanley_Xu/article/details/2035925#comments" target="_blank">查看评论</a>                    </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]查询接口小议]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1722313</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1722313</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/08/02 11:59:00</pubDate>
                <description>
                    <![CDATA[
                    <div style="margin-bottom:.0001pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">前面的废话</span></strong></div>
<p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">接口大大增强了类设计的灵活性，类似于</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">c++</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">中的多重继承。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">不管你是否真正了解接口</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (Interface)</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，但它已经默默的在为你的程序服务了。你可以去看一下</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> TComponent </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的定义部分，你会发现它内部已经封装了</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">2</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">个接口：</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">IInterface, IInterfaceComponentReference</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">不难发现，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Delphi </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">中除了原子类 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">TObject </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">之外，任何</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">类有且只有一个父类，但同时它可以拥有</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">0..n</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">个接口。接口是一组抽象的函数集，不能被实例化，函数实现部分必须由它的实现类或间接实现</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">外包</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">) </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">类完成。</span></p>
<div style="margin-bottom:.0001pt;line-height:150%;"><strong> </strong></div>
<div style="margin-bottom:.0001pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">如何查询接口</span></strong></div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">先请看下面的代码：</span></div>
<p style="margin-bottom:.0001pt;line-height:150%;"><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">type</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   IHello = </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">interface</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">(IUnknown)<br />     [</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#800000;">'{1EE7A0AA-F525-4DD5-AB1B-900348BF8322}'</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">]<br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Hello;<br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br />   <br />   THello = </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">class</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">(TObject, IHello)<br />     </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">// Implements IHello</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Hello;<br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> UnSafeInftCall(Obj: TObject);<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">// Case 1</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   Obj.Hello; </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">//&lt;-- Syntax error</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">// Case 2</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   THello(Obj).Hello;<br />   </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">// Case 3</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   IHello(Obj).Hello;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> SafeInftCall(Obj: TObject);<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   pIntfHello: IHello;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">// Case 4</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Obj.GetInterface(IHello, pIntfHello) </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     pIntfHello.Hello;<br />   </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">// Case 5</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">try</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     pIntfHello := Obj </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">as</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> IHello;<br />     pIntfHello.Hello;<br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">except</span></strong> <strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">; <br />   </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">// Case 6</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Supports(Obj, IHello, pIntfHello) </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     pIntfHello.Hello;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;</span></p>
<div style="margin-bottom:.0001pt;line-height:150%;"> </div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">前面</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">3</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">种情况都是不安全的接口函数调用，这里就不仔细说了。</span></div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">情况</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">4</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">：这种方法是最直接的。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">GetInterface </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">函数会去</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> VMT </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">中寻找是否定义过 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">IHello </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">这个接口，如果找到的话，并且把实现者的实例返回到</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> pIntfHello </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">中。这样就可以安全的使用了。</span></div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">情况</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">5</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">：这里使用了保留字</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> as </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">进行强制类型转换。如果转换失败运行期会丢出异常，我们可以通过</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> try…except </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">处理掉异常。其实 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">as </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">内部机制就是调用了</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> _IntfCast</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，只是比情况</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">4 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">多了一个抛出异常而已。</span></div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">情况</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">6</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">：可以通过</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Supports </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">函数查询接口。于情况</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">4</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">不同的是</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Supports </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">会自动检查</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Obj </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">是否是个有效的实例，帮你省了一行代码。（但是这个函数会让你在接口转换时付出其它额外的代价）</span></div>
<div style="margin-bottom:.0001pt;line-height:150%;"> </div>
<div style="margin-bottom:.0001pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">使用</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Supports </span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">2</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">个问题</span></strong></div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">这个问题的发现实出偶然：网友许子健设计的一个接口应用中统一使用了</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> as 进行转换，而我当时推荐他使用 Supports，因为 Supports 在查询接口失败后并不抛异常，而是返回 False。虽然只是小小的代码改动，但是他的程序意外崩溃了。</span></div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">请看下面的代码</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">：</span></div>
<p style="margin-bottom:.0001pt;line-height:150%;"><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">type</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   THelloImplementor = </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">class</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">(TInterfacedObject, IHello)<br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">public</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Hello;<br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> TestMe;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   Obj: THelloImplementor;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   Obj := THelloImplementor.Create;<br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">try</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Supports(Obj, IHello) </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">then</span></strong> <span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">//&lt;-- Obj.Destroy is called</span></p>
<p style="margin-bottom:.0001pt;text-indent:21pt;line-height:150%;"><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />       </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">// Own code</span></p>
<p style="margin-bottom:.0001pt;text-indent:21pt;line-height:150%;"><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">finally</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     ShowMessage(Obj.ClassName); </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">//&lt;-- Crashed!</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> <br />     Obj.Free; <br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">; </span></p>
<div style="margin-bottom:.0001pt;line-height:150%;"> </div>
<p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">奇怪吗，为什么用</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Supports 查询接口出错了呢？通过调试发现，在执行 Supports </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">之后，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Obj </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的实例被意外的释放了。于是乎意外应该是在</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Supports </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">之内发生的。现在我们来看一下</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Supports </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的实现：</span></p>
<p style="margin-bottom:.0001pt;line-height:150%;"><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">function</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Supports(</span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">const</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Instance: TObject; </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">const</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> IID: TGUID): Boolean; </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">overload</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   Temp: IInterface;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   Result := Supports(Instance, IID, Temp); <br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;</span></p>
<div style="margin-bottom:.0001pt;line-height:150%;"> </div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">当执行 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Result := Supports(Instance, IID, Temp) 时，Temp 这个接口指针指向 Instance (</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">即</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Obj)，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">同时因为接口引用计数的关系</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Obj.FRefCount </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">加一。当离开</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Supports </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">函数时</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">本地变量指针</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Temp </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">会被清除</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">于是</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Obj.FRefCount </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">减一。<span style="color:#FF0000;">这个加一减一表面上没有差别，但是你完全无法预计</span></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;"> Instance </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">内部会对</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;"> FRefCount </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">的变化做什么样的处理。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">而恰恰 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Obj </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">是从臭名昭著的 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">TInterfacedObject </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">继承来的。这个类会当</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> FRefCount=0 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">时释放掉实例本身。这个就是该程序出错的真正原因。</span></div>
<div style="margin-bottom:.0001pt;line-height:150%;"> </div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">好了，下面再介绍一个隐藏的比较深的问题。这个和接口的委托机制有关。请看下面的代码</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">：</span></div>
<p style="margin-bottom:.0001pt;line-height:150%;"><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">type</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   TVirtualImplementor = </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">class</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">(TInterfacedObject</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">{TObject does not have problem}</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">, IHello)<br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">public</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     FImplementorOfIHello: THelloImplementor;<br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">property</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> ImplementorOfIHello: THelloImplementor </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">read</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> FImplementorOfIHello </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">implements</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> IHello; </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">//&lt;-- Be careful!</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> <br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> TestMe;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   VI: TVirtualImplementor;<br />   pIntfHello: IHello;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   VI := TVirtualImplementor.Create;<br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">try</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">// Method 1</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">try</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />       pIntfHello := VI </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">as</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> IHello;<br />       pIntfHello.Hello;<br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">except end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br />     </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">// Method 2</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Supports(VI, IHello, pIntfHello) </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">then</span></strong> <span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">//&lt;-- VI.Destroy is called</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />       pIntfHello.Hello;<br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">finally</span></strong></p>
<p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">    ShowMessage(VI.ClassName); </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">//&lt;-- Crashed!</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> <br />     VI.Free; <br />   </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">; </span></p>
<div style="margin-bottom:.0001pt;line-height:150%;"> </div>
<p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">如果使用</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> as 做类型转换，程序是可以顺利运行的。但是为什么用 Supports 就出错了呢？我们应该会很自然的联想上面那个问题。但问题是，这次接口指针 pIntfHello 实实在在地获得了接口，而且在 VI 释放之前并没有清除，也就是说 VI 不应该同上面的情况一样被自动销毁的。那么我们就再</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">看一下</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Supports </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的实现：</span></p>
<p style="margin-bottom:.0001pt;line-height:150%;"><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">function</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Supports(</span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">const</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Instance: TObject; </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">const</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> IID: TGUID; </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">out</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Intf): Boolean; </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">overload</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   LUnknown: IUnknown;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />   Result := (Instance &lt;&gt; </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">nil</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">) </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">and</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />             ((Instance.GetInterface(IUnknown, LUnknown) </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">and</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Supports(LUnknown, IID, Intf)) </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">or</span></strong> <span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">//&lt;-- RefCount changed!</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />              Instance.GetInterface(IID, Intf)); <br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;</span></p>
<div style="margin-bottom:.0001pt;line-height:150%;"> </div>
<p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">倒数第三行的地方，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">Supports 并不是直接通过 Instance </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">去查询是否支持</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">IHello </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">接口的</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">而是</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;">先去查询</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';color:#FF0000;"> Instance 是否支持 IUnknown，然后通过 IUnknown 去查询 IHello接口。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">我不清楚</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Delphi </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">为什么这样处理。</span></p>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">现在我们手动调试程序：</span></div>
<p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">当执行</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Instance.GetInterface(IUnknown, LUnknown) </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">之后，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">LUnknown </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">指针指向了 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Instance (</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">即</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> VI)</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，同时因为接口引用计数的关系 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">VI.FRefCount </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">加一。</span></p>
<p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">然后程序继续执行 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Supports(LUnknown, IID, Intf)</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">。这时</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Intf </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">指针指向了</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">IHello </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的真正实现者 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">VI.FImplementorOfHello</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，同样的的，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">VI.FImplementorOfHello.FRefCount </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">加一。</span></p>
<p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">当查询成功离开 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Supports </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">函数时，本地变量指针 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">LUnknown </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">会被清除，于是</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> VI.FRefCount </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">减一。不巧的是</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> VI </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">也是由 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">TInterfacedObject </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">继承来的……。种种不幸最终酿成又一场惨祸。</span></p>
<div style="margin-bottom:.0001pt;line-height:150%;"> </div>
<div style="margin-bottom:.0001pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">最后总结</span></strong></div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">这篇文章除了要介绍一下接口的查询方法外，主要是要想交代一下我在具体使用接口中发现的一些问题。上述代码中包涵了</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">3</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">个问题：<br /></span><p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">(1) TInterfacedObject </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">由于会在</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> FRefCount=0 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">时释放掉对象实例，所以在使用上要格外小心。建议重新封装一个</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">TInterfacedObjectEx</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，或者改用 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">TComponent</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">。</span></p>
<p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">(2) </span></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Supports </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">内部这行代码虽不知其用意，但显然是不安全的！尤其是在使用委托机制实现接口封装的时候。<strong><span style="color:#FF0000;">说明：我暂时无法证明去掉有问题的这行是否能保证不引入其它问题。</span></strong></span></p>
<p style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">(3) </span></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">上述代码设计上的问题是：既然 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">TVirtualImplementor </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">把接口的实现工作委托</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">外包</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">) </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">给了</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> TRealImplementor</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，那么</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">TVirtualImplementor </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">就应该定义成 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">TObject</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">。尽管程序可以运行，但是逻辑上还是有些不通。</span></p>
<br /></div>
<div style="margin-bottom:.0001pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">此外，委托</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (implements) </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">这个概念挺有意思，它提高了接口的复用度。有时间的话，我会详细再写一篇介绍。</span></div>
<div style="margin-bottom:.0001pt;line-height:150%;"> </div>                    <div>
                        作者：Stanley_Xu 发表于 2007/08/02 11:59:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1722313">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1722313                    </div>
                    <div>
                        阅读：1941 评论：1 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1722313#comments" target="_blank">查看评论</a>                    </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]可能你不知道的内存泄漏]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1699834</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1699834</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/07/20 02:53:00</pubDate>
                <description>
                    <![CDATA[
                    <div style="margin:0in 0in 0pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">
</span></strong><div style="margin:0in 0in 10pt;line-height:150%;"><strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Delphi <strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">是如何管理</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的？</span></strong></span></strong></strong></div><strong>
</strong><div style="margin:0in 0in 10pt;line-height:150%;"><strong> </strong></div><strong>
</strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">为了提高</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string 的读写性能 Delphi 采用了 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><font color="#800080"><a href="http://en.wikipedia.org/wiki/Copy-on-write">Copy-on-Write</a> </font></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">机制进行内存管理。<span style="color:#008000;">简单来说，在复制一个</span></span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">时并不是真的在内存中把原来</span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的内容复制一份到另外一个地址，而是把新的</span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">在内存映射表中指向同原</span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">相同的位置，并且把那块内存的引用计数加一。这样就省去了复制字符串的时间。只有当</span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的内容发生变化的时候，才真正将改动的内容完整复制一份到新的地址，然后对原地址的引用计数减一，将新地址的引用计数设为一，最后将新</span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">在内存映射表中指向这个新的位置。当某个字符串内存块的引用计数为零了，这块内存就可以被其它程序使用了。</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">注意：所有常量</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">会在编译时率先分配内存，其引用计数不会在程序中变化，始终为</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">-1</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">更详细的介绍，可以参考『</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><a href="http://book.chinaz.com/others/Pascal/ch07str.htm">Pascal <span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">精要</span></a></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">』和『</span><font color="#800080"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><a href="http://blog.csdn.net/haoel/archive/2004/06/23/24058.aspx">标准<span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">C++</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">类</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">std::string</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的内存共享和</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Copy-On-Write</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">技术</span></a></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">』。</span></font> </div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong> </strong></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">内存泄漏的发现：</span></strong></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">在检查内存泄漏时，无意发现了使用记录过程中产生的内存泄漏。请看如下代码：</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">type</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> <br />  TMyRec = </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">record</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    S: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">string</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />    I: Integer;<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">procedure</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> Test;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">var</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  ARec: TMyRec;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin<br /></span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">  FillChar(ARec, SizeOf(ARec), </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">);<br />  ARec.S := </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'abcd'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />  ARec.I := </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1234</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />  </span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">// ...<br /></span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">  FillChar(ARec, SizeOf(ARec), </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">); </span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">//&lt;--- A leak!</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  </span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">// ...</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">FillChar 的作用是对一个内存块进行连续赋值，内存泄漏出现在第二次调用 FillChar 的时候。经过调试后发现：如果把记录中的 string 字段改成 Pchar 或者删除，就不再有内存泄漏了。</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"> </div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">原因分析：</span></strong></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">我们现在先了解一下记录在内存中是如何分配的。记录是个不同数据类型的集合体。记录长度就是每个字段的内存长度之和。<span style="color:#FF0000;">注意，</span></span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">该</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">长度在编译之前就已经是确定的。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">因此那些长度不定的类型</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">如</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string、对象</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">) </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">都是</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">以指针形式出现在记录中。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">我的分析是：<span style="color:#008000;">由于</span></span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> FillChar </span><span style="font-size:10pt;color:#008000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">是低级内存读写操作，它仅仅把记录所占的内存块清掉，但没通知编译器更新字符串的引用计数，因而造成了泄漏。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">请看如下代码：</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">function</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> StringStatus(</span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">const</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> S: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">string</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">): </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">string</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  Result :=<br />    Format(</span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'Addr: %p, RefCount: %d, Value: %s'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">,<br />      [Pointer(S),<br />       PInteger(Integer(S) - </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">8</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">)^,<br />       S]);<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">procedure</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> BadExample1;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">var</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  S1: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">string</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />  ARec: TMyRec;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin<br /></span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">  S1 := Copy(</span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'string'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">, </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">, </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">6</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">); </span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">// Force allocates memory for the string</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  WriteLn(StringStatus(S1));<br />  ARec.S := S1;<br />  WriteLn(StringStatus(ARec.S));<br />  FillChar(ARec, SizeOf(ARec), </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">);<br />  WriteLn(StringStatus(S1));<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:9pt;color:rgb(23,54,93);line-height:150%;font-family:'Courier New';">Addr: 00E249E8, RefCount: 1, Value: string // OK, Allocated as a new string<br />Addr: 00E249E8, RefCount: 2, Value: string // OK, RefCount increated<br />Addr: 00E249E8, RefCount: </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">2</span><span style="font-size:9pt;color:rgb(23,54,93);line-height:150%;font-family:'Courier New';">, Value: string // WRONG! RefCount should be 1</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">在执行</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> FillChar 之前，字符串 S1 的引用计数是2，但是执行 FillChar 之后并没有减1。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">这段代码验证了我的推测</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">：</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">FillChar </span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">操作可能会破坏字符串的</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Copy-on-Write </span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">机制</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">使用的时候需要倍加小心</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">！</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"> </div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">进一步分析：</span></strong></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">文章开头我提到 </span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">“所有有常量</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">会在编译时率先分配内存，其引用计数不会在程序中变化，始终为</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">-1</span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">。“ </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">那么如果我们让</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> S1 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">和</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> ARec.S </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">都赋值为一个常量字符串，那么照理说就不用管引用计数，也就没有泄漏问题了。请接着看下面这个例子：</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">procedure</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> BadExample2;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">var</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  S1: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">string</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />  ARec: TMyRec;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin<br /></span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">  S1 := </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'string'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">; </span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">// Assigns S1 to a const (compiler time allocated) string</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> <br />  WriteLn(StringStatus(S1));<br />  ARec.S := S1;<br />  WriteLn(StringStatus(ARec.S));<br />  FillChar(ARec, SizeOf(ARec), </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">);<br />  WriteLn(StringStatus(S1));</span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';"> <br />end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:9pt;color:rgb(23,54,93);line-height:150%;font-family:'Courier New';">Addr: 0040CCBC, RefCount: -1, Value: string // OK, RefCount UN-changed<br />Addr: </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">00E24B08</span><span style="font-size:9pt;color:rgb(23,54,93);line-height:150%;font-family:'Courier New';">, RefCount:  </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span><span style="font-size:9pt;color:rgb(23,54,93);line-height:150%;font-family:'Courier New';">, Value: string // !!! Allocated as a new string<br />Addr: 0040CCBC, RefCount: -1, Value: string // OK, RefCount UN-changed</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">是不是很吃惊？对赋值 <span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">ARec.S </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的时候，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">结果并不是预期的那样，</span></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">直接将其指向常量字符串，而是重新分配了一个新的字符串。我个人认为：<span style="color:#FF0000;">记录在对字符串赋值上是有问题的！</span></span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"> </div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">解决方法：</span></strong></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">既然知道使用 FillChar 来初始化记录是不安全的，那么我们是不是要回到解放前，手动对记录进行初始化呢？也不用。Delphi 有个保留字 out。它和 var、const 一样，是用来修饰函数参数的。它和 var 的功能相似，不同是，它会对那些以指针形式传入的变量先进行引用计数清理。Delphi 的帮助中解释道：<span style="color:rgb(0,112,192);">An out parameter, like a variable parameter, is passed by reference. With an out parameter, however, the initial value of the referenced variable is discarded by the routine it is passed to. The out parameter is for output only; that is, it tells the function or procedure where to store output, but doesn't provide any input.</span> </span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">哈哈，这个不正是 FillChar 想要但又做不到的吗？于是我改造了一个 InitializeRecord 来初始化记录。</span></div>
<div style="margin:0in 0in 10pt 35.4pt;line-height:150%;"><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">procedure</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> InitializeRecord(</span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">out</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> ARecord; count: Integer</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">);<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  FillChar(ARecord, count, </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">);<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">仅仅是多了一层函数嵌套，内存泄漏问题就解决了。多亏了这个神奇的 </span><span style="font-size:10pt;color:#FF0000;line-height:150%;font-family:'微软雅黑', 'sans-serif';">out</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">！
</span><div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">我们来仔细看看加了</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> out </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">之后，编译器到底做了什么？</span></div>
<div style="margin:0in 0in 10pt 35.4pt;line-height:150%;"><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">mov  edx,[</span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">$</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0040</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">c904]<br />mov  eax,ebx<br />call @FinalizeRecord</span><font face="Courier New"><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">  </span></font><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">//&lt;----- cleanup</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />mov  edx,</span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">$</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0000000</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">c<br />call InitializeRecord </span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">关键就是第三行调用了 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">FinalizeRecord</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">。这是</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> System.pas </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">中的一个汇编函数，作用就是对记录做一下清理工作。如果你想探个究竟，可以查看一下这个函数是如何实现的。这里就不作详解了。</span></div>
</div>
<div style="margin:0in 0in 10pt;line-height:150%;"> </div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">想法总结：</span></strong></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">没想到一个偶然的发现，竟可以带出这么多问题，真是因祸得福。我总价一下几点想法：</span></div>
<ol><li>
    <div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">FillChar </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">是低级的内存读写，所以在使用之前你要非常清楚要打算干什么。</span></div>
    </li>
    <li>
    <div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">在记录类型中慎用</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">和</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Widestring。如果记录的结构复杂，不妨尝试封装成类，类可以提供更丰富的特性，扩展性更佳。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">如果一定要定义带 string 的记录，最好注释一下，以免日后出错。(有时候的确是记录更方便和高效)</span></div>
    </li>
    <li>
    <div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">活用 out 保留字可以解决</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">接口类型和带</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> string </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的记录类型的引用计数问题。</span></div>
    </li>
</ol><br /><a href="http://stanleyxu2005.blogspot.com/2008/01/potential-memory-leak-by-initializing.html"><span style="font-weight:bold;">点击这里英文版本</span></a>                    <div>
                        作者：Stanley_Xu 发表于 2007/07/20 02:53:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1699834">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1699834                    </div>
                    <div>
                        阅读：3001 评论：8 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1699834#comments" target="_blank">查看评论</a>                    </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]你的单例足够单吗]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1604060</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1604060</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/05/11 09:41:00</pubDate>
                <description>
                    <![CDATA[
                    <div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">什么是单例：<br /></span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">单例模式（</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Singleton</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">）是一种常用的软件设计模式。在应用这个模式时，单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象，这样有利于我们协调系统整体的行为。实现单例模式的思路是：一个类能返回对象一个引用</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">(</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">永远是同一个</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">)</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">和一个获得该实例的方法（必须是静态方法，通常使用</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">getInstance</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">这个名称）；当我们调用这个方法时，如果类持有的引用不为空就返回这个引用，如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用；同时我们还将该类的构造函数定义为私有方法，这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象，只有通过该类提供的静态方法来得到该类的唯一实例。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">[</span><a href="http://zh.wikipedia.org/wiki/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">wikipedia</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">]</span></a></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Delphi </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">源码中的单例应用：</span></div>
<div style="margin:0in 0in 10pt 35.4pt;line-height:150%;"><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">var</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  FClipboard: TClipboard;<br /><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">function</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> Clipboard: TClipboard;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> FClipboard = </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">nil</span></strong> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    FClipboard := TClipboard.Create;<br />  Result := FClipboard;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;</span><span style="font-size:9pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span> </div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></strong></div>
<div style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></strong></div>
<p style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><br /><br />问题的提出：<br /></span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">上述代码不是线程安全的。假设</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> A </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">率先调用函数 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Clipboard</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，局部变量 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">FClipboard</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">会先进行实例化。在实例尚未完全创建完之前，如果</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> B </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">也尝试调用函数</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Clipboard</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，那么它也会去对</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> FClipboard </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">进行实例化。因为变量</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">FClipboard</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">此时依然为空指针。于是乎</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">A</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">、</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">B</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">分别创建了一个</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> TClipboard </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的实例，单例不再单！其中的一个并且变成了一个内存泄漏。这种泄漏往往发送在构建函数需要耗费较长时间的情况下。如何将上述代码改成线程安全的呢？其实可以通过加入临界区处理来解决</span></p>
<p style="margin:0in 0in 10pt 35.4pt;line-height:150%;"><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">var<br />  </span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">FClipboard: TClipboard;<br />  GClipboardLocker: TRTLCriticalSection;<br /><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">function</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> Clipboard: TClipboard;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin<br /></span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> FClipboard = </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">nil</span></strong> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then<br />  begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />   EnterCriticalSection(GClipboardLocker);<br />   </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">try</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />     </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> FClipboard = </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">nil</span></strong> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />       FClipboard := TClipboard.Create;<br />   </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">finally</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />     LeaveCriticalSection(GClipboardLocker);<br />   </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;</span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';"><br /> end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />  Result := FClipboard ;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">initialization</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  InitializeCriticalSection(GClipboardLocker);<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">finalization</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  DeleteCriticalSection(GClipboardLocker);<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">.</span> </p>
<p style="margin:0in 0in 10pt;line-height:150%;"><strong> </strong></p>
<p style="margin:0in 0in 10pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">小结：<br /></span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">单例模式简约而不简单，当开发往多线程延伸之后，可能还会爆出更多的问题。单例就是一个全局变量，建议不要滥用，否则软件的层次结构会被破坏。</span></p>                    <div>
                        作者：Stanley_Xu 发表于 2007/05/11 09:41:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1604060">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1604060                    </div>
                    <div>
                        阅读：2085 评论：1 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1604060#comments" target="_blank">查看评论</a>                    </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]如何访问私有成员变量和函数 (修正版)]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1557107</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1557107</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/04/09 00:49:00</pubDate>
                <description>
                    <![CDATA[
                    <div style="line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">这篇文章介绍一些</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Delphi </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">穿透</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> OOP </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">约束的技巧。</span></div>
<div style="line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></div>
<div style="line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></div>
<div style="line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">访问保护的</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (protected) </span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">变量</span></strong></div>
<div style="line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">如果是某个类的保护变量，可以在任何地方，通过如下方法访问：</span></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">type</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  TSomeClassAccess = </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">class</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">(TSomeClass);<br /><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  TSomeClassAccess(Object1).protected_Bool := False;<br />  TSomeClassAccess(Object1).protected_Int  := </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />  ...<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /><br /></span></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><strong> </strong></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">访问私有的</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (private) </span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">变量</span></strong></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">如果是某个类的私有变量，我们需要计算该变量在</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> VMT </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">中的偏移量。同时由于类声明可能在不同的</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Delphi </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">版本中也有所不同，所以最好事先先检查一下源码。例：访问</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> TMenuItem </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的第二个内部成员变量</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> FHandle</span></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">type</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  THackMenuItem = </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">class</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">(TComponent)<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">protected</span></strong> <span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">//&lt;-- change to protected </span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    FxxxxCaption: AnsiString;<br />    FHandle: HMENU; </span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">//&lt;-- the property you want to access</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  THackMenuItem(AMenuItem).FHandle := 0;<br />  ...<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /><br /></span></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><strong> </strong></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">访问部分私有的</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (private) </span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">函数</span></strong></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">访问私有函数要相对困难许多。据我所知只有</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">定义时声明为</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> virtual</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">、</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">override</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">、</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">dynamic</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">、</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> message </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">私有函数才可以被访问或替换。其实现</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">原理和访问私有变量相似：先计算该函数在</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> VMT/DMT </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">中的偏移量</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">然后把该内存地址替换成新函数的内存地址。具体做法可以参考</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> TntControls </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">中</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> TntSystem.pas </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">安装系统补丁</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">或者是</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Fastcode </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">控件包。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><br /></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">友情提醒：</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">(1) </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">通常私有函数中会涉及到一些访问其它的私有函数</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">/</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">变量。往往为了访问一个私有函数，还需要修改更多个私有函数</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">/</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">变量。相对比较复杂，也不很可靠。</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">(2) </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">内存地址修改不当会引发于一些软件的冲突，如 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">AQTime</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">。</span></div>
<div style="line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">注：如果变量定义时未设置关键字 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">strict</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，同一个单元里面的所有类的内部变量</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">/</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">函数可以直接相互访问。这个是</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Delphi </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">开的一个不大不小的后门。</span></div>
<div style="line-height:150%;"> </div>
<div style="line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></strong></div>
<div style="line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">增加私有的</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (private) </span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">函数</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (a)</span></strong></div>
<div style="line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">我们真的需要吗？有时候要！比如我在写一个</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Dunit </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">单元测试的时候，需要接受</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> WM_COPYDATA </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">消息。但是这个消息是发送给 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">GUITestRunner </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的，我必须打入</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> GUITestRunner </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">才可以得到相应消息。实现方法和访问私有函数类似，我们计算</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> VMT/DMT </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的长度，在尾端增加一个新的函数指针。我在网上找到一篇文章说的比较详细，请</span><a href="http://hallvards.blogspot.com/2007/03/hack15-overriding-message-and-dynamic.html"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><font color="#800080">点击这里查看</font></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">。这个方法有个限制：这个修改不是编译期完成的，你必须在类实例化之后，才进行修改。如果这个类被频繁使用，这个做法显然有些麻烦。如果能把这段修改代码放如类的构析函数中，问题就迎刃而解了。我在假想：我们是否可以使用介绍</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">3</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">中引入的方法，实现这个……</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><br /><br /></span></a></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"></span></strong></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">增加私有的</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (private) </span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">函数</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> (b)</span></strong></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">还有一种更干净的修改方法，我们定义一个同名的类来<strong>欺骗</strong>编译器。例：我们创建一个新的单元，名为 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">GUITestRunnerPatch.pas</span></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">type</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  THackGUITestRunner = </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">class</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">(GUITestRunner.TGUITestRunner)<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">private</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> <br />    procedure WMCopyData(var Msg: TWMCopyData); </span><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">message</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> WM_COPYDATA; </span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">//&lt;-- the method you want to append<br /></span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end;</span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><br /><br /></span></div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">在需要使用</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">GUITestRunner </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的地方</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">加上新的</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">GUITestRunnerPatch。注意：一定要在其之后，否则编译器不会调用你修改过的这个类，而是调用了原先的那个。</span></div>
<div style="line-height:150%;"><strong></strong></div>
<div style="line-height:150%;"> </div>
<div style="line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">总结：</span></strong></div>
<div style="line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">在进入 </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Delphi </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的内部世界时，我们要尽可能的考虑代码的移植性和通用性，要以少量修改换回最佳效果。如果上面介绍的修修补补不能解决你的问题，当然你也可以直接修改</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> Delphi </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">的控件源码。修改之后，勾选编译选项里面的 „</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Use Debug DCUs</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">“，并编译程序，再将编译得到的</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> dcu </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">文件保存到编译目录下面。我一般创建</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">2</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">个目录：</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">PatchedVCLs </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">和</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> PreCompiled </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">放修改过的源码，和编译之后的版本。然后把这个</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">2</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">个目录定义到环境变量里面，这样只要在每个项目的路径设置中添加这些变量，就可以使用改动过的代码了。如果本文不正确的地方，欢迎拍砖。</span></div>
<div style="line-height:150%;"> </div>                    <div>
                        作者：Stanley_Xu 发表于 2007/04/09 00:49:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1557107">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1557107                    </div>
                    <div>
                        阅读：3464 评论：5 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1557107#comments" target="_blank">查看评论</a>                    </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]TntControls 被糟蹋了]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1553642</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1553642</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/04/06 06:19:00</pubDate>
                <description>
                    <![CDATA[
                    <p style="line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">原本打算介绍一下 Delphi 的一些优秀开源项目，其中就有我很喜欢的 TntControls。它为大部分 Delphi 原生控件提供了 Unicode 支持。很可惜，作者最近决定不打算继续维护了。为了让这套库可以继续活下去，在一片质疑和惋惜声中，它被转到了新东家 TMS Software 手下。TMS 是何许公司？应该算大的控件商了吧，相信很多 Delphi <span>粉丝都听说过，旗下控件超过应该有百个之多。（但是在下印象中，这个公司控件的产量普遍于其质量） 哎，当时我的心就一凉，心想为什么是 </span>TMS 而不是 CodeGear 呢……。不过我还是好奇的询问了一下 TMS，究竟准备如何维护这套库？会不会和原作者一样，做成一个纯正的原生控件的 Unicode 补完项目。当时我得到的答案是 YES。可惜今天拿到新的代码 — 完全和他们当时说的，是<strong>两码事</strong>。他们那些烂控件也一并进入了新的 TMS Unicode Component Pack。估计原作者看到这个，也难免心酸。为一个优秀开源库的消失，不爽一记！</span></p>                    <div>
                        作者：Stanley_Xu 发表于 2007/04/06 06:19:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1553642">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1553642                    </div>
                    <div>
                        阅读：2169 评论：1 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1553642#comments" target="_blank">查看评论</a>                    </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]到底谁是流氓]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1514749</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1514749</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/02/26 13:10:00</pubDate>
                <description>
                    <![CDATA[
                    看见新闻频道的这篇文章 “疯狂VC邪恶的钱：一个视频站创始人的狼狈退出”<br /><a href="http://news.csdn.net/n/20070224/101540.html">http://news.csdn.net/n/20070224/101540.html</a><br /><br />看见里面这么一段<br /><span style="color:rgb(0,0,255);">在视频网站普遍无法盈利的情况下，流量成为衡量其前途好坏的唯一指标。为了实现目标，林风不得不大把“烧钱”。他甚至还通过与流氓软件合作，以强制弹出的形式加大网站流量。</span><br /><br />真好笑，就是有象你们这样的流氓站点，才早就了今天这么多的流氓软件。<br />毫不夸张的说，你们才是流氓风气的制造机。<br />究竟谁疯狂谁邪恶？<br /><br />也不知道这种专访是怎么登到csdn的，csdn也不把关的哦？                    <div>
                        作者：Stanley_Xu 发表于 2007/02/26 13:10:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1514749">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1514749                    </div>
                    <div>
                        阅读：1511                     </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]告别畸形的工具提示]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1511572</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1511572</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/02/18 08:45:00</pubDate>
                <description>
                    <![CDATA[
                    <p><strong><span style="font-size:11pt;font-family:'微软雅黑', 'sans-serif';">问题的提出：</span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /> Delphi </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的怪异封装我们见到不少了。工具提示</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> (Tooltip </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">或者</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Hint) </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">属于一个典型的畸形封装。或许是</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Borland </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的工程师想让</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Delphi </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的应用程序与众不同，而故意将工具提示最外层边框不用标准的黑色。</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">(</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">这个问题可以通过修改</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Controls.pas </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">来解决，即画边框时候修改边框风格。</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">) </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">但新的</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Windows Vista </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">系统对工具提示做了调整。原先的“浅黄色“变成了“浅蓝色梯度渐变”；原先的“直角边框”改成了“圆角边框”。但是奇怪的是，</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Delphi </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的应用程序还是在沿用老风格，这种效果于</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Vista </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的华丽风格格格不入。于是我想要解决这个问题……</span></p>
<div> </div>
<p><strong><span style="font-size:11pt;font-family:'微软雅黑', 'sans-serif';">问题的产生原因：</span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /></span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">经过一番研究，我注意到，所有的工具提示其实是通过</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> THintWindow </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">来画出的。可能是因为</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Borland </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">工程师想让工具提示可以彻底自定义重绘。于是并没有创建一个 </span>TOOLTIPS_CLASS <span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">窗口，而是创建了一个</span><span>WS_EX_TOOLWINDOW </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">窗口。也就是说，</span><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Delphi </span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">程序里面的工具提示是用</span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> TOOLWINDOW </span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">假冒的</span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">。这也就解释了为什么在</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Vista </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">下面会这么难看的原因了。</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><a href="http://gosurfbrowser.com/~xuqan/code/NativeHintWindow.zip">解决代码</a></span></p>
<div style="margin-bottom:.0001pt;"><strong> </strong></div>
<p><strong><span style="font-size:11pt;font-family:'微软雅黑', 'sans-serif';">题外话：</span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /> Delphi 2007 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">预计会在</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">3</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">月份发布，网上已经有</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">2</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">张截图了。</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Delphi </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">开发小组说这个版本会解决</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Vista </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的兼容性问题，同时改善</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> IDE </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">性能</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> (</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">重绘等问题</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">)</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">。可能是大部分核心开发人员都跳槽的缘故吧。</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Delphi 2006 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的质量不如人意，最近的热补竟然出到了</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">#10</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">。希望下个版本会改观。</span></p>
<div> </div>
<div style="margin:3pt 1.5pt .0001pt;"><span style="font-size:10pt;"><a href="http://stanleyxu2005.blogspot.com/2008/01/performance-issue-of-taction.html"><span style="font-family:'微软雅黑', 'sans-serif';">点击这里查看本文的英文版本</span></a></span></div>
<div> </div>                    <div>
                        作者：Stanley_Xu 发表于 2007/02/18 08:45:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1511572">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1511572                    </div>
                    <div>
                        阅读：4486 评论：2 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1511572#comments" target="_blank">查看评论</a>                    </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]冤枉！浏览器缘何会丢失 Cookie]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1509503</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1509503</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/02/13 18:49:00</pubDate>
                <description>
                    <![CDATA[
                    <p style="margin:3pt 1.5pt .0001pt 0cm;"><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">问题</span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">描述</span></strong><strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">：</span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /> 最近一段时间用户总反应使用 GOSURF 的时候经常丢 cookie。问我是否内核里面做了一些错误的修改。我检查许久也没什么头绪，唯一觉得不同的就是，只在运行期加载 GOSURF 自己的用户标示</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> (User agent)</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">。网上搜索一下关于丢</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> cookie </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的文章，大部分都直指国内最红火的</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Discuz</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">论坛。也看见该站技术人员解释道：因为</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> cookie </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的有效期、作用域造成丢失，需要通过修改论坛设置就可解决。但是事实上，在我机器上各个</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Discuz</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">论坛疯狂丢</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> cookie </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的同时，那些国外的</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> vbb</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">、</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">ipb </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">论坛相安无事。所以我认为官方的说法有误，并进行了一番研究。</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /><br /><strong><span style="font-family:'微软雅黑', 'sans-serif';">实际情况：</span></strong><br /> 研究发现，</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Discuz</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">论坛程序在网站安全方面有这样的处理。如果</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> SecurityId 发生了变化，将删除原先的 cookie，并且提示用户重新登陆。而这个 sid是把用户标示联合其它变量计算而得。那么一旦用户标示发生了改变，sid 肯定也会随之改变，从而导致</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Discuz</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">论坛错误的删除</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> cookie。如果你频繁切换使用 MSIE 和 GOSURF</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> (</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">包括其它外壳浏览器</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">) </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">就容易出现这个问题了。</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">(</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">注：我仅检查了 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Discuz v5.0 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">版的代码</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">)</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /><br /><strong><span style="font-family:'微软雅黑', 'sans-serif';">解决方案：</span></strong><br />也有些临时的解决方案。比如使用固定或不主动添加用户标示的浏览器。还可以象</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Firefox </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">一样，使用区别于</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> MSIE </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">的</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> cookie </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">系统。但是要真正解决这个问题，还是希望</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Discuz </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">论坛做出回应。</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Discuz </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">论坛无疑是国内最优秀的论坛程序之一，或许是出于安全性的考虑吧，但这样的设计未免欠妥。不知道是否他们还有其它的考量。外壳浏览器虽然不属于正规军，但是在市场的份额是必须得到承认的。因此，尽可能的兼容性各个浏览器，应该是产品设计时候需要周全考虑到的。</span></p>
<br />                    <div>
                        作者：Stanley_Xu 发表于 2007/02/13 18:49:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1509503">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1509503                    </div>
                    <div>
                        阅读：2193                     </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]子窗体弹出位置错误]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1504745</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1504745</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/02/07 20:33:00</pubDate>
                <description>
                    <![CDATA[
                    <p class="MsoNormal" style="line-height:normal;"><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">在设计窗体时通常会把子窗体的 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Position <span lang="zh-cn" xml:lang="zh-cn">设置成 </span>poMainFormCenter<span lang="zh-cn" xml:lang="zh-cn">。也就是说，子窗体弹出的位置是主窗体的正中。但是如果把主窗体拖动到屏幕左下角，而且主窗体的</span>50<span lang="zh-cn" xml:lang="zh-cn">％部分已经超出了屏幕范围，这个时候主窗体的正中其实已经不在屏幕范围之内了。这个时候弹出的子窗体可能部分或者完全处在屏幕之外了。</span></span></p><p></p>
<p class="MsoNormal" style="line-height:normal;"><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">具体解决方法：修改</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Forms.pas<span lang="zh-cn" xml:lang="zh-cn">，修改 </span></span><span style="font-size:9pt;font-family:'Courier New';">procedure TcustomForm.CMShowingChanged(var Message: Tmessage); </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"></span></p><p></p>
<p class="MsoNormal" style="background:#FFFFFF none repeat scroll 0% 50%;margin-bottom:.0001pt;line-height:normal;"><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">procedure</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> TCustomForm.CMShowingChanged(</span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">var</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> Message: TMessage);<br /></span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">const</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />   ShowCommands: </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">array</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">[TWindowState] </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">of</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> Integer =<br />     (SW_SHOWNORMAL, SW_SHOWMINNOACTIVE, SW_SHOWMAXIMIZED);<br /></span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">var</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />   X, Y: Integer;<br />   NewActiveWindow: HWnd;<br />   CenterForm: TCustomForm;<br /></span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />   </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">not</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> (csDesigning </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">in</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> ComponentState) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">and</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> (fsShowing </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">in</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> FFormState) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />     </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">raise</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> EInvalidOperation.Create(SVisibleChanged);<br />   Application.UpdateVisible;<br />   Include(FFormState, fsShowing);<br />   </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">try</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />     </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">not</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> (csDesigning </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">in</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> ComponentState) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />     </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />       </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> Showing </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />       </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">try</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           DoShow;<br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">except</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           Application.HandleException(Self);<br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">end</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> (FPosition = poScreenCenter) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">or</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />            ((FPosition = poMainFormCenter) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">and</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> (FormStyle = fsMDIChild)) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> FormStyle = fsMDIChild </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             X := (Application.MainForm.ClientWidth - Width) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />             Y := (Application.MainForm.ClientHeight - Height) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">end</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">else</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             X := (Screen.Width - Width) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />             Y := (Screen.Height - Height) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">end</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> X &lt; Screen.DesktopLeft </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             X := Screen.DesktopLeft;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> Y &lt; Screen.DesktopTop </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             Y := Screen.DesktopTop;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> Y &gt; Screen.WorkAreaHeight - Height </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">  </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#008000;" xml:lang="en-us">//PATCH</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             Y := Screen.WorkAreaHeight - Height;      </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#008000;" xml:lang="en-us">//PATCH</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           SetBounds(X, Y, Width, Height);<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> Visible </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> SetWindowToMonitor;<br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">end</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">else</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> FPosition </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">in</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> [poMainFormCenter, poOwnerFormCenter] </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           CenterForm := Application.MainForm;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> (FPosition = poOwnerFormCenter) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">and</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> (Owner </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">is</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> TCustomForm) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             CenterForm := TCustomForm(Owner);<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> Assigned(CenterForm) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             X := ((CenterForm.Width - Width) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">) + CenterForm.Left;<br />             Y := ((CenterForm.Height - Height) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">) + CenterForm.Top;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">end</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">else</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             X := (Screen.Width - Width) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />             Y := (Screen.Height - Height) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">end</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> X &lt; Screen.DesktopLeft </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             X := Screen.DesktopLeft;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> Y &lt; Screen.DesktopTop </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             Y := Screen.DesktopTop;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> Y &gt; Screen.WorkAreaHeight - Height </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">  </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#008000;" xml:lang="en-us">//PATCH</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             Y := Screen.WorkAreaHeight - Height;      </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#008000;" xml:lang="en-us">//PATCH</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           SetBounds(X, Y, Width, Height);<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> Visible </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> SetWindowToMonitor;<br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">end</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">else</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> FPosition = poDesktopCenter </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />         </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> FormStyle = fsMDIChild </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             X := (Application.MainForm.ClientWidth - Width) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />             Y := (Application.MainForm.ClientHeight - Height) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">end</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">else</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             X := (Screen.DesktopWidth - Width) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />             Y := (Screen.DesktopHeight - Height) </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">div</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#FF0000;" xml:lang="en-us">2</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">end</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">;<br />           </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">if</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"> X &lt; Screen.DesktopLeft </span><strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#0000FF;" xml:lang="en-us">then</span></strong><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us">              </span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#008000;" xml:lang="en-us">//PATCH</span><span lang="en-us" style="font-size:9pt;font-family:'Courier New';color:#000000;" xml:lang="en-us"><br />             X := Screen.DesktopLeft;                  </span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">//</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />           </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Y &lt; Screen.DesktopTop </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">               </span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">//</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />             Y := Screen.DesktopTop;                   </span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">//</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />           </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Y &gt; Screen.WorkAreaHeight - Height </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">  </span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">//</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />             Y := Screen.WorkAreaHeight - Height;      </span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">//PATCH</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />           SetBounds(X, Y, Width, Height);<br />         </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;</span><span style="font-size:12pt;font-family:'Times New Roman', serif;"></span></p><p></p>
<p class="MsoNormal" style="line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /><span lang="zh-cn" xml:lang="zh-cn">好了！大功告成。将修改后的 </span>Forms.pas <span lang="zh-cn" xml:lang="zh-cn">复制到您的工程目录下，再次编译您的程序。这个问题消失了。</span></span></p><p></p>
<p class="MsoNormal" style="line-height:normal;"><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">此外，对于修改</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Delphi <span lang="zh-cn" xml:lang="zh-cn">的源文件，我建议把所有修改过的源文件都放在一个新的目录 （例如</span> PatchedVCLs<span lang="zh-cn" xml:lang="zh-cn">），然后在</span> Delphi <span lang="zh-cn" xml:lang="zh-cn">里面定义一个环境变量，这样以后你只要给其它工程的路径里面添加这个环境变量，这些工程都可以使用你修改过的代码了。至于修改源码的一些方法和技巧，请参考 </span></span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><a href="http://blog.csdn.net/Stanley_Xu/archive/2007/01/28/1496113.aspx"><span lang="zh-cn" xml:lang="zh-cn">如何访问私有成员变量和函数</span></a></span><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">。</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"></span></p><p></p>                     <div>
                        作者：Stanley_Xu 发表于 2007/02/07 20:33:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1504745">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1504745                    </div>
                    <div>
                        阅读：1877                     </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]如何访问私有成员变量和函数]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1496113</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1496113</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/01/28 12:39:00</pubDate>
                <description>
                    <![CDATA[
                    <p><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">一说到修改</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Delphi <span lang="zh-cn" xml:lang="zh-cn">源码或者访问对象的私有成员函数，很多人马上可以说出种种危害来否定我。这种做法我也提倡，但是有时候如果可以灵活运用，可以解决由于</span> Delphi <span lang="zh-cn" xml:lang="zh-cn">因为封装不正确而带来的问题。我在这里分享一些技巧：</span></span></p>
<p><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><span lang="zh-cn" xml:lang="zh-cn"></span></span><span style="font-size:10pt;"></span></p><p></p>
<p style="margin-left:18pt;text-indent:-18pt;"><!--[if !supportLists]--><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><span>1.<span style="font:7pt 'Times New Roman';">     </span></span></span><!--[endif]--><strong><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">访问私有成员变量</span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /><span lang="zh-cn" xml:lang="zh-cn">如果是</span> protected <span lang="zh-cn" xml:lang="zh-cn">的变量，可以用如下方法访问：</span></span><span style="font-size:10pt;"></span></p><p></p>
<p style="background:#FFFFFF 0% 50%;margin:0cm 0cm 0pt 18pt;"><strong><span style="font-size:9pt;color:#0000FF;font-family:'Courier New';">type</span></strong><span style="font-size:9pt;color:#000000;font-family:'Courier New';"><br />  TSomeClassAccess = </span><strong><span style="font-size:9pt;color:#0000FF;font-family:'Courier New';">class</span></strong><span style="font-size:9pt;color:#000000;font-family:'Courier New';">(TSomeClass);<br /><br /></span><strong><span style="font-size:9pt;color:#0000FF;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;font-family:'Courier New';"><br />  TSomeClassAccess(Object1).protected_Bool := False;<br />  TSomeClassAccess(Object1).protected_Int := </span><span style="font-size:9pt;color:#FF0000;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;font-family:'Courier New';">;<br />  ...<br /></span><strong><span style="font-size:9pt;color:#0000FF;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;font-family:'Courier New';">;</span><span style="font-family:'Courier New';"></span></p><p></p>
<p style="margin-left:18pt;"><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">如果是</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> private <span lang="zh-cn" xml:lang="zh-cn">的变量，那么就要当心了。因为涉及到偏移量。还要考虑不同</span> Delphi <span lang="zh-cn" xml:lang="zh-cn">版本的控件的内部成员可能也有变化。最简单的例子是：访问</span> TMenuItem <span lang="zh-cn" xml:lang="zh-cn">的第二个内部成员变量</span> FHandle</span></p>
<p style="background:#FFFFFF 0% 50%;margin:0cm 0cm 0pt 17.4pt;"><strong><span lang="en-us" style="font-size:9pt;color:#0000FF;font-family:'Courier New';" xml:lang="en-us">type</span></strong><span lang="en-us" style="font-size:9pt;color:#000000;font-family:'Courier New';" xml:lang="en-us"><br />  THackMenuItem = </span><strong><span lang="en-us" style="font-size:9pt;color:#0000FF;font-family:'Courier New';" xml:lang="en-us">class</span></strong><span lang="en-us" style="font-size:9pt;color:#000000;font-family:'Courier New';" xml:lang="en-us">(TComponent)<br />  </span><strong><span lang="en-us" style="font-size:9pt;color:#0000FF;font-family:'Courier New';" xml:lang="en-us">protected</span></strong><span lang="en-us" style="font-family:'Courier New';" xml:lang="en-us"> </span><span lang="en-us" style="font-size:9pt;color:#008000;font-family:'Courier New';" xml:lang="en-us">//&lt;-- change to protected </span><span lang="en-us" style="font-size:9pt;color:#000000;font-family:'Courier New';" xml:lang="en-us"><br />    FxxxxCaption: AnsiString;<br />    FHandle: HMENU; </span><span lang="en-us" style="font-size:9pt;color:#008000;font-family:'Courier New';" xml:lang="en-us">//&lt;-- the property you want to access</span></p>
<p style="background:#FFFFFF 0% 50%;margin:0cm 0cm 0pt 17.4pt;"><strong><span style="font-size:9pt;color:#0000FF;font-family:'Courier New';">  end</span></strong><span style="font-size:9pt;color:#000000;font-family:'Courier New';">;</span></p>
<p style="background:#FFFFFF 0% 50%;margin:0cm 0cm 0pt 17.4pt;"><span style="font-size:9pt;color:#000000;font-family:'Courier New';"></span><span lang="en-us" style="font-size:9pt;color:#000000;font-family:'Courier New';" xml:lang="en-us"><br /></span><strong><span lang="en-us" style="font-size:9pt;color:#0000FF;font-family:'Courier New';" xml:lang="en-us">begin</span></strong><span lang="en-us" style="font-size:9pt;color:#000000;font-family:'Courier New';" xml:lang="en-us"><br />  THackMenuItem(AMenuItem).FHandle := 0;<br />  ...<br /></span><strong><span lang="en-us" style="font-size:9pt;color:#0000FF;font-family:'Courier New';" xml:lang="en-us">end</span></strong><span lang="en-us" style="font-size:9pt;color:#000000;font-family:'Courier New';" xml:lang="en-us">;</span><span lang="en-us" style="font-family:'Courier New';" xml:lang="en-us"></span></p><p></p>
<p style="margin-left:18pt;text-indent:-18pt;"><!--[if !supportLists]--><span>2.<span style="font:7pt 'Times New Roman';">      </span></span><!--[endif]--><strong><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">访问私有成员函数</span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /><span lang="zh-cn" xml:lang="zh-cn">这个目前普遍的做法是偷梁换柱。就是把自己的函数地址替换成待修改函数的内存地址。不过其中涉及到了内存修改、地址偏移量……，具体做法可以参考</span> TntControls <span lang="zh-cn" xml:lang="zh-cn">中</span> TntSystem.pas <span lang="zh-cn" xml:lang="zh-cn">安装系统补丁，或者是</span> Fastcode <span lang="zh-cn" xml:lang="zh-cn">控件包。当然这个替换是会出现副作用的：例如</span> AQTime <span lang="zh-cn" xml:lang="zh-cn">就无法测试安装过</span> TntSystem <span lang="zh-cn" xml:lang="zh-cn">补丁的程序。</span></span></p>
<p style="margin-left:18pt;text-indent:-18pt;"><!--[if !supportLists]--><span>3.<span style="font:7pt 'Times New Roman';">      </span></span><!--[endif]--><strong><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">直接修改代码的实现</span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /><span lang="zh-cn" xml:lang="zh-cn">如果是运行库中的具体实现要修改，可以直接动源码，因为改动是</span>implementation <span lang="zh-cn" xml:lang="zh-cn">的部分，不会影响到其它的调用该单元的部分。（注意：</span>interface <span lang="zh-cn" xml:lang="zh-cn">和</span> implementation <span lang="zh-cn" xml:lang="zh-cn">的内容不能直接修改，否则无法编译通过。）修改之后，勾选编译选项里面的 „</span>Use Debug DCUs<span lang="zh-cn" xml:lang="zh-cn">“，并编译程序，再将编译得到的</span> dcu <span lang="zh-cn" xml:lang="zh-cn">文件保存到编译目录下面。我一般创建</span>2<span lang="zh-cn" xml:lang="zh-cn">个目录：</span>PatchedVCLs <span lang="zh-cn" xml:lang="zh-cn">和</span> PreCompiled <span lang="zh-cn" xml:lang="zh-cn">放修改过的源码，和编译之后的版本。然后把这个</span>2<span lang="zh-cn" xml:lang="zh-cn">个目录定义到环境变量里面，这样只要在每个项目的路径设置中添加这些变量，就可以使用改动过的代码了。</span></span></p>
<p style="margin-left:18pt;text-indent:-18pt;"><!--[if !supportLists]--><span>4.<span style="font:7pt 'Times New Roman';">      </span></span><!--[endif]--><strong><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">间接修改代码的实现</span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /><span lang="zh-cn" xml:lang="zh-cn">如果要在修改定义部分怎么办？方法</span>3<span lang="zh-cn" xml:lang="zh-cn">是肯定行不通了。因为所有引用到这个单元的单元也需要重新编译，但不是所有</span> Delphi <span lang="zh-cn" xml:lang="zh-cn">源码你都可以重新编译的。这种情况就伤脑筋了。我目前只可以修改很小一部分的。基本思路是在自己的程序里面定义需访问对象的扩展类和具体实现。然后释放原先对象实例，并以新扩展类重新创建实例。请参考 </span><a href="http://blog.csdn.net/stanley_xu/archive/2007/01/28/1496061.aspx"><span lang="zh-cn" xml:lang="zh-cn">打入消息循环的另类方法</span></a><span lang="zh-cn" xml:lang="zh-cn">。</span></span></p>
<p><strong><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn"><br /></span></strong></p>
<p><strong><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">总结：</span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /><span lang="zh-cn" xml:lang="zh-cn">以上四种方法是我在修改</span> Delphi <span lang="zh-cn" xml:lang="zh-cn">库或者第三方控件时候所用到的。在修改源码的时候，尽量要考虑到代码的移植性。要做到最少量的修改，得到最好的效果。并且需要考虑修改的代码是否可以在不 同的</span> Delphi <span lang="zh-cn" xml:lang="zh-cn">版本中使用。我在实际项目中，修改了</span>6<span lang="zh-cn" xml:lang="zh-cn">、</span>7<span lang="zh-cn" xml:lang="zh-cn">个源码。（有时间的话，我会一一列出，有需要的可以问我索取。）同时也欢迎交流更多的修改方法，以及</span> Delphi <span lang="zh-cn" xml:lang="zh-cn">不正确封装的补丁。</span></span></p>
<p><strong><span lang="zh-cn" style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn"><br />题外话：</span></strong><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /><span lang="zh-cn" xml:lang="zh-cn">刚刚来自 CodeGear 的消息，Delphi 下个版本会引入了新的技术，直接修改声明部分的代码将变的可能</span><span lang="zh-cn" xml:lang="zh-cn">。</span></span></p>                    <div>
                        作者：Stanley_Xu 发表于 2007/01/28 12:39:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1496113">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1496113                    </div>
                    <div>
                        阅读：2362                     </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]打入消息循环的另类方法]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/1496061</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/1496061</guid>
                <author>Stanley_Xu</author>
                <pubDate>2007/01/28 11:09:00</pubDate>
                <description>
                    <![CDATA[
                    <p style="line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">正常打入消息循环的方法：</span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><br /> 如果要监视 WM_CONTEXTMENU 消息来实现菜单的右键菜单，一般做法是通过子类化 (subclass) Menus.PopupList.WndProc 的方法来处理窗口消息。简单讲就是：打入消息循环，完成我的处理，再把消息交还给原先的消息处理函数。当不需要监视消息的时候再退出消息处理（un-subclass）。这样做的好处是：不打破控件的结构。</span></p>
<p style="background:#FFFFFF none repeat scroll 0% 50%;margin-bottom:.0001pt;line-height:normal;"><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> TMyMenuMessagesHandler.SubclassWndProc;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   FDefMenuProc := Pointer(GetWindowLongA(PopupList.Window, GWL_WNDPROC));<br />   FObjInstance := Classes.MakeObjectInstance(CustomMenuWndProc);<br />   SetWindowLongA(PopupList.Window, GWL_WNDPROC, Longint(FObjInstance));<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> TMyMenuMessagesHandler.UnSubclassWndProc;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Assigned(FDefMenuProc) </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     SetWindowLongA(PopupList.Window, GWL_WNDPROC, Longint(FDefMenuProc));<br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Assigned(FObjInstance) </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     Classes.FreeObjectInstance(FObjInstance);<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> TMyMenuMessagesHandler.CustomMenuWndProc(</span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Message: TMessage);<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   CancelPopupContextMenu: Boolean;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Message.Msg = WM_CONTEXTMENU </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     </span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">// My own code ....</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     Message.Result := </span><span style="font-size:9pt;font-family:'Courier New';color:#FF0000;">1</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br />     Exit;<br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br /><br />   </span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">// Send message to default message handler</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">with</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Message </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">do</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     Result := CallWindowProcA(FDefMenuProc, PopupList.Window, Msg, wParam, lParam);<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">; </span></p>
<p style="line-height:150%;"><span style="font-size:9pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><br /></span><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">问题的提出</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">：</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><br /></span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">但是这样做有个隐藏问题</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">：</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">如果你接管的消息窗口提前释放了</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">那么消息处理链就断了</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">，</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">这个时候程序可能会崩溃。如果我们可以直接修改</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Menus.PopupList.WndProc，那么就不用通过 subclass 来实现消息接管了。幸运的是，对于 Menus.PopupList 这个特殊的全局变量来说，这个是可以做到的。<br /><!--[if !supportLineBreakNewLine]--><br /><!--[endif]--></span></p>
<p style="line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">实现原理：</span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><br /> PopupList 的类型是 TPopupList，我们可以在自己的程序里面定义一个继承类，名为TPopupListEx。因为这是个特殊的全局变量，它是在 Menus.pas <span>的初始化部分就创建的，我们可以在它创建之后，立刻释放它，然后以 </span>TPopupListEx的形式重新创建。只要声明部分没有任何变化，这种方法可以 “骗过” 任何调用者，它们以为还是在调用TPopupList。<br /><!--[if !supportLineBreakNewLine]--><br /><!--[endif]--></span></p>
<p style="line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">具体代码：</span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><br /> 把上面的代码替换成如下代码即可</span></p>
<p style="background:#FFFFFF none repeat scroll 0% 50%;margin-bottom:.0001pt;line-height:normal;"><span style="font-size:9pt;font-family:'Courier New';color:#008000;">//PATCH-BEGIN</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">type</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   TPopupListEx = </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">class</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">(TPopupList)<br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">private</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     FOnCustomWndProc: TWndMethod;<br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">public</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">property</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> OnCustomWndProc: TWndMethod </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">read</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> FOnCustomWndProc </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">write</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> FOnCustomWndProc;<br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">protected</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> WndProc(</span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Message: TMessage); </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">override</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> TPopupListEx.WndProc(</span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Message: TMessage);<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Assigned(OnCustomWndProc) </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     OnCustomWndProc(Message);<br />     </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Message.Result = </span><span style="font-size:9pt;font-family:'Courier New';color:#FF0000;">1</span> <strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />       Exit;<br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">inherited</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br /></span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">//PATCH-END</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br /><br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> TMyMenuMessagesHandler.SubclassWndProc;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Assigned(PopupList) </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     TPopupListEx(PopupList).OnCustomWndProc := CustomMenuWndProc;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> TMyMenuMessagesHandler.UnSubclassWndProc;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Assigned(PopupList) </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     TPopupListEx(PopupList).OnCustomWndProc := </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">nil</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> TMyMenuMessagesHandler.CustomMenuWndProc(</span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Message: TMessage);<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   CancelPopupContextMenu: Boolean;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Message.Msg = WM_CONTEXTMENU </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     </span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">// My own code ....</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     Message.Result := </span><span style="font-size:9pt;font-family:'Courier New';color:#FF0000;">1</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">; <br /><br /><br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">initialization</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   FreeAndNil(PopupList);<br />   PopupList := TPopupListEx.Create;<br /><br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">finalization</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br /></span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">//FreeAndNil(PopupList); //NOTE: will be freed by finalization section of Menus.pas</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">.</span></p>
<div style="line-height:150%;"> </div>
<p style="line-height:150%;"><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">说明</span></strong><strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">：</span></strong><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><br /></span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">但是我还不清楚为什么用</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> subclass </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">方法的时候，一旦消息窗口释放，程序会崩溃。目前也只能先用这个方法了。</span></span></p>                    <div>
                        作者：Stanley_Xu 发表于 2007/01/28 11:09:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/1496061">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/1496061                    </div>
                    <div>
                        阅读：1803                     </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]由演示程序 coolstuf 而找到的工具栏错位问题]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/285743</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/285743</guid>
                <author>Stanley_Xu</author>
                <pubDate>2005/02/11 12:58:00</pubDate>
                <description>
                    <![CDATA[
                    <p style="line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">DELPHI 光盘中有一个浏览器的演示程序 coolstuf。我发现它的奇怪问题：一旦你将第三行工具栏“链接栏”拖动到最顶端，然后再拖回原来的位置，那么工具栏最下方会多出一个大概 40px 的空白区域。这个显然是 TCoolBar 没有封装好的缘故，我暂时称该问题为“工具栏错位”。</span></p>
<p style="line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">我发现如果有</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Band 设置过 FixedSize=True，就会出现偏差，没设置过就没有问题。我猜测可能是工具栏高度发生变化后，Band 的高度属性未被真正更新所致。（ReBar <span>系列控件的细节问题的确很多，难怪到现在 </span>Delphi 都没有给工具栏加上 Chevron 效果。）要解决这个问题，只要在接收到 RBN_HEIGHTCHANGE 消息时，对设置过 FixedSize=True 的 Band 强制更新一次属性即可。反正只是重新更新一次属性，所以也不会带来什么副作用。</span></p>
<p style="line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">具体方法：找到</span><span style="font-size:9pt;font-family:'Courier New';"> procedure TCoolBar.CNNotify(var Message: TWMNotify); </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /> 将整个函数替换成如下代码即可。</span></p>
<p style="background:#FFFFFF none repeat scroll 0% 50%;margin-bottom:.0001pt;line-height:normal;"><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> TCoolBar.CNNotify(</span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Message: TWMNotify);<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   I: Integer;<br />   RBBI: TReBarBandInfo;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />   </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> (Message.NMHdr^.code = RBN_HEIGHTCHANGE) </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> IsAutoSized </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">and</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> (ComponentState * [csLoading, csDestroying] = []) </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />       </span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">//PATCH-BEGIN</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />       </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">for</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> I := </span><span style="font-size:9pt;font-family:'Courier New';color:#FF0000;">0</span> <strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">to</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Bands.Count - </span><span style="font-size:9pt;font-family:'Courier New';color:#FF0000;">1</span> <strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">do</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />         </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> Bands[I].FixedSize </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />         </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />           FillChar(RBBI, SizeOfReBarBandInfo, </span><span style="font-size:9pt;font-family:'Courier New';color:#FF0000;">0</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;">);<br />           RBBI.cbSize := SizeOfReBarBandInfo;<br />           RBBI.fMask := RBBIM_STYLE;<br />           Perform(RB_GETBANDINFO, Bands[I].FID </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">and</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> IDMask, Integer(@RBBI));<br />           Perform(RB_SETBANDINFO, Bands[I].FID </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">and</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> IDMask, Integer(@RBBI));<br />         </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br />       </span><span style="font-size:9pt;font-family:'Courier New';color:#008000;">//PATCH-END</span><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />                      <br />       ReadBands;<br />       BeginUpdate;<br />       </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">try</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />         </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> AutoSize </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> AdjustSize;<br />       </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">finally</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />         EndUpdate;<br />       </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;<br />     </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">else</span></strong> <strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"> IsBackgroundDirty </span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;"><br />       Invalidate;<br /></span><strong><span style="font-size:9pt;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;font-family:'Courier New';color:#000000;">;</span></p>
<p style="line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /> 好了！大功告成。将修改后的 ComCtrls.pas 复制到 coolstuf 目录下，再次编译文件。这个问题消失了。</span></p>
<p style="line-height:normal;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">此外，对于修改</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"> Delphi 的源文件，我建议把所有修改过的源文件都放在一个新的目录 （例如 PatchedVCLs），然后在 Delphi 里面定义一个环境变量，这样以后你只要给其它工程的路径里面添加这个环境变量，这些工程都可以使用你修改过的代码了。</span><span lang="zh-cn" style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">至于修改源码的一些方法和技巧，请参考 </span><span style="font-size:11pt;line-height:115%;font-family:Calibri, 'sans-serif';"><a href="http://blog.csdn.net/Stanley_Xu/archive/2007/01/28/1496113.aspx"><span lang="zh-cn" style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">如何访问私有成员变量和函数</span></a></span><span lang="zh-cn" style="font-size:10pt;line-height:115%;font-family:'微软雅黑', 'sans-serif';" xml:lang="zh-cn">。</span></p>                    <div>
                        作者：Stanley_Xu 发表于 2005/02/11 12:58:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/285743">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/285743                    </div>
                    <div>
                        阅读：2214 评论：1 <a href="https://blog.csdn.net/Stanley_Xu/article/details/285743#comments" target="_blank">查看评论</a>                    </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]用来替换 MaskMatch 的通配符比较函数]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/99876</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/99876</guid>
                <author>Stanley_Xu</author>
                <pubDate>2004/09/10 01:08:00</pubDate>
                <description>
                    <![CDATA[
                    <div style="line-height:150%;"><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">Delphi </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">提供的通配符匹配函数</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> TMask.Matches </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">有些问题：如果通配符字符串太长，比如进入</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> hotmail </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">邮箱时的地址有大概</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">250</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">个字符。这会导致</span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';"> TMask.Matches </span><span style="font-size:10pt;line-height:150%;font-family:'微软雅黑', 'sans-serif';">函数出错，并导致整个程序崩溃。我在网上找了一些不同的实现，并且做了性能比较。现在我优化过的版本分享出来。</span></div>
<div style="line-height:150%;"> </div>
<div style="background:#FFFFFF;margin:0in 0in 0pt;line-height:150%;"><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">type</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  TMaskMatchResult = </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">record</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    Offset: Integer;  <br />    PatternLength: Integer;<br />    LeadingFlexibleLength: Integer;<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /><br /><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">function</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> HasWildcardsA(</span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">const</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> S: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">string</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">): Boolean;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">var</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  I: Integer;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  Result := False;<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">for</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> I := </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">to</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> Length(S) </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">do</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> S[I] </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">in</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> [</span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'*'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">, </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'?'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">] </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />      Result := True;<br />      Exit;<br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /><br /></span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">// Indicates whether a string matches a wildcard pattern.</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">function</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> MatchMaskA(</span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">const</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> APattern, ASource: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">string</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">): Boolean;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">var</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  I: Integer;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> APattern = </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">''</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    Result := ASource = </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">''</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">else</span></strong> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> ASource = </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">''</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">for</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> I := </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">to</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> Length(APattern) </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">do</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />      </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> APattern[I] &lt;&gt; </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'*'</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />      </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />        Result := False;<br />        Exit;<br />      </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />    Result := True;<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">else</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    Result := MatchMaskExA(APattern, ASource).PatternLength = Length(ASource);<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /><br /></span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">// Indicates whether a string matches a wildcard pattern. </span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';"><br />// </span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">When not matched, Result.PatternLength = 0.</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">function</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> MatchMaskExA(</span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">const</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> APattern, ASource: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">string</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">; Offset: Integer = </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /> ScanPattern: Boolean = True): TMaskMatchResult;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">var</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  StringPtr, StringRes, PatternPtr, PatternRes: PChar;<br />  CountingFlexibleLength: Boolean;<br />  I: Integer;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  FillChar(Result, SizeOf(Result), </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">);<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> Offset &lt; </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    Offset := </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /><br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> ScanPattern </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">and</span></strong> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">not</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> HasWildcardsA(APattern) </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> Offset = PosEx</span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">{ANSI only}</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">(APattern, ASource, Offset) </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />      Result.PatternLength := Length(APattern)</span><span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">{! &gt;0}</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />      Result.Offset := Offset;<br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />    Exit;<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br /><br />  StringPtr := PChar(ASource);<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> Offset &gt; </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    Inc(StringPtr, Offset - </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">);<br />  PatternPtr := PChar(APattern);<br />  StringRes := </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">nil</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />  PatternRes := </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">nil</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />  CountingFlexibleLength := (Length(APattern) &gt; </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">) </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">and</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> (APattern[</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">] = </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'*'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">);<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">repeat</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">repeat</span></strong> <span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">// ohne vorangegangenes "*"</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />      </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">case</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> PatternPtr^ </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">of</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />        </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> : </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />               Result.PatternLength := Length(ASource) + (</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> - Offset) - Length(StringPtr);<br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> Result.PatternLength &gt; </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                 Result.Offset := Offset;<br />               Exit;<br />             </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />        </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'*'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />               Inc(PatternPtr);<br />               PatternRes := PatternPtr;<br />               Break;<br />             </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />        </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'?'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> StringPtr^ = </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                 Exit;<br />               Inc(StringPtr);<br />               Inc(PatternPtr);<br />             </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />        </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">else</span></strong> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> StringPtr^ = </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                 Exit;<br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> StringPtr^ &lt;&gt; PatternPtr^ </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                 </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> (StringRes = </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">nil</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">) </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">or</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> (PatternRes = </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">nil</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">) </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                   Exit;<br />                 StringPtr := StringRes;<br />                 PatternPtr := PatternRes;<br />                 Break;<br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">else</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                 Inc(StringPtr);<br />                 Inc(PatternPtr);<br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />             </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />      </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">until</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> False;<br /><br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">repeat</span></strong> <span style="font-size:9pt;color:#008000;line-height:150%;font-family:'Courier New';">// mit vorangegangenem "*"</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />      </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">case</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> PatternPtr^ </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">of</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />        </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> : </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />               Result.PatternLength := Length(ASource) + (</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">1</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> - Offset);<br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> AnsiLastChar(APattern) &lt;&gt; </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'*'</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                 Dec(Result.PatternLength, Length(StringPtr));<br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> Result.PatternLength &gt; </span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                 Result.Offset := Offset;<br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> CountingFlexibleLength </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                 Result.LeadingFlexibleLength := Result.PatternLength;<br />               Exit;<br />             </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />        </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'*'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />               Inc(PatternPtr);<br />               PatternRes := PatternPtr;<br />             </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />        </span><span style="font-size:9pt;color:#800000;line-height:150%;font-family:'Courier New';">'?'</span><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">: </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> StringPtr^ = </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                 Exit;<br />               Inc(StringPtr);<br />               Inc(PatternPtr);<br />             </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />        </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">else</span></strong> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">repeat</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                 </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> StringPtr^ = </span><span style="font-size:9pt;color:#FF00FF;line-height:150%;font-family:'Courier New';">#</span><span style="font-size:9pt;color:#FF0000;line-height:150%;font-family:'Courier New';">0</span> <strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />                   Exit;<br />                 </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> StringPtr^ = PatternPtr^ </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then<br /></span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">                   Break;<br />                 Inc(StringPtr);<br />               </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">until</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> False;<br />               Inc(StringPtr);<br />               StringRes := StringPtr;<br />               Inc(PatternPtr);<br />               Break;<br />             </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />      </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">until</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> False;<br /><br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">if</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> CountingFlexibleLength </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">then</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">begin</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"><br />      Result.LeadingFlexibleLength := Length(ASource) - Offset - Length(StringPtr);<br />      CountingFlexibleLength := False;<br />    </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;<br />  </span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">until</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';"> False;<br /></span><strong><span style="font-size:9pt;color:#0000FF;line-height:150%;font-family:'Courier New';">end</span></strong><span style="font-size:9pt;color:#000000;line-height:150%;font-family:'Courier New';">;</span></div>
<div style="margin:0in 0in 10pt;line-height:150%;"> </div>                    <div>
                        作者：Stanley_Xu 发表于 2004/09/10 01:08:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/99876">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/99876                    </div>
                    <div>
                        阅读：2459                     </div>
                    ]]>
                </description>
                <category></category>
            </item>
                    <item>
                                <title><![CDATA[[原]可能你不知道的 CPU 资源杀手]]></title>
                <link>https://blog.csdn.net/Stanley_Xu/article/details/99874</link>
                <guid>https://blog.csdn.net/Stanley_Xu/article/details/99874</guid>
                <author>Stanley_Xu</author>
                <pubDate>2004/09/10 01:01:00</pubDate>
                <description>
                    <![CDATA[
                    <div style="margin:3pt 1.5pt .0001pt;"><strong><span style="font-size:11pt;font-family:'微软雅黑', 'sans-serif';">问题的提出：</span></strong></div>
<p style="margin:3pt 1.5pt .0001pt;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">如果你没有用过 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TAction</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">，或许你不该说你会 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Delphi</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">。</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TAction </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">大大简化了界面逻辑的关联，加速了项目的开发。不过我在程序中大量使用 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TAction </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">时，无意发现这样一个问题：如果程序的某个窗体里有超过</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">100</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">个 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TAction</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">，在运行这个程序时，只要不停的在该窗体上快速移动鼠标，</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">CPU </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">占用率会猛增到 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">30% </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">左右。</span></p>
<div style="margin:3pt 1.5pt .0001pt;"> </div>
<p style="margin:3pt 1.5pt .0001pt;"><strong><span style="font-size:11pt;font-family:'微软雅黑', 'sans-serif';">为什么会有如此高的 </span></strong><strong><span style="font-size:11pt;font-family:'微软雅黑', 'sans-serif';">CPU </span></strong><strong><span style="font-size:11pt;font-family:'微软雅黑', 'sans-serif';">占用？</span></strong></p>
<p style="margin:3pt 1.5pt .0001pt;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">使用 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Spy++ </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">调试后发现，一旦鼠标快速在窗体上移动，程序会频繁发送 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">WM_UPDATE </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">消息。进一步调试后发现，</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TContainedAction.Update() </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">被 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TActionManager </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">频繁调用。正如帮助文档中所写：当应用程序处于空闲状态时，所有的 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TxxxxAction.OnUpdate </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">事件会被触发。由于空闲状态频繁改变，因此 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">OnUpdate </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">也就被频繁触发，这个正是造成不当 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">CPU </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">占用的真正原因。</span></p>
<div style="margin:3pt 1.5pt .0001pt;"> </div>
<div style="margin:3pt 1.5pt .0001pt;"><strong><span style="font-size:11pt;font-family:'微软雅黑', 'sans-serif';">解决方案</span></strong></div>
<p style="margin:3pt 1.5pt .0001pt;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">如果你的程序中没有使用到 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TxxxxAction.OnUpdate</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">，那么你可以屏蔽 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TActionManager </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">去查询并触发 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TxxxxAction.OnUpdate</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">。具体实现代码如下：</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /><br /></span></p>
<p style="margin:3pt 1.5pt .0001pt 0in;line-height:150%;"><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">uses</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />  FastcodePatch </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#008000;">{http://fastcode.sourceforge.net/}</span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">procedure</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> TContainedActionUpdateStub;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">asm</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />  call TContainedAction.Update;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">type</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />  TContainedActionPatch = </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">class</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">(TContainedAction)<br />  </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">public</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">function</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Update: Boolean; </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">override</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br />  </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">function</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> TContainedActionPatch.Update: Boolean;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />  Result := False;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /><br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">function</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> DisableTActionOnUpdate(ActnList: TActionList): Boolean;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">var</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />  I: Integer;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />  Result := True;<br />  </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">for</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> I := </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#FF0000;">0</span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">to</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> ActnList.ActionCount - </span><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#FF0000;">1</span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">do</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Assigned(ActnList.Actions[I].OnUpdate) </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />       Result := False;<br />       Break;<br />     </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /><br />  </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">if</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"> Result </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">then</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />  </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">begin</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;"><br />     FastcodeAddressPatch(<br />       FastcodeGetAddress(@TContainedActionUpdateStub),<br />       @TContainedActionPatch.Update);<br />  </span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;<br /></span><strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#0000FF;">end</span></strong><span style="font-size:9pt;line-height:150%;font-family:'Courier New';color:#000000;">;</span></p>
<p style="margin:3pt 1.5pt .0001pt 0in;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';"><br /></span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">这段代码的最佳运行位置是在你程序窗体的</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">OnCreate() </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">事件中。当然</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">，</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">如果你希望彻底解决这个问题</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">，</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">你可以修改</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">ActnList.pas </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">中的</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TContainedAction.Update，</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">或者提交申请让</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">CodeGear </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">来改进这个问题。</span></p>
<div style="margin:3pt 1.5pt .0001pt 0in;"> </div>
<div style="margin:3pt 1.5pt .0001pt 0in;"><strong><span style="font-size:11pt;font-family:'微软雅黑', 'sans-serif';">总结</span></strong></div>
<p style="margin:3pt 1.5pt .0001pt;"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">本文展示了过多使用</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">TxxxxAction </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">组件可能会造成应用程序过高的</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">CPU </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">占用问题。并且提供了补丁代码来解决这个问题。尽管我手上没有最新版本的 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">Delphi</span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">，但是估计这个问题是不会被 </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">CodeGear </span><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">修正的。</span></p>
<div style="margin:3pt 1.5pt .0001pt;"> </div>
<div style="margin:3pt 1.5pt .0001pt;"><a href="http://stanleyxu2005.blogspot.com/2008/01/performance-issue-of-taction.html"><span style="font-size:10pt;font-family:'微软雅黑', 'sans-serif';">点击这里查看本文的英文版本</span></a></div>
<div style="margin:3pt 1.5pt .0001pt;"> </div>                    <div>
                        作者：Stanley_Xu 发表于 2004/09/10 01:01:00 <a href="https://blog.csdn.net/Stanley_Xu/article/details/99874">原文链接</a> https://blog.csdn.net/Stanley_Xu/article/details/99874                    </div>
                    <div>
                        阅读：2466                     </div>
                    ]]>
                </description>
                <category></category>
            </item>
            </channel>
</rss>
