dllee 站務副站長
    

發表:315
回覆:2470
積分:1695
註冊:2002-04-15
發送簡訊給我
|
 |
|
寫這個工具主要是整理兩天來在網路上搜尋的結果,
最後還是在 KTOP 找到解答 
感謝 SANJYSAN 在 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55094
所發表的「萬用轉碼函數」總算是讓我以前在 DOS 下使用倚天碼的文件
可以重回 BIG5 碼的懷抱

由 黃國書 Kii Ali 的「技術_NT nls 問題」列表:
"20000"="c_20000.nls" ;Taiwan 國家標準碼 CNS
"20001"="c_20001.nls" ;Taiwan 公會碼 TCA
"20002"="c_20002.nls" ;Taiwan 倚天碼 Eten
"20003"="c_20003.nls" ;Taiwan IBM5550
"20004"="c_20004.nls" ;Taiwan 電信碼 Teletext
"20005"="c_20005.nls" ;Taiwan 王安碼 Wang
應該包含大部分非BIG5的繁體中文,以我的 XP HomeEd. 預設只有裝 c_20000.nls
如果需要其他的 codepage 可以從 Windows 原版光碟中找,或是網路搜尋下載。
不想下載的就參考以下的原始碼吧
//---------------------------------------------------------------------------
// ◎ MS 定義支援的 codepage 及在 HTML 內的 CHARSET 代號對照表
//
// http://msdn.microsoft.com/workshop/author/dhtml/reference/charsets/charset4.asp
// ◎ 俄羅斯 Konstantin Kazarnovsky 對於 CP_nnnn.nls 與 C_nnnn.cls 檔的內容解析
// http://webcenter.ru/~kazarn/eng/nls.htm
// ◎ 國人 黃國書 Kii Ali 所整理的「技術_NT nls 問題」
// http://ftp.isu.edu.tw/pub/CPatch/faq/tech/tech_nlsnt.txt
// ◎ MS 說明如何自己加入 codepage
// http://msdn.microsoft.com/library/en-us/vcce/htm/evc_appendices_1.asp
// http://support.microsoft.com/default.aspx?scid=kb;EN-US;151701
// ◎ SANJYSAN 在 KTOP 所提供的「萬用轉碼函數」
// http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55094
// <2004-10-09> 整理 by Lee, Dong-Liang
// http://dllee.ktop.com.tw
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "CodePageUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TStringList *CodePageListSupported;
TStringList *CodePageList;
CPINFOEX CodePageInfoEx;
BOOL CALLBACK EnumCodePagesProc(LPTSTR lpCodePageString) // code page identifier string
{ UINT CodePage=String(lpCodePageString).ToIntDef(0); if(IsValidCodePage(CodePage)) // code page { GetCPInfoEx(CodePage,0,&CodePageInfoEx); CodePageList->AddObject(CodePageInfoEx.CodePageName,(TObject*)CodePage); CodePageListSupported->AddObject(CodePageInfoEx.CodePageName,(TObject*)CodePage); } else { CodePageList->AddObject(String(lpCodePageString)+" **Not Installed**", (TObject*)CodePage); } return true;
}
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{ CodePageList=new TStringList; CodePageListSupported=new TStringList; EnumSystemCodePages((CODEPAGE_ENUMPROC)EnumCodePagesProc, // callback function CP_SUPPORTED); // CP_INSTALLED: installed, CP_SUPPORTED: supported code pages Memo1->Lines->Add("This System Support All the following CodePage."); Memo1->Lines->Add("If the name of the CodePage is **Not Installed** means it is not installed."); Memo1->Lines->AddStrings(CodePageList); ComboBox1->Items->AddStrings(CodePageListSupported); ComboBox2->Items->AddStrings(CodePageListSupported); ComboBox1->ItemIndex=ComboBox1->Items->IndexOfObject((TObject*)950); ComboBox2->ItemIndex=ComboBox1->Items->IndexOfObject((TObject*)950); if(ComboBox1->ItemIndex<0)ComboBox1->ItemIndex=0; if(ComboBox2->ItemIndex<0)ComboBox2->ItemIndex=0; delete CodePageList; delete CodePageListSupported;
}
//---------------------------------------------------------------------------
// SANJYSAN http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55094
// 萬用轉碼函數
#define UNICODE 0
void* __fastcall TForm1::CodeConvert(void *str, int code_from, int code_to, int MAXLENG)
{ PWSTR wszUnicode = NULL; //Unicode PSTR InStr = NULL; //from Code PSTR OutStr = NULL; //to Code int iLen = 0; //char length
if (code_from!=UNICODE) // other to unicode { InStr = (char*)str; iLen = MultiByteToWideChar(code_from, 0, InStr, -1, NULL,0); wszUnicode = new wchar_t[MAXLENG+1]; MultiByteToWideChar(code_from, 0, InStr, -1, wszUnicode,iLen); if (code_to==UNICODE) return wszUnicode; } else wszUnicode = (PWSTR)str;
//unicode to other iLen = WideCharToMultiByte(code_to, 0, wszUnicode, -1, NULL,0,NULL, NULL); OutStr = new char[MAXLENG+1]; WideCharToMultiByte(code_to, 0, wszUnicode, -1, OutStr,iLen,NULL, NULL);
if (code_from!=UNICODE) delete [] wszUnicode;
return OutStr;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{ char *Output=NULL; char *Input=Memo1->Text.c_str(); Output=(char*)CodeConvert(Input, (int)ComboBox1->Items->Objects[ComboBox1->ItemIndex], (int)ComboBox2->Items->Objects[ComboBox2->ItemIndex], Memo1->Text.Length()*2); Memo1->Text=AnsiString(Output); delete Output;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{ if(OpenDialog1->Execute()) Memo1->Lines->LoadFromFile(OpenDialog1->FileName);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{ if(SaveDialog1->Execute()) { Memo1->Lines->SaveToFile(SaveDialog1->FileName); ShowMessage("File Saved"); }
}
//---------------------------------------------------------------------------
對了,忘了說明,我把 SANJYSAN 小改了一下,主要是字串長度,
原本的方式我轉出來都只有一行,後來火大,直接設一個比較大的數值
就 OK 了,而且發現設超大結果也是正常,所以,我才會直接以 2 倍
大小來處理。 另外,就是本來想用它應該也可以作簡繁轉換,沒想到
效果實在是不好... 不過,在繁轉繁的部分,應該算是不錯了。
吃軟也吃硬 dllee.ktop.com.tw StatPlus 系統資源監測器 @ SoftKing VMASK - ViewMove Automation Software Kernel
發表人 - dllee 於 2004/10/09 08:07:53 |
|
------ http://blog.yam.com/dllee/
|
conundrum 尊榮會員
    

發表:893
回覆:1272
積分:628
註冊:2004-01-06
發送簡訊給我
|
 |
|
日語馬ㄟ通喔 哈哈 哈哈哈 一句話 真好
win2000上 執行 ok ok
試用過很多翻譯日文軟體 老是翻不準不然就是無法原貌呈現
除了 南極星老軟體也可以 原貌呈現日文 但在切換方式 令人髮指
殺咪 一點不通 議神 用於老東西的本文翻譯 只能說差了
這東西好EZ 哈哈 哈哈哈 使人抓狂
|
|
|
dllee 站務副站長
    

發表:315
回覆:2470
積分:1695
註冊:2002-04-15
發送簡訊給我
|
 |
|
感謝 conundrum 的測試,讓我發現,一定要先去安裝
conundrum 大大所介紹的 Unicode 補完計畫:
參照頁:http://leoboard.cpatch.org/cgi-bin/topic.cgi?forum=21&topic=405&show=0
網址:http://search.cpatch.org/download/patchutil/unicodeaton/unicodeaton_240.exe
裝完之後,使用此工具,就可以轉簡轉繁,不過轉出來的是 BIG5 中的簡體造字(這也是之前我自己測出來效果很差,但裝了 Unicode 補完計畫後效果就還可接受),而不是真的對應的繁體字,算是小缺陷。同樣,在裝了 Unicode 補完計畫後,就可以用 BIG5 中的日文造字來顯示日文,所以,也可以把日文轉用 BIG5 來顯示,但前題是要安裝 Unicode 補完計畫,或至少要裝中國海字集 for windows 才能顯示日文造字。
吃軟也吃硬 dllee.ktop.com.tw StatPlus 系統資源監測器 @ SoftKing VMASK - ViewMove Automation Software Kernel |
|
------ http://blog.yam.com/dllee/
|
SANJYSAN 一般會員


發表:5
回覆:10
積分:3
註冊:2002-05-28
發送簡訊給我
|
 |
|
引言:
對了,忘了說明,我把 SANJYSAN 小改了一下,主要是字串長度,
原本的方式我轉出來都只有一行,後來火大,直接設一個比較大的數值
就 OK 了,而且發現設超大結果也是正常,所以,我才會直接以 2 倍
大小來處理。
因為原來的程式只是拿來轉一個字串而已,其長度來自:
iLen = MultiByteToWideChar(code_from, 0, InStr, -1, NULL,0);
所以遇上0x00的字串結尾自然就停了。要轉整篇的話,MAXLENG是個方法,但最好還是把整個buffer(file)的大小傳進去比較好。
引言:
另外,就是本來想用它應該也可以作簡繁轉換,沒想到
效果實在是不好... 不過,在繁轉繁的部分,應該算是不錯了。
簡繁體和codepage沒有關係,那是字形的關係。big5碼裡也有big5碼的簡體字形,gb碼裡也有gb碼的繁體字形,所以要簡繁轉換的話得另外轉字形才行。當然一般是內碼字形一起轉就是了。
要轉簡繁字形的話,你得在前面內碼轉碼完畢後,再呼叫一個API:
int LCMapString( LCID Locale, // locale identifier DWORD dwMapFlags, // mapping transformation type LPCTSTR lpSrcStr, // source string int cchSrc, // number of characters in source string LPTSTR lpDestStr, // destination buffer int cchDest // size of destination buffer
);
MSDN上有對於這個API的說明,裡面有參數:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_5s2v.asp
當然這些參數得另外設定,基本上沒辦法用內碼直接判斷,因gb與big5都同時具有簡繁字形的關係。除非你強迫指定成轉big5就自動變繁體,gb就自動變簡體,但不建議這麼做。
又LCMapString的字型轉換還有個有趣的功能。看看MSDN上的參數說明:
LCMAP_FULLWIDTH
LCMAP_HALFWIDTH
LCMAP_HIRAGANA
LCMAP_KATAKANA
LCMAP_LINGUISTIC_CASINGLCMAP_UPPERCASE
LCMAP_LOWERCASE
LCMAP_SIMPLIFIED_CHINESE
LCMAP_SORTKEY
LCMAP_TRADITIONAL_CHINESE
LCMAP_UPPERCASE
這也就是說,字形轉換也可以轉日文,你可以把日文裡的平假片假,半形全形等自由轉換....
|
|
|
dllee 站務副站長
    

發表:315
回覆:2470
積分:1695
註冊:2002-04-15
發送簡訊給我
|
 |
|
感謝 SANJYSAN 的指教,說真的,沒有您的「萬用轉碼函數」
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55094
也不可能有這篇...
而您提到的 LCMapString 除了
LCMAP_SIMPLIFIED_CHINESE Windows NT 4.0 and later: Maps traditional Chinese characters to simplified Chinese characters.
LCMAP_TRADITIONAL_CHINESE Windows NT 4.0 and later: Maps simplified Chinese characters to traditional Chinese characters.
有比較明顯是簡繁轉換,其他的我實在是看不懂是由什麼轉到什麼... 
有空再試試看吧...
吃軟也吃硬 dllee.ktop.com.tw StatPlus 系統資源監測器 @ SoftKing VMASK - ViewMove Automation Software Kernel |
|
------ http://blog.yam.com/dllee/
|
dllee 站務副站長
    

發表:315
回覆:2470
積分:1695
註冊:2002-04-15
發送簡訊給我
|
 |
|
已經試出來 SANJYSAN 所介紹的 LCMapString()
用 LCMAP_SIMPLIFIED_CHINESE 繁轉簡
用 LCMAP_TRADITIONAL_CHINESE 簡轉繁
在原 CodeConvert()
return OutStr;
前加上
LCMapString() 及對應的參數即可。
當然,如果所選用的參數與 From To 的 CodePage 選用不同,那結果就還是亂碼一堆  如果正確選用,如:
From : 936
To : 950
再用 LCMapString() 及 LCMAP_TRADITIONAL_CHINESE 就可以完美的簡轉繁
From : 950
To : 936
再用 LCMapString() 及 LCMAP_SIMPLIFIED_CHINESE 就可以完美的繁轉簡
這樣轉出來就像一般的簡繁互換軟體是一樣的了,效果就像之前我一直在用的
sos_admin 大大的
■【發表】e?繁???器 Ver1.0
http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55939
真的好用!!
我平常也會使用漢書XP 來作簡繁互換,現在,這個簡繁互換的功能,預計要加入 StatPlus2 中,請期待...
PS1. 預告一下: StatPlus2 目前正在設計使用者自定熱鍵介面,這樣對於不了如何操作 regedit 的使用者來說,就可以方便使用 StatPlus 了。
PS2. TOGET 的軟體登錄服務實在是太爛了!! StatPlus2 從 2004-09-03 登錄更新到目前都還沒更新上。40天了耶!! SoftKing 則是軟體登錄大約一週就刊出。
吃軟也吃硬 dllee.ktop.com.tw StatPlus 系統資源監測器 @ SoftKing VMASK - ViewMove Automation Software Kernel |
|
------ http://blog.yam.com/dllee/
|
muta 一般會員


發表:0
回覆:2
積分:0
註冊:2004-01-06
發送簡訊給我
|
 |
|
感謝兩位先進,解決我一直想要簡單轉換簡體到繁體的困擾
不敢單獨發一篇文章佔篇幅,綜合兩位的程式及發文,小弟寫成BCB可方便使用的函數如下:
// GB to BIG5
AnsiString __fastcall GBToBig5(const AnsiString str)
{
PWSTR wszUnicode = NULL; //Unicode PSTR InStr = NULL; //from Code PSTR OutStr = NULL; //to Code int iLen = 0; //char length
InStr = (char*)str.c_str(); int InSize = str.Length(); iLen = MultiByteToWideChar(936,0,InStr,InSize,NULL,0); wszUnicode = new wchar_t[iLen+1]; MultiByteToWideChar(936,0,InStr,InSize,wszUnicode,iLen);
// 簡轉繁 PWSTR wszUnicode2 = new wchar_t[iLen+1];
LCMapStringW(0x0404, // Locale id of taiwan LCMAP_TRADITIONAL_CHINESE, wszUnicode, iLen, wszUnicode2,iLen);
//unicode to other int uiLen = WideCharToMultiByte(950,0,wszUnicode2,iLen,NULL,0,NULL,NULL); OutStr = new char[uiLen+1]; WideCharToMultiByte(950,0,wszUnicode2,iLen,OutStr,uiLen,NULL,NULL);
AnsiString ret = AnsiString(OutStr); delete [] OutStr ; delete [] wszUnicode; delete [] wszUnicode2 ;
return ret ;
}
|
|
|
|