unit D7ComboBoxStringsGetPatch;

// The patch fixes TCustomComboBoxStrings.Get method for empty string item in Delphi .

interface

{$IF RTLVersion <> 15.0}

'This patch is intended for Delphi 7 only';

{$IFEND}

implementation

uses

  Windows, SysUtils, StdCtrls;

resourcestring

  RsPatchingFailed = 'TCustomComboBoxStrings.Get patching failed.';

type

  TPatchResult = (prNotNeeded, prOk, prError);

function PatchCode(RoutineStartAddr: Pointer; PatchOffset: Cardinal; OriginalCode: Pointer;

  OriginalCodeLen: Cardinal; PatchedCode: Pointer; PatchedCodeLen: Cardinal): TPatchResult;

const

  JmpOpCode = $25FF;

type

  PPackageThunk = ^TPackageThunk;

  TPackageThunk = packed record

    JmpInstruction: Word;

    JmpAddress: PPointer;

  end;

var

  CodeStart: Pointer;

  BytesWritten: DWORD;

begin

  if FindClassHInstance(System.TObject) <> HInstance then

    with PPackageThunk(RoutineStartAddr)^ do

      if JmpInstruction = JmpOpCode then

        RoutineStartAddr := JmpAddress^

      else

      begin

        Result := prError;

        Exit;

      end;

  CodeStart := Pointer(LongWord(RoutineStartAddr) + PatchOffset);

  if CompareMem(CodeStart, OriginalCode, OriginalCodeLen) then

  begin

    if WriteProcessMemory(GetCurrentProcess, CodeStart, PatchedCode, PatchedCodeLen, BytesWritten) and

      (BytesWritten = PatchedCodeLen) then

    begin

      FlushInstructionCache(GetCurrentProcess, CodeStart, PatchedCodeLen);

      Result := prOk;

    end

    else

      Result := prError;

  end

  else

    Result := prNotNeeded;

end;

type

  TCustomComboBoxStringsHack = class(TCustomComboBoxStrings);

function AddrOfTCustomComboBoxStringsGet: Pointer;

begin

  Result := @TCustomComboBoxStringsHack.Get;

end;

procedure PatchTCustomComboBoxStringsGet;

const

  OriginalCode: Cardinal  = $74FFF883; // CMP EAX, - | JZ  +$

  PatchedCode: Cardinal   = $7E00F883; // CMP EAX,   | JLE +$

  PatchOffset             = $1F;

  // for DEBUG DCU by Pavel Rogulin

  OriginalCodeD: Cardinal = $FFF07D83;

  PatchedCodeD: Cardinal  = $00F07D83;

  PatchOffsetD            = $2E;

var

  PatchResult: TPatchResult;

begin

  PatchResult := PatchCode(AddrOfTCustomComboBoxStringsGet, PatchOffset, @OriginalCode, SizeOf(OriginalCode),

    @PatchedCode, SizeOf(PatchedCode));

  if PatchResult = prNotNeeded then

    PatchResult := PatchCode(AddrOfTCustomComboBoxStringsGet, PatchOffsetD, @OriginalCodeD, SizeOf(OriginalCodeD),

      @PatchedCodeD, SizeOf(PatchedCodeD));

  case PatchResult of

    prError:

      begin

        if IsConsole then

          WriteLn(ErrOutput, RsPatchingFailed)

        else

          MessageBox(, PChar(RsPatchingFailed), nil, MB_OK or MB_ICONSTOP or MB_TASKMODAL);

        RunError();

      end;

  end;

end;

initialization

  PatchTCustomComboBoxStringsGet;

end.

官方BUG解决地址:

http://cc.embarcadero.com/item/18872

(转)TComboBox patch for Delphi 7的更多相关文章

  1. Delphi XE2 之 FireMonkey 入门(42) - 控件基础: TComboBox、TComboEdit

    Delphi XE2 之 FireMonkey 入门(42) - 控件基础: TComboBox.TComboEdit TListBox 有两个兄弟 TComboListBox.TComboEditL ...

  2. delphi连接sql存储过程

    针对返回结果为参数的 一. 先建立自己的存储过程 ALTER PROCEDURE [dbo].[REName] ) AS BEGIN select ROW_NUMBER() over(order by ...

  3. 转:Delphi 6 实用函数

    来自: daocaoren0824, 时间: -- ::, ID: 再给你一份 程序员实用函数 {▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎▎} {▎ ▎} {▎ 大 ...

  4. delphi里动态创建AlphaControls实现换肤

    AlphaControls是一套Delphi下的优秀的皮肤vcl控件.几年前,一般用得比较多的是vclskin,使用很方便,可惜这套2010年已经停止维护了.后来就看到更多的人开始推崇AlphaCon ...

  5. delphi.指针.应用

    注:初稿...有点乱,可能增删改... 因为指针应用,感觉不好写,请大家指出错误,谢谢. 注意: 本文着重点讲的是指针的各类型的应用或使用,而不是说这种方法不应该+不安全+危险+不提倡使用. 其它:本 ...

  6. Delphi完成的断点续传例子 转

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  7. Delphi经验总结(1)

    先人的DELPHI基础开发技巧 ◇[DELPHI]网络邻居复制文件 uses shellapi; copyfile(pchar('newfile.txt'),pchar('//computername ...

  8. Delphi xe7 FireMonkey / Mobile (Android, iOS)生成 QR Code完整实例

    这个实例在windows.OS X.IOS和Android等平台运行正常.本文参考这个网站提供的方法:http://zarko-gajic.iz.hr/firemonkey-mobile-androi ...

  9. 2年后的Delphi XE6

    1.有幸下载到Delphi XE6,下载地址如下: http://altd.embarcadero.com/download/radstudio/xe6/delphicbuilder_xe6_win. ...

随机推荐

  1. GCC泛型宏

    在JAVA和CPP这种OOP语言中,都有泛型类,在C语言可以用宏定义实现泛型函数. main.c #include <stdio.h> #define min(x, y) ({ \ typ ...

  2. html之canvas

    canvas代码片段: <canvas id="testCanvas" width="400" height="150" style= ...

  3. JUnit手记

    BeforeClass全局只执行一次初始化: Before,每个用例(测试方法)都会走一次: After/AfterClass以此类推

  4. Linux ssh 不需要输入密码的方法

    采用证书的方法可以解决ssh不需要输入密码的问题. 本文采用CentOS的操作系统,创建SSH的key,并在两台或多台机器间实现信任.从而实现SSH登录不需要输入密码的功能. 首先,在一台机器上创建S ...

  5. bzoj4403

    组合数学 我好菜啊 想到dp去了... 事实上对于固定长度的数列,我们只用考虑选了哪些数就行了,所以这个就是$C(n+m-1,m-1)$ 也就是$n$个数,划分成$m$段且允许空的方案数 然后变成$\ ...

  6. ES6学习之数值扩展

    二进制和八进制表示法(二进制用前缀0b(或0B)表示,八进制用前缀0o(或0O)表示) Number('0b111') Number('0o10') Number.isFinite()(判断一个值是否 ...

  7. Sql server 备份及还原

    --最常用的几种备份方法: --数据备份----------------------- --数据库级:完整数据库备份 差异数据库备份 --文件级: 完整文件备份 差异文件备份 --日志备份------ ...

  8. 12.Redis Select 命令 - 切换到指定的数据库

    转自:http://www.runoob.com/redis/redis-tutorial.html Redis Select 命令用于切换到指定的数据库,数据库索引号 index 用数字值指定,以 ...

  9. 伪分布模式 hive查询

    [root@node1 ~]# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian ...

  10. strust2.2.3版本启动报错struts-plugin.xml:8:162

    我用的是struts-2.2.3,开始把全部的jar包都放进去了,可是一直报 信息: Parsing configuration file [struts-plugin.xml] 2011-6-11 ...