【delphi】TMS_Component_Pack_v9.2.4.0中的TadvMemo 支持中文完美修改
大家知道,在delphi的開發(fā)環(huán)境中,TMS是赫赫有名的三方控件提供商,基本上沒有不知道或者沒有不使用的。TMS提供的控件包羅萬象,非常豐富。但是有一個控件TadvMemo的一個編輯控件,支持語法(delphi,basic,HTML,javascript,css,SQL,C#等等)高亮,很好用,就是有一個硬結(jié)是不支持中文,相信大家在使用的過程中都有體會,我問了TMS,答復(fù)是tadvMemo只支持monospace字體。而且這個控件版本已經(jīng)升級的很高了也沒有支持中文,看來只能自己修改了。于是我們修改了TadvMemo源代碼,使其完美支持中文。
簡單的幾個函數(shù)就可以讓TadvMemo 支持中文,修改后的代碼下載。
修改后的TadvMemo支持中文功能測試如下:
| 1 | 輸入中文顯示半個漢字 | 修改后正確顯示 |
| 2 | 光標(biāo)不能放置到一個漢字的中間 | 修改后正確 |
| 3 | Ctrl + Left(home)光標(biāo)到行首 | 修改后正確 |
| 4 | Ctrl + Right(end)光標(biāo)到行尾 | 修改后正確 |
| 5 | 鼠標(biāo)或者按鍵反選 | 修改后正常 |
| 6 | 反選后拷貝到外邊 | 修改后正常 |
| 7 | 從外邊拷貝進入編輯器 | 修改后正常 |
| 8 | overwrite下輸入中文 | 修改后正常 |
| 9 | 光標(biāo)上移或者下移不能移動到一個漢字中間 | 修改后正常 |
1. 修改原理
TadvMemo認(rèn)為字符都是等寬的,等寬的概念是顯示一個字符就只能占用一個顯示位置,對于英文字符是沒有問題的,但是對于中文,就不一樣的,一個中文漢字顯示的時候會占用兩個英文字符的位置,這樣就會產(chǎn)生問題。我們要做的就是把中文字符能夠合理的告知TadvMemo,為此,我們需要書寫如下函數(shù):
1.1 修復(fù)需要的函數(shù)
一、將光標(biāo)位置轉(zhuǎn)換成實際的字符位置。比如字符串:”A偉大123“,當(dāng)光標(biāo)位于”大"和“1”之間的時候,光標(biāo)是5,但是對于字符串”A偉大123“來說,如果我們要獲取光標(biāo)前的字符串“A偉大”,就不能使用光標(biāo)位置5,而應(yīng)該使用長度3,因為一個漢字作為字符串處理(unicode)也是1。
參數(shù)說明:
S:是實際字符串
CurX:表示光標(biāo)位置,光標(biāo)在行首的時候是0,每向右移動一個英文字符光標(biāo)加1,移動一個漢字光標(biāo)加2.
positon:表示轉(zhuǎn)換后字符串的位置。
結(jié)果為 True表示轉(zhuǎn)換成功,否則表示轉(zhuǎn)換失敗。
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設(shè)那個';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;二、判斷當(dāng)前光標(biāo)前是不是一個漢字, True 表示是漢字,否則是英文字母,光標(biāo)左移是需要使用此函數(shù)。
參數(shù)說明:
S:是實際字符串
CurX:表示光標(biāo)位置,
三、判斷當(dāng)前光標(biāo)后是不是一個漢字, True 表示是漢字,否則是英文字母,光標(biāo)右移的時候需要使用該函數(shù)
參數(shù)說明:
S:是實際字符串
CurX:表示光標(biāo)位置
四、判斷光標(biāo)是否在一個完整漢字的中間,正常編輯是不應(yīng)該出現(xiàn)這個問題的。
參數(shù)說明:
S:需要判斷的字符串
CurX:表示光標(biāo)位置
返回結(jié)果True 表示是在一個漢字中間,否則不是
function is_Half_Chinense(S : string; CurX : integer) : Boolean; vari : integer;B : TBytes;o : integer; //記錄半個函數(shù)數(shù)量 beginB := TEncoding.ANSI.GetBytes(S);if CurX > Length(B) then Exit(False);if CurX = 0 then Exit(False);//光標(biāo)前或者后是一個英文字符,則直接表示不再半個漢字中間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 直接調(diào)整光標(biāo)位置。
例如,當(dāng)需要把光標(biāo)移動到行尾,也就是按下Ctrl + Right(end)鍵的時候,需要修改函數(shù)中的CurX:
修改前函數(shù):
procedure TAdvCustomMemo.GotoEnd; beginCurY := Lines.Count - 1;CurX := Length(Lines[Lines.Count - 1]); end;修改后函數(shù):按照漢字字節(jié)數(shù)調(diào)整了光標(biāo)的位置。
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;二、使用我們的函數(shù)調(diào)整,例如反選后需要拷貝到剪貼板,此時需要修改函數(shù):TAdvCustomMemo.CopyToClipBoard;
修改前函數(shù)代碼:
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 函數(shù)
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;//=================================================================>類似需要修改的地方大概有上百處,這里不詳細(xì)列舉,需要的朋友可以下載。資源下載
總結(jié)
以上是生活随笔為你收集整理的【delphi】TMS_Component_Pack_v9.2.4.0中的TadvMemo 支持中文完美修改的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: li标签中hover的使用及li标签的样
- 下一篇: 安装U8后服务器开机加载信息慢,用友U8