修正ComboBox删除中文的乱码问题

这个问题我前几天已经给出了解答,本文想说的并不是如何去解决这个问题,而是说一种解决问题的思想
其实VCL中许多小陷阱都是可以自己来解决的,它们并不会对实际的开发带来多大的麻烦。
D2007下,如果AutoComplete设为True,则用BackSpace删除中文时,会产生乱码。反之,如果关闭AutoComplete就不会有问题,于是首先想到的是AutoComplete带来的问题。于是,直接在StdCtrls.pas里搜了下AutoComplete。在TcustomComboBox类下,用到AutoComplete的只有一处,即3355行的if not AutoComplete then exit;
这行代码位于KeyPress方法下,一看就明白了,就是按下键时的处理。看到下面那个case语句,里面有单独对VK_BACK的处理,好了,就是它了,打个断点跟进去。
我事先在TComboBox里输入了”一二三“,然后运行,按BackSpace键,就进入了断点,跟踪情况如下:
if (Style in [csDropDown, csSimple]) and (Length(Text) > 0) then
begin
SaveText := Text;
LastByte := StartPos;  <-- 此处跟踪得到的值是3,但是我明明输入三个汉字,应该是6。于是此处就能认为光标位置是按unicode处理的。
while ByteType(SaveText, LastByte) = mbTrailByte do Dec(LastByte);
OldText := Copy(SaveText, 1, LastByte - 1);  <-- 此处已产生了乱码,说明Copy语句有问题
SendMessage(Handle, CB_SETCURSEL, -1, 0);
Text := OldText + Copy(SaveText, EndPos + 1, MaxInt);
SendMessage(Handle, CB_SETEDITSEL, 0, MakeLParam(LastByte - 1, LastByte - 1));
FFilter := Text;
end
看到OldText乱码后,下面的已经没有必要看了,原因很简单,取字符长度时,按Unicode取了,而Copy函数执行时,传入的却是Ansi的字符串,即SaveText
于是最简单的解决方案就有了,

直接把SaveText, OldText的类型改成WideString,改后问题解决。
然后再说一下如何把修改过的东西弄进Delphi里,当你直接修改了StdCtrls.pas后,编译程序,并不会重新生成StdCtrls.dcu。这里有一个小技巧,你可以把StdCtrls.pas另存到你的项目下,然后把它添加到项目里编译,这样在你的项目下就会生成一个StdCtrls.dcu,把这个dcu复制到Delphi下的Lib目录里,就行了
这样你就拥有了一个修正了的StdCtrls.dcu。对于其他的修改,也可以这么做。

posted @ 2010-04-20 11:25  SouthAurora  Views(2499)  Comments(0Edit  收藏  举报