lazarus缺臨門一腳(中文輸入問題) [論壇 - Ubuntu 程式設計]
正在瀏覽:
1 名遊客
lazarus缺臨門一腳(中文輸入問題) |
|||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
會員三級
![]() ![]() 註冊日期:
2006/11/16 8:27 所屬群組:
已註冊使用者 等級: 10
HP : 0 / 228
![]() |
經過了數千年的等待(太誇張了),目前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
![]() |
不管是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
![]() |
或許你可以到 gicn 官方論壇問問:http://hyperrate.com/dir.php?eid=67
2009/10/11 23:46
|
||||||||||
![]() |
回覆: lazarus缺臨門一腳(中文輸入問題) |
|||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
會員一級
![]() ![]() 註冊日期:
2009/4/10 9:11 所屬群組:
已註冊使用者 等級: 1
HP : 0 / 18
![]() |
2009/10/20 8:36
|
||||||||||
![]() |
回覆: lazarus缺臨門一腳(中文輸入問題) |
|||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
會員二級
![]() ![]() 註冊日期:
2011/10/5 8:09 所屬群組:
已註冊使用者 等級: 6
HP : 0 / 128
![]() |
山不轉,路轉,我參考對岸的方法,在 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
![]() |
以下是在 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
![]() |
要讓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
![]() |
解決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
![]() |
請問Chinlung 大大,
您使用哪一種Linux 中文輸入法? 小弟用gcin,但是發現與TMemo 不相容,很困擾。
2013/8/25 12:52
|
||||||||||
![]() |
您可以查看帖子.
您不可發帖.
您不可回覆.
您不可編輯自己的帖子.
您不可刪除自己的帖子.
您不可發起投票調查.
您不可在投票調查中投票.
您不可上傳附件.
您不可不經審核直接發帖.