日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/16 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【delphi】TMS_Component_Pack_v9.2.4.0中的TadvMemo 支持中文完美修改 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

大家知道,在delphi的開發環境中,TMS是赫赫有名的三方控件提供商,基本上沒有不知道或者沒有不使用的。TMS提供的控件包羅萬象,非常豐富。但是有一個控件TadvMemo的一個編輯控件,支持語法(delphi,basic,HTML,javascript,css,SQL,C#等等)高亮,很好用,就是有一個硬結是不支持中文,相信大家在使用的過程中都有體會,我問了TMS,答復是tadvMemo只支持monospace字體。而且這個控件版本已經升級的很高了也沒有支持中文,看來只能自己修改了。于是我們修改了TadvMemo源代碼,使其完美支持中文。

簡單的幾個函數就可以讓TadvMemo 支持中文,修改后的代碼下載。
修改后的TadvMemo支持中文功能測試如下:

編號功能結論
1輸入中文顯示半個漢字修改后正確顯示
2光標不能放置到一個漢字的中間修改后正確
3Ctrl + Left(home)光標到行首修改后正確
4Ctrl + Right(end)光標到行尾修改后正確
5鼠標或者按鍵反選修改后正常
6反選后拷貝到外邊修改后正常
7從外邊拷貝進入編輯器修改后正常
8overwrite下輸入中文修改后正常
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 支持中文完美修改的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。