大家知道,在delphi的开发环境中,TMS是赫赫有名的三方控件提供商,基本上没有不知道或者没有不使用的。TMS提供的控件包罗万象,非常丰富。但是有一个控件TadvMemo的一个编辑控件,支持语法(delphi,basic,HTML,javascript,css,SQL,C#等等)高亮,很好用,就是有一个硬结是不支持中文,相信大家在使用的过程中都有体会,我问了TMS,答复是tadvMemo只支持monospace字体。而且这个控件版本已经升级的很高了也没有支持中文,看来只能自己修改了。于是我们修改了TadvMemo源代码,使其完美支持中文。

简单的几个函数就可以让TadvMemo 支持中文,修改后的代码下载。
修改后的TadvMemo支持中文功能测试如下:

编号 功能 结论
1 输入中文显示半个汉字 修改后正确显示
2 光标不能放置到一个汉字的中间 修改后正确
3 Ctrl + Left(home)光标到行首 修改后正确
4 Ctrl + Right(end)光标到行尾 修改后正确
5 鼠标或者按键反选 修改后正常
6 反选后拷贝到外边 修改后正常
7 从外边拷贝进入编辑器 修改后正常
8 overwrite下输入中文 修改后正常
9 光标上移或者下移不能移动到一个汉字中间 修改后正常

1. 修改原理

TadvMemo认为字符都是等宽的,等宽的概念是显示一个字符就只能占用一个显示位置,对于英文字符是没有问题的,但是对于中文,就不一样的,一个中文汉字显示的时候会占用两个英文字符的位置,这样就会产生问题。我们要做的就是把中文字符能够合理的告知TadvMemo,为此,我们需要书写如下函数:

1.1 修复需要的函数

一、将光标位置转换成实际的字符位置。比如字符串:”A伟大123“,当光标位于”大"和“1”之间的时候,光标是5,但是对于字符串”A伟大123“来说,如果我们要获取光标前的字符串“A伟大”,就不能使用光标位置5,而应该使用长度3,因为一个汉字作为字符串处理(unicode)也是1。

参数说明:
S:是实际字符串
CurX:表示光标位置,光标在行首的时候是0,每向右移动一个英文字符光标加1,移动一个汉字光标加2.
positon:表示转换后字符串的位置。

结果为 True表示转换成功,否则表示转换失败。

function Get_InsertPositonX_02(S : string; CurX : integer; var position : word) : Boolean;
vari : integer;B : TBytes;E_Char_Count : Word;A1 : integer;
begin//s := 'A你好12大小3设那个';if S = '' then Exit(True);E_Char_Count := 0;B := TEncoding.ANSI.GetBytes(S);//计算有多少个 英文字符for i:= 0 to CurX - 1 doif B[i] < $80 thenE_Char_Count := E_Char_Count + 1;A1 := CurX - E_Char_Count;A1 := (CurX - E_Char_Count) mod 2;A1 := E_Char_Count + (CurX - E_Char_Count) div 2;Result := ((CurX - E_Char_Count) mod 2) = 0;if Result thenposition := E_Char_Count + (CurX - E_Char_Count) div 2elseposition := E_Char_Count + (CurX - E_Char_Count + 1) div 2;end;

二、判断当前光标前是不是一个汉字, True 表示是汉字,否则是英文字母,光标左移是需要使用此函数。

参数说明:
S:是实际字符串
CurX:表示光标位置,

function is_Chinese_Char_Left(S : string; CurX : integer) : Boolean;
varB : TBytes;i,count : integer;
beginB := TEncoding.ANSI.GetBytes(S);if Length(B) = 0 then Exit(False);if CurX = 0 then Exit(False);if Length(B) < CurX then Exit(False);//Result := B[CurX - 1] > $80;if B[CurX -1] < $80 then Exit(False);//需要进一步判断,判断是不是在一个汉字的中间,如果是则返回Falsecount := 0;for i := 0 to CurX - 1 doif B[i] > $80 thencount := count + 1;Result := (count mod 2) = 0;end;

三、判断当前光标后是不是一个汉字, True 表示是汉字,否则是英文字母,光标右移的时候需要使用该函数

参数说明:
S:是实际字符串
CurX:表示光标位置

function is_Chinese_Char_Right(S : string; CurX : integer) : Boolean;
varB : TBytes;i,count : integer;
beginB := TEncoding.ANSI.GetBytes(S);if Length(B) = 0 then Exit(False);//if CurX = 0 then Exit(False);if Length(B) < CurX then Exit(False);//Result := B[CurX] > $80;if B[CurX] < $80 then Exit(False);//需要进一步判断,判断是不是在一个汉字的中间,如果是则返回Falsecount := 0;for i := CurX to Length(B) - 1 doif B[i] > $80 thencount := count + 1;Result := (count mod 2) = 0;end;

四、判断光标是否在一个完整汉字的中间,正常编辑是不应该出现这个问题的。

参数说明:
S:需要判断的字符串
CurX:表示光标位置

返回结果True 表示是在一个汉字中间,否则不是

function is_Half_Chinense(S : string; CurX : integer) : Boolean;
vari : integer;B : TBytes;o : integer;  //记录半个函数数量
beginB := TEncoding.ANSI.GetBytes(S);if CurX > Length(B) then Exit(False);if CurX = 0 then Exit(False);//光标前或者后是一个英文字符,则直接表示不再半个汉字中间if (B[CurX - 1] < $80) or (B[CurX] < $80) then  Exit(False);o := 0;for i := CurX - 1 downto 0 dobeginif B[i] < $80 thenbeginif (o mod 2) = 0 thenExit(False)elseExit(True);end;o := o + 1;end;if (o mod 2) = 0 thenExit(False)elseExit(True);
end;

2. 需要修改的地方举例

一、使用 TEncoding.ANSI.GetBytes 直接调整光标位置。

例如,当需要把光标移动到行尾,也就是按下Ctrl + Right(end)键的时候,需要修改函数中的CurX:

修改前函数:

procedure TAdvCustomMemo.GotoEnd;
beginCurY := Lines.Count - 1;CurX := Length(Lines[Lines.Count - 1]);
end;

修改后函数:按照汉字字节数调整了光标的位置。

procedure TAdvCustomMemo.GotoEnd;
beginCurY := Lines.Count - 1;//SZHN 20210113//CurX := Length(Lines[Lines.Count - 1]);CurX := Length(TEncoding.ANSI.GetBytes(Lines[Lines.Count - 1]));
end;

二、使用我们的函数调整,例如反选后需要拷贝到剪贴板,此时需要修改函数:TAdvCustomMemo.CopyToClipBoard;

修改前函数代码:

procedure TAdvCustomMemo.CopyToClipBoard;
varMemHandleRTF: THandle;MemHandleHTML: THandle;rtfstr, htmlstr: AnsiString;sl,el: string;ChangeEvt: TNotifyEvent;
beginFRTFEngine := TRTFEngine.Create;ChangeEvt := OnChange;OnChange := nil;sl := InternalLines[SelStartY];el := InternalLines[SelEndY];if (SelStartY < SelEndY) thenbeginInternalLines[SelStartY] := Copy(sl, SelStartX, Length(sl));InternalLines[SelEndY] := Copy(el, 1, SelEndX);endelsebeginInternalLines[SelStartY] := Copy(sl, 1, SelStartX);InternalLines[SelEndY] := Copy(el, SelEndX, Length(el));end;下面还有,不需要修改就不贴出来....

修改后代码:注意使用了 Get_InsertPositonX_02 函数

procedure TAdvCustomMemo.CopyToClipBoard;
varMemHandleRTF: THandle;MemHandleHTML: THandle;rtfstr, htmlstr: AnsiString;sl,el: string;ChangeEvt: TNotifyEvent;//LXY 20210112positionStart,positionEnd:word;
beginFRTFEngine := TRTFEngine.Create;ChangeEvt := OnChange;OnChange := nil;sl := InternalLines[SelStartY];el := InternalLines[SelEndY];//LXY 20210113 重新定位位置{if (SelStartY < SelEndY) thenbeginInternalLines[SelStartY] := Copy(sl, SelStartX, Length(sl));InternalLines[SelEndY] := Copy(el, 1, SelEndX);endelsebeginInternalLines[SelStartY] := Copy(sl, 1, SelStartX);InternalLines[SelEndY] := Copy(el, SelEndX, Length(el));end;}if (SelStartY < SelEndY) thenbeginGet_InsertPositonX_02(sl,SelStartX,positionStart);Get_InsertPositonX_02(el,SelEndX,positionEnd);InternalLines[SelStartY] := Copy(sl, positionStart+1, Length(sl));InternalLines[SelEndY] := Copy(el, 1, positionEnd);endelsebeginGet_InsertPositonX_02(sl,SelStartX,positionStart);Get_InsertPositonX_02(el,SelEndX,positionEnd);InternalLines[SelStartY] := Copy(sl, 1, positionStart);InternalLines[SelEndY] := Copy(el, positionEnd, Length(el));end;//=================================================================>

类似需要修改的地方大概有上百处,这里不详细列举,需要的朋友可以下载。资源下载

【delphi】TMS_Component_Pack_v9.2.4.0中的TadvMemo 支持中文完美修改相关推荐

  1. JAVA Web Servlet中的异步处理 (1) -- Servlet3.0中的Async支持

    JAVA Web Servlet中的异步处理 (1) – Servlet3.0中的Async支持 每个请求来到Web容器,Web容器会为其分配一个线程来专门负责该请求,直到完成处理前,该执行线程都不会 ...

  2. vue3.0中使用Element-plus默认英文组件修改为中文

    vue3.0中使用Element-plus默认英文组件修改为中文修改方法 说明:本方法Element-plus 1.0.2-beta.59 之前的版本可以,1.0.2-beta.59之后版本请看下一篇 ...

  3. Fira Code字体中增加思源黑体支持中文字体

    在Fira Code字体基础上增加思源黑体,合并到一个字体中,解决类似sourceinsight mono模式下无法显示中文的问题 下载链接如下(不需要付费,免费下载的): FiraCode字体中增加 ...

  4. 微信小程序------MD5加密(支持中文和不支持中文)和网络请求(get和post)

    2019独角兽企业重金招聘Python工程师标准>>> 开发中常常遇到MD5加密,最近做小程序也用到了,简单总结了一下: 这要有两个加密文件,一个不支持中文,一个支持,所以你选择支持 ...

  5. mastercam西门子840d后处理_对MasterCAM9.0中SINUMERIK840D钻孔循环后处理的修改.pdf

    中国科技信息2O08年第21j期 c卜¨t帆 sI cE D 1-Ec卜IN(>oGYI lMAT Nov.2008 ≮ . 饕 钻孔循环后处理的修改 钟如全 四川信息职业技术学院 求.以前也有 ...

  6. net2.0中使用Cookie保存中文出现乱码的解决方法

    今天朋友注册会员账号使用了中文,登陆后发现用户名变成了乱码,后来发现是因为账号直接用cookie保存的,而cookie对中文不支持才导致乱码的情况.下面的代码是在网上找的 设置cookie时: Htt ...

  7. php中pathinfo不支持中文解决办法

    发现pathinfo对中文文件无法解析,解析出来的文件名都是空字符串 查看了以下php的官方文档,有这样一句话 大概意思是,pathinfo如果想要正确的解析多字节编码的字符串路径的时候,必须先通过s ...

  8. 在 .NET Compact Framework 2.0 中宿主 ActiveX 控件

    适用于: ActiveX Microsoft .NET Compact Framework 版本 2.0 摘要:了解如何在使用 .NET Compact 的应用程序中宿主 ActiveX 控件.本文提 ...

  9. 避免在 ASP.NET Core 3.0 中为启动类注入服务

    本篇是如何升级到ASP.NET Core 3.0系列文章的第二篇. Part 1 - 将.NET Standard 2.0 类库转换为.NET Core 3.0 类库 Part 2 - IHostin ...

  10. TeeChart 8.01 With Source在Delphi 7.0中的安装(转)

    转载自:http://www.360doc.com/content/10/1012/22/3572432_60499559.shtml TeeChart.v8.01安装日志. 为了安装teechart ...

最新文章

  1. 部署war包到阿里云liunx的tomcat时报错:zip END header not found
  2. sentinel安装
  3. 定义一个员工类(JAVA)
  4. python控制结构(二)_Python程序控制结构---2
  5. awk print 的用法
  6. android在Service中弹出Dialog对话框,即全局性对话框
  7. Hive更换TEZ引擎
  8. 泛型数组 c# 0104
  9. C#LeetCode刷题之#168-Excel表列名称(Excel Sheet Column Title)
  10. Flask session
  11. deeplung代码实现测试是卡住情况说明
  12. 通过自定义Module实现URl重写和登陆验证
  13. QTP自动化测试-点滴-步骤
  14. JavaScript文档对象模型DOM节点操作之创建和添加节点(5)
  15. C++中两种计算时间方法的比较
  16. Android音频系统学习二:Android音频框架
  17. Java提取视频中的音频(JavaCV)
  18. moment 的使用 当月第一天
  19. 计算机网络掉线,电脑网络经常掉线的解决方法
  20. 绝对值函数可导点的判断

热门文章

  1. 含蓄的告别,google今日LOG
  2. BZOJ 3162 独钓寒江雪
  3. 2019/7/31随笔
  4. built a JNCIS LAB系列:Chapter 1 Routing Policy
  5. 如何制作ISO镜像文件
  6. 90后程序英雄季逸超
  7. L2-016 愿天下有情人都是失散多年的兄妹(25 分)
  8. 实验六 卷积神经网络(4)ResNet18实现MNIST
  9. AndroidTV开发-实现APP开机自启动
  10. 用CSS来实现一些动画在vue中使用之流星滑过(3)