lazarus缺臨門一腳(中文輸入問題) [論壇 - Ubuntu 程式設計]


正在瀏覽:   1 名遊客


 到底部   前一個主題   下一個主題  [無發表權] 請登錄或者註冊

(1) 2 3 »


lazarus缺臨門一腳(中文輸入問題)
會員三級
註冊日期:
2006/11/16 8:27
所屬群組:
已註冊使用者
等級: 10
HP : 0 / 228
MP : 41 / 11256
EXP: 12
離線
經過了數千年的等待(太誇張了),目前Lazarus0.9.28beta版,下傳回來測試,測試環境9.04+gcin,在初步測試中,終於可以正常顯示和處理中文了。但是使用Gcin輸入法時有問題,在程式撰寫時,按鍵會被系統誤判,在寫好的程式輸入中文(使用大易),按一個鍵會被判讀成按了同一個鍵二次,使用注音,會跳字。
可是在9.10+ibus(酷音),不管是程式撰寫或是在寫好的程式中,輸入中文是正常的。
gcin要如何細步調整來解決這個問題呢?
備註:lazarus是類似Delphi的快速開發程式的整合視窗開發工具,使用pascal語言,可以快速完成視窗程式,雖然畫面上放二個元件加一個按鈕,編好的可執行程式高達19.6M,如果同樣的功能用python之類的來寫,只要上百個byte,真是天差地遠,但是這種開發工具最適合我這種懶人了,因為元件拉一拉、擺一擺,事件寫一寫就完成簡易工作。

2009/10/11 9:02
應用擴展 工具箱
gcin
回覆: lazarus缺臨門一腳(中文輸入問題)
Anon:gcin
你的 gcin 版本?最新的可能沒有這個問題。好像某些 .deb .rpm 的 不知為何 im-gcin.so 還是舊的,試試這個 im-gcin.so 看看

http://cle.linux.org.tw/gcin/download/im-gcin.so

2009/10/11 9:24 | b6589 fc6ab 0dc82 cf120
應用擴展 工具箱
回覆: lazarus缺臨門一腳(中文輸入問題)
會員三級
註冊日期:
2006/11/16 8:27
所屬群組:
已註冊使用者
等級: 10
HP : 0 / 228
MP : 41 / 11256
EXP: 12
離線
不管是9.04的版本(1.4.2),或是9.10的版本(1.4.5),甚至是手動安裝最新的1.4.6pre10,結果都一樣。如果硬把im-gcin.so蓋掉原來的,連切換成中文輸入都不行。

2009/10/11 19:35
應用擴展 工具箱
回覆: lazarus缺臨門一腳(中文輸入問題)
管理員
註冊日期:
2005/6/11 0:21
來自 Chia-yi City
所屬群組:
已註冊使用者
討論區管理群
等級: 20
HP : 0 / 482
MP : 160 / 25839
EXP: 31
離線
或許你可以到 gicn 官方論壇問問:http://hyperrate.com/dir.php?eid=67

2009/10/11 23:46
應用擴展 工具箱
回覆: lazarus缺臨門一腳(中文輸入問題)
會員一級
註冊日期:
2009/4/10 9:11
所屬群組:
已註冊使用者
等級: 1
HP : 0 / 18
MP : 2 / 779
EXP: 73
離線
我到這裏下載
http://sourceforge.net/projects/lazarus/files/

可否指導一下如何安裝.

2009/10/20 8:36
應用擴展 工具箱
回覆: lazarus缺臨門一腳(中文輸入問題)
會員二級
註冊日期:
2011/10/5 8:09
所屬群組:
已註冊使用者
等級: 6
HP : 0 / 128
MP : 17 / 4492
EXP: 12
離線
山不轉,路轉,我參考對岸的方法,在 Lazarus 1.0 的環境略加修改實作之後,證明確實可以改一個方式來輕鬆輸入中文字了:

1.檔案瀏覽器在/usr/share/lazarus/1.0/ide按右鍵選擇以系統管理員的身分開啟,也可能因為安裝版本不同有所差異

2.在「SourceEditor.pp」按右鍵選擇用lazarus打開

3.按F12會叫出一個視窗界面,在其下方再放下一個panel面板(align設置成 albottom),面板裡面放下一個memo(自己取名例如Memo_InsCNstrs,清掉Lines),放一個button(自己取名例如Btn_InsCNstrs,加caption),適當安排界面(比如把button設置成alright,把memo設置成 alclient等)

4.源碼裡面Ctrl+Home,然後Ctrl+F(查找),查找「InsertCVSKeyword」,會先找到這麼一行:procedure InsertCVSKeyword(const AKeyWord: string); 在這一行下面加一行:
procedure InsertKeyword(const AKeyWord: string);

5.按F3繼續找,會找到InsertCVSKeyword這個procedure,在其結尾的下面粘貼,加入下面的procedure:
procedure TSourceEditor.InsertKeyword(const AKeyWord: string);
begin
if ReadOnly then Exit;
FEditor.InsertTextAtCaret(AKeyWord);
end;
這樣,就給TSourceEditor增加了一個叫「InsertKeyword」的副程式,作用是可以通過編程語句在游標所在位置添加指定字符串。

6.雙擊視窗界面上新加的button,輸入以下語句:
procedure TSourceNotebook.Btn_InsCNstrsClick(Sender: TObject);
var i:integer;
begin
if Self.Memo_InsCNstrs.Lines.Count<=1 then
Self.GetActiveSE.InsertKeyword(Self.Memo_InsCNstrs.Lines[0])
else
begin
for i := 1 to Self.Memo_InsCNstrs.Lines.Count do
Self.GetActiveSE.InsertKeyword(Self.Memo_InsCNstrs.Lines[i-1]+LineEnding);
end;
Self.Memo_InsCNstrs.Lines.Clear;
Self.FocusEditor;
end;

7.儲存 (是 save 而不是save all) --> Tools --> Build Lazarus with Profile: Normal IDE --> 是(Y)
編譯成功之後, Lazarus的Source Editor的下半部就會多出剛才加入的 memo 和 button,這樣,每次需要輸入中文字時轉到下面輸入,然後點一下按鈕,就自動添到上面源碼游標所在位置,並且將輸入焦點轉到上面源碼裡面。

8.終於相對圓滿的解決了lazarus中文輸入問題。

2012/11/1 16:00
應用擴展 工具箱
回覆: lazarus缺臨門一腳(中文輸入問題)
會員二級
註冊日期:
2011/10/5 8:09
所屬群組:
已註冊使用者
等級: 6
HP : 0 / 128
MP : 17 / 4492
EXP: 12
離線
以下是在 Ubuntu 12.04 的32位元版本環境安裝lazarus的過程 (安裝時,請一定要手動下載來安裝,不要用Ubuntu軟體中心),這是一個類似Delphi的linux版Free Pascal整合式開發環境,讓你很容易就寫出自己的linux視窗程式,目前的最新版號是 1.0.10 版.

一.官網下載安裝檔:

到Lazarus的網站 http://www.lazarus.freepascal.org/
去下載 Lazarus Linux i386 DEB 進入最新版Lazarus資料夾,依畫面的說明,下載相關檔案,例如:
fpc_2.6.2-0_i386.deb
fpc-src_2.6.2-0_i386.deb
lazarus_1.0.10-0_i386.deb

二.安裝deb檔的注意事項:

不可直接點2下去執行(會啟動Ubuntu軟體中心去安裝,但會失敗),而是要在終端機下指令安裝,依序一次安裝1個deb檔,因為會出現尚未安裝某些相依的套件,不要在一個指令同時安裝3個deb檔,步驟如下:
[步驟1]. 在終端機切換到下載的資料夾, 一次只安裝1個deb檔, 上述的三個deb檔依序先裝 fpc 然後裝 fpc-src 最後才裝 lazarus 指令如下:
sudo dpkg -i 套件檔名.deb
若有出現相依套件未安裝的訊息,就是安裝失敗,請改為先去執行下面[步驟2].
[步驟2]. 如果失敗就先安裝出現的相依套件,但不要手動執行 sudo apt-get install 而是應該透過 sudo synaptic 來安裝剛才顯示的 [相依套件] 名稱, 在synaptic套件管理程式的畫面,搜尋該套件名稱,標記起來,套用, 因為 synaptic 會自動把這個相依套件又再出現的更多未安裝的相依套件,全部都自動提示讓你套用安裝進來, 如果只是執行 sudo apt-get -f install 仍會失敗的,還是用 sudo synaptic 的方式來安裝相依套件才是方便.
[步驟3]. 相依套件安裝成功之後,回頭再去執行一次剛才[步驟1]失敗的deb檔,就可以把3個deb檔給輕鬆順利安裝完畢,這樣Lazarus會非常穩定的運作,才不會莫名其妙的當掉.

三.Lazarus的第一次設定:

按Super鍵(Win key),在Dash主目錄的搜尋框,搜尋 lazarus 然後執行它, 就會看到跟Delphi一樣的開發環境,點一下IDE視窗,再做下列設定:
1. Tools|Options|Debugger|General| 把 Debugger type and path 選在GNU debugger (gdb)
2. Tools|Configure "Build Lazarus" 可以設定 LCL widget type 或 Target OS 或 Target CPU 若有特殊需要才來修改, 預設是編譯為Linux的可執行檔.
3. Project|Project Options|Code Generation| 把 Optimizations 要選在 Level 1 (quick and debugger friendly) (-O1)
4. Project|Project Options|Compiler Options|Linking
取消 Generate debugging info for GDB (slower / increases exe-size)
勾選 Strip symbols from executable (-Xs)
勾選 Link smart (-XX)
勾選 Win32 gui application (-WG)
這樣所編譯出來的執行檔會縮小為 4 MB以上,而不會是 20 MB以上.
5. 第一次設定的時候,可以勾選最下面的 Use these compiler options as default for new projects 這樣以後每一個專案(Project)就會套用這些設定.
6. 按 OK
7. 將來某個專案若需要設定中斷點來抓bug的話,想要使用 break point 的F7,F8,F9來逐步追蹤程式碼的執行,只要臨時改一下:
點一下IDE視窗, Project|Project Options|Linking|
要勾選Generate debugging info for GDB (slower / increases exe-size)
要取消Strip Symbols From Executable (-Xs)
要取消Link Smart (-XX)
(但是編譯出來的執行檔會變很大,執行檔至少會超過 20 MB以上)

四.專案的開啟注意事項:

每次要修改某個專案時,直接在該專案的 lpr檔 直接點兩下,就會開啟該專案供編輯修改。 但如果每次要寫尚未建立的一個全新的專案,因為就算是你從Dash主目錄去啟動Lazarus,它仍是會去開啟你最近一次開過的專案,而不是一個空白的專案,請千萬...千萬...一定要記住...要去點 IDE視窗-->Project-->Close Project-->New Project
這樣才是一個全新空白的專案,才不會去動到最近一次開過的舊專案相關檔案。

五.編譯出來的Linux程式,也是一個單一執行檔,雖然在Project Options已經設定strip指令,現在的版本又已經不支援upx指令,所以編譯出來的最小size大概都是 4 MB 以上的執行檔.

六.若要放在別台電腦執行,除了把編譯出來的執行檔copy到任一個資料夾裡,還要在檔名點滑鼠右鍵-->屬性-->權限--> 勾選 "允許檔案作為程式執行(E)" --> 關閉

七.雖然Lazarus 「號稱」改用 unicode,但不建議你把 delphi的程式用Convert轉移到 lazarus 上使用,(複製一份到工作資料夾,Project-->Close Project-->Convert Delphi Project-->指到你複製的 dpr檔-->開啟)因為 delphi 的程式碼是 ansi text 格式,Lazarus 是unicode 格式,所以當你的form有「中文字」,則Convert之後都會變為亂碼,因為Lazarus並不是把你的中文字當作是BIG5編碼來轉換為UTF8,而且有很多指令或元件(尤其是自製或第三方元件)在Linux環境底下的Lazarus不能用,仍必須做很多修改的工作。

八.關於 include file 注意事項及範例:

若要如同Delphi一樣把自己寫的許多副程式或函式,集中放在一個特定的資料夾裡(例如 userinc 這個資料夾),供其他專案程式共用呼叫,就要注意幾個地方:
1. 不論是撰寫 *.inc 或呼叫使用,都要注意英文字母大小寫必須完全一致,例如宣告的時候是寫 function myNewFnc(AA:Integer):Boolean;
那麼在include的時候就不可寫為 {$I ../userinc/mynewfnc.inc}
而是必須寫為 {$I ../userinc/myNewFnc.inc}
或是在主程式引用呼叫的時候,就不可寫為 if mynewfnc(aNum) then ...
而是必須寫為 if myNewFnc(aNum) then ...
2. 集中存放的每一個副程式(procedure)或每一個函式(function)要儲存為 includ file 也就是 *.inc 而不是 *.pas 例如 myNewFnc.inc 或 myOwnProc.inc
3. 要引用這些 *.inc 的專案(project)要設定: Project-->Project Options-->Compiler Options-->Paths-->Include files 按右側的[...]指到 *.inc 存放的資料夾位置-->開啟-->按Add 就可看到Search paths的大框框裡出現你指定的資料夾位置-->按OK 就可看到已經加進 Include files 這一欄裡面了-->按OK
4. 寫一個 unit 把你需要共用呼叫的副程式(procedure)或函式(function)都集中宣告在這個 unit file 裡面,存檔為 *.pas 而且放在你的專案(project)相同資料夾裡, 例如 myfunc.pas 這個unit檔的格式如下:
unit myfunc;
{$mode objfpc} {$H+} // 如有用到PChar()就一定要有這個 H+
interface
uses
Classes, SysUtils, StdCtrls; // 若下面的procedure或function有需要其他的系統unit或第三方unit 就要一起uses進來
function myNewFnc(St:String) : String;
procedure myOwnProc(var txts:String);
// 在此處繼續宣告你自己寫的其他procedure或function
implementation
{$I ../userinc/myNewFnc.inc}
{$I ../userinc/myOwnProc.inc}
// 在此處逐一列出上面宣告出來的其他procedure或function的 *.inc 檔名(含路徑)
end.
5. 在你的主程式(通常預設是 Unit1.pas)的 implementation 下面新增一行:
uses myfunc; // 也就是你所寫的 myfunc.pas (用來集中宣告所需的 *.inc)
6. 這樣在其他專案(project)也可以用此模式來呼叫這些已經寫好的 *.inc 的副程式(procedure)或函式(function),真的非常方便哦!

如果你用過 Delphi 的IDE環境,那你也會如同我一樣對 Lazarus 的IDE環境感到親切不已,對於 Lazarus 的穩定感到驚奇不已(可能是我只寫幾個自用的小程式),祝各位使用愉快!

2013/8/13 13:37
應用擴展 工具箱
回覆: lazarus缺臨門一腳(中文輸入問題)
會員二級
註冊日期:
2011/10/5 8:09
所屬群組:
已註冊使用者
等級: 6
HP : 0 / 128
MP : 17 / 4492
EXP: 12
離線
要讓lazarus的TMemo在Ubuntu系統可以開啟及儲存由微軟Windows系統所儲存正體中文Big5編碼的文字檔:

因為lazarus都是UTF-8編碼,如果直接用Memo1.LoadFromFile()在Ubuntu系統會無法開啟Big5編碼的文字檔, 但是可以透過TStringList來讀入之後,判斷文字內容若是Big5編碼,就利用CP950ToUTF8()把Big5編碼轉為UTF-8編碼的文字, 就可以放入Memo1.Text來顯示文字檔的內容,也就是TMemo只能顯示UTF-8編碼的文字.
儲存檔案時,若原檔案是Big5編碼,就要先利用UTF8ToCP950()把Memo1.Text由UTF-8編碼轉為Big5編碼才儲存, 而且把列結尾都改為微軟Windows系統的 CR+LF 格式,底下所列示的範例或許不是很嚴謹的方法,但卻是可行的:

一. 如前一篇 include file 的方式,先在你的主程式(通常預設是 Unit1.pas)的 implementation 下面新增兩行:

uses myfunc; // 也就是你所寫的 myfunc.pas (用來集中宣告所需的 *.inc)
var isBig5: Boolean; // 宣告一個公用變數,來暫存開啟的文字檔是否為Big5編碼,做為存檔的參考(依原編碼方式存檔)

二. 假設Button1的OnClick就是開啟一個文字檔,透過 LoadToMemo.inc 判斷若是Big5編碼就要轉為UTF-8編碼,把檔案內容顯示在Memo1裡面:

procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDlg.Execute and FileExists(OpenDlg.FileName) then begin
isBig5:=LoadToMemo(Memo1, OpenDlg.FileName);
end;
end;

三. 假設Button2的OnClick就是把開啟在Memo1的文字內容,透過 SaveAmemo.inc 依原編碼方式儲存檔案:

procedure TForm1.Button2Click(Sender: TObject);
begin
if SaveDlg.Execute then SaveAmemo(Memo1, SaveDlg.FileName, isBig5);
end;

四. 然後撰寫 myfunc.pas 如下, 把需要的 ../userinc/*.inc 都宣告進來:

unit myfunc;
{$mode objfpc} {$H+}
interface
uses
Classes, SysUtils, StdCtrls,
lazutf8, // 才可使用UTF8CharacterLength(),
LConvEncoding; // 才可使用CP950ToUTF8()把Big5轉為UTF-8, 或是使用UTF8ToCP950()把UTF-8轉為Big5
function LoadToMemo(thisMemo: TMemo; FnofName: String) : Boolean;
procedure SaveAmemo(thisMemo: TMemo; FnofName: String; toBig5CrLf: Boolean);
function isBig5str(thisTxt: String) : Boolean;
function ChDwLength(thisTxt: String) : Integer;
implementation
{$I ../userinc/LoadToMemo.inc}
{$I ../userinc/SaveAmemo.inc}
{$I ../userinc/isBig5str.inc}
{$I ../userinc/ChDwLength.inc}
end.

五. 然後撰寫 ../userinc/LoadToMemo.inc 如下:

function LoadToMemo(thisMemo: TMemo; FnofName: String) : Boolean;
var isCP950: Boolean; // CP950 就是 BIG5編碼
txts: String;
thisStrLst: TStringList;
begin
result:=False; // 預設不是BIG5編碼
thisMemo.Lines.LoadFromFile(FnofName);
if (thisMemo.Lines.Count>0) then exit;
// 若原內容不是UTF-8編碼的文字檔,則此時thisMemo會是空的,需要進一步判斷編碼方式,改用TStringList來載入文字檔
thisStrLst:=TStringList.Create;
try
thisStrLst.LoadFromFile(FnofName);
finally
txts:=thisStrLst.Text;
thisStrLst.Free;
end;
isCP950:=isBig5str(txts); // 判斷來源是否為 Big5編碼 的中文字內容
if isCP950 then thisMemo.Text:=CP950ToUTF8(txts); // 把Big5字串轉為Utf-8字串,但要先把 LConvEncoding 這一個單元先uses進來
// 如果原內容也不是 Big5編碼 則thisMemo仍會是空的
result:=isCP950;
end;

六. 然後撰寫 ../userinc/SaveAmemo.inc 如下:

procedure SaveAmemo(thisMemo: TMemo; FnofName: String; toBig5CrLf: Boolean);
var
KK: Integer;
FileVar: TextFile;
begin
if toBig5CrLf then begin // encoding is BIG5
AssignFile(FileVar, FnofName);
try
Rewrite(FileVar);
for KK:=0 to (thisMemo.Lines.Count-1) do begin
Write(FileVar,UTF8ToCP950(thisMemo.Lines[KK])); // 把Utf-8字串轉為Big5字串,但要先把 LConvEncoding 這一個單元先uses進來
Write(FileVar,#13#10); // 每列的換行符號改為微軟Windows系統的 CR+LF 格式的 0D 0A 此處若是用 Writeln() 就仍是只有 0A 而已.
end;
finally
CloseFile(FileVar);
end;
end
else // encoding is Utf-8
thisMemo.Lines.SaveToFile(FnofName);
end;

七. 然後撰寫 ../userinc/isBig5str.inc 如下:

function isBig5str(thisTxt: String) : Boolean;
// 判斷 thisTxt 若是 BIG5編碼的字串就傳回True, 若是 UTF8編碼的字串或每個byte都是小於128的符號就傳回False
var Kloop,Lens,ChDwsLen: Integer;
chBtVlu: Byte;
ChinaWord: Boolean;
BigToUtfStr: String;
begin
result:=False; ChinaWord:=False;
Lens:=Length(thisTxt);
for Kloop:=1 to Lens do begin
chBtVlu:=Ord(thisTxt[Kloop]);
if (chBtVlu>127) then begin
// 從第1個遇到的中文字才開始做判斷,而且要直到最後一個byte,不可只截一段,以免右邊切在半個中文字
ChinaWord:=True;
thisTxt:=Copy(thisTxt,Kloop,Lens); // 因為要以原bytes來處理,所以不可用UTF8Copy()
Lens:=Lens-Kloop+1;
break;
end;
end; // for Kloop
if not ChinaWord then exit;
BigToUtfStr:=CP950ToUTF8(thisTxt);
ChDwsLen:=ChDwLength(BigToUtfStr);
result:=(Lens=ChDwsLen);
end;

八. 然後撰寫 ../userinc/ChDwLength.inc 如下:

function ChDwLength(thisTxt: String) : Integer;
// 這是視覺上的字串長度,計算單位:(英文字母是1,中文字是2,全型符號是2),也就是模擬微軟Windows系統Big5編碼的字串長度計算方式.
// 此處不使用lazarus的Length()因為在英文字母是1,而中文字可能會是3~4, 而全型符號可能會是2~3
// 也不使用lazutf8的UTF8Length()因為在英文字母是1,而中文字是1, 而全型符號是1
var
p: PChar;
ChDwChrs,Utf8Bytes: Integer;
begin
p:=PChar(thisTxt); // 指到第一個字
ChDwChrs:=0;
repeat
Utf8Bytes:=UTF8CharacterLength(p); // 現在p所指到的一個UTF8的字的 byte 數目(英文字母是1,中文字是3或4,全型符號是2或3)
if (Utf8Bytes=1) then
Inc(ChDwChrs,1) // 一律算作是1
else if (Utf8Bytes>1) then
Inc(ChDwChrs,2); // 一律算作是2
inc(p,Utf8Bytes); // 指到下一個UTF8的字
until (Utf8Bytes=0) or (p^ = #0);
result:=ChDwChrs;
end;

九. 編譯出來的程式在Ubuntu系統,用TMemo就可以對UTF-8編碼或Big5編碼的文字檔做 開啟、修改、儲存, 這樣如果有個文字檔必須經常用在Ubuntu系統及微軟Windows系統做編輯修改, 就可以用此方法在Ubuntu共用同一個文字檔, 很方便哦!

2013/8/24 23:59
應用擴展 工具箱
回覆: lazarus缺臨門一腳(中文輸入問題)
會員二級
註冊日期:
2011/10/5 8:09
所屬群組:
已註冊使用者
等級: 6
HP : 0 / 128
MP : 17 / 4492
EXP: 12
離線
解決lazarus的 TMemo.CaretPos 的怪異現象

Memo1.CaretPos 只在 Memo1.MemoAreaMouseUp() 及 Memo1.MemoAreaKeyUp() 才會更新,其他時候都不會更新, 而且怪異的是: 它指的是Up的位置, 可能是已選取的第一個字的左側位置, 也可能是已選取的最後一個字的位置!
如果在程式中重新指定 Memo1.SelStart 但 Memo1.CaretPos 根本就不會自動更新,所以這時的 Memo1.CaretPos 一定都是錯的! 所以只有在 Memo1.MemoAreaMouseUp() 及 Memo1.MemoAreaKeyUp() 才可以信任 Memo1.CaretPos 那麼在其他情況就必須自己找出正確的 TMemo 目前選取字串的位置資訊.

同樣的在lazarus用 include file 的方式,自製一個 selctRows.inc 就可以隨時呼叫 selctRows() 來取得 TMemo 目前選取字串的位置資訊, 關於 include file 的注意事項請參考前面的貼文, 在此不再贅述, 僅列出 selctRows.inc 程式碼如下:

procedure selctRows(aMemo: TMemo; var bgColRow,edColRow: TPoint; var Lis0A,Ris0A: Boolean);
// 傳回aMemo目前選取字串的位置資訊, bgColRow是第1個字左側(SelStart)的格數及列數, edColRow是第後一個字的格數及列數,
// 若SelLength>0 則 Lis0A,Ris0A 是判斷選取文字的第1個Byte及最後1個Byte, 若是換行符號 #10 就傳回 True, 因為Ubuntu環境的lazarus的TMemo換行符號只會是 #10 而不會是 #13#10
// 若SelLength=0 則 Lis0A,Ris0A 是判斷 caret (游標)的左右兩側的Byte, 若是換行符號 #10 就傳回 True, 因為Ubuntu環境的lazarus的TMemo換行符號只會是 #10 而不會是 #13#10
// Lis0A,Ris0A 搭配 TMemo.SelLength 可供參考選取列數的取捨,視需要可做更進一步精準的選取列數調整.
var Kloop,chrBytes,selCharstart,selcnt0As,frontcnt0As,CharLen,theLnChars,AChars,BChars: Integer;
selStr,oneChar: String;
p: PChar;
begin
selStr:=aMemo.SelText; chrBytes:=Length(selStr); selCharstart:=aMemo.SelStart;
bgColRow:=aMemo.CaretPos; edColRow:=bgColRow;
if (chrBytes=0) then begin
// 若SelLength=0 則 Lis0A,Ris0A 是判斷游標的左右兩側的Byte
oneChar:=UTF8Copy(aMemo.Text,selCharstart,1);
Lis0A:=(oneChar=#13) or (oneChar=#10);
oneChar:=UTF8Copy(aMemo.Text,selCharstart+1,1);
Ris0A:=(oneChar=#13) or (oneChar=#10);
end
else begin
// 若SelLength>0 則 Lis0A,Ris0A 是判斷選取文字的第1個Byte及最後1個Byte
Lis0A:=(selStr[1]=#10) or (selStr[1]=#13);
Ris0A:=(selStr[chrBytes]=#10) or (selStr[chrBytes]=#13);
end; // if (chrBytes=0)
p:=PChar(aMemo.Text); // 指到第一個字
Kloop:=0; CharLen:=1; frontcnt0As:=0; selcnt0As:=0; theLnChars:=0; AChars:=0; BChars:=0;
while (Kloop<selCharstart+aMemo.SelLength) and (CharLen<>0) and (p^ <> #0) do begin
CharLen:= UTF8CharacterLength(p); // 現在p所指到的一個UTF8的字的 byte 數目(英文字母是1,中文字是3或4,全型符號是2或3)
if (CharLen=0) then break;
Inc(Kloop);
if (P[0]=#10) then begin
if (Kloop<=selCharstart) then
Inc(frontcnt0As) // 計算aMemo.SelStart前面的 0A 有幾個,暫放於 frontcnt0As
else if (Kloop<=selCharstart+aMemo.SelLength) then
Inc(selcnt0As); // 計算已選取字串裡的 0A 有幾個,暫放於 selcnt0As
theLnChars:=0;
end
else
Inc(theLnChars); // 累計在該列的UTF8字數
if (Kloop=selCharstart) then AChars:=theLnChars; // 已選取字串selCharstart前一字,在該列的UTF8字數(不是byte數)
if (Kloop=selCharstart+aMemo.SelLength) then BChars:=theLnChars; // 最後一個已選取字串的字,在該列的UTF8字數(不是byte數)
inc(p,CharLen); // 指到下一個UTF8的字
end; // while
bgColRow:=Point(AChars,frontcnt0As); edColRow:=Point(BChars,frontcnt0As+selcnt0As);
end;

如前面的貼文把 selctRows.inc 宣告好之後, 就可以在主程式的Button1的OnClick呼叫 selctRows() 來取得 Memo1 目前選取字串的位置資訊.

procedure TForm1.Button1Click(Sender: TObject);
var Lis0A, Ris0A: Boolean;
bgColRow, edColRow: TPoint;
txts: String;
begin
selctRows(Memo1, bgColRow, edColRow, Lis0A, Ris0A);
txts:='bg X,Y='+inttostr(bgColRow.X)+','+inttostr(bgColRow.Y)
+' ed X,Y='+inttostr(edColRow.X)+','+inttostr(edColRow.Y)
+' Left';
if Lis0A then txts:=txts+'是' else txts:=txts+'不是';
txts:=txts+'0A Right';
if Ris0A then txts:=txts+'是' else txts:=txts+'不是';
txts:=txts+'0A';
ShowMessage(txts);
end;

在lazarus程式碼中任意把 TMemo 的游標(caret)移到指定的 Col及Row 位置, 雖然可以用重新設定 Memo1.CaretPos 來把游標(caret)移過去, 但是 Memo1 的內容不會自動把新游標位置的內容捲動(scroll)到可視範圍內, 必需再用 Memo1.SelStart 來使lazarus把新游標位置的內容捲動到可視範圍內, 所以再寫一個 setCaretClRw.inc 來把 TMemo 的游標移到指定的 Col及Row 位置, 例如搜尋字串找到下個相符字串之後, 可以用此方法把此字串選取起來.

在此僅列出 setCaretClRw.inc 的程式碼如下:

procedure setCaretClRw(aMemo: TMemo; NewCol,NewRow,SelLen: Integer);
begin
aMemo.CaretPos:=Point(NewCol,NewRow); // 把游標移動到第NewRow列的第NewCol格
aMemo.SelStart:=aMemo.SelStart+0; // 把新游標位置的內容捲動(scroll)到可視範圍內,此處只能+0
aMemo.SelLength:=SelLen; // 設定選取的長度
end;

如前面的貼文把 setCaretClRw.inc 宣告好之後, 就可以在主程式的Button2的OnClick呼叫 setCaretClRw() 來設定 Memo1 移動到指定的 CC及RR 位置及設定選取的LL長度.

procedure TForm1.Button2Click(Sender: TObject);
var CC,RR,LL: Integer;
begin
CC:=StrToInt(Edit1.Text);
RR:=StrToInt(Edit2.Text);
LL:=StrToInt(Edit3.Text);
setCaretClRw(Memo1, CC, RR, LL);
end;

2013/8/25 11:24
應用擴展 工具箱
回覆: lazarus缺臨門一腳(中文輸入問題)
會員三級
註冊日期:
2009/1/10 10:33
所屬群組:
已註冊使用者
等級: 14
HP : 0 / 341
MP : 82 / 14706
EXP: 66
離線
請問Chinlung 大大,
您使用哪一種Linux 中文輸入法?
小弟用gcin,但是發現與TMemo 不相容,很困擾。

2013/8/25 12:52
應用擴展 工具箱

(1) 2 3 »

 [無發表權] 請登錄或者註冊


可以查看帖子.
不可發帖.
不可回覆.
不可編輯自己的帖子.
不可刪除自己的帖子.
不可發起投票調查.
不可在投票調查中投票.
不可上傳附件.
不可不經審核直接發帖.