我需要用 Delphi 6/7 繪制條形碼(QR)。該程式可以在各種windows語言環境中運行,資料來自輸入框。
在這個輸入框中,用戶可以選擇一個字符集,并輸入自己的語言。這作業正常。輸入資料僅來自同一代碼頁。示例配置可能是:
- Windows 在西歐,ANSI 文本的代碼頁 1252
- 輸入以 Shift-JIS ANSI 字符集完成
我需要讓 Shift-JIS 對著條形碼。最穩健的方法是使用十六進制編碼。
所以我的問題是:如果代碼頁與 Windows 區域設定不同,我如何從 Shift-JIS 轉到 UTF-8 編碼的十六進制字串?
例如:我有字串能ラ。這需要E883BDE383A9根據 UTF-8 進行轉換。我已經嘗試過了,但結果不同且毫無意義:
String2Hex(UTF8Encode(ftext))
不幸的是,我不能只為 WideStrings 提供一個輸入框。但是,如果我能找到將 ANSI 文本轉換為 WideString 的方法,那么條形碼模塊也可以使用 Unicode 字串。
如果相關:我正在使用 TEC-IT TBarcode DLL。
uj5u.com熱心網友回復:
創建和訪問 Unicode 文本控制元件
這比您想象的要容易,而且我在過去使用全新的Windows 2000時就這樣做了,因為Tnt Delphi Unicode 控制元件等方便的組件不可用。了解如何在不使用Delphi的 VCL 和手動創建所有內容的情況下創建Windows GUI 程式的背景知識會有所幫助 - 否則這也是對它的介紹。
首先向您的表單添加一個屬性,以便我們稍后可以輕松訪問新控制元件:
type TForm1= class(TForm) ... private hEdit: THandle; // Our new Unicode control end;現在只需在您最喜歡的活動中創建它 - 我選擇了
FormCreate:// Creating a child control, type "edit" self.hEdit:= CreateWindowW( PWideChar(WideString('edit')), PWideChar(WideString('myinput')), WS_CHILD or WS_VISIBLE, 10, 10, 200, 25, Handle, 0, HINSTANCE, nil ); if self.hEdit= 0 then begin // Failed. Get error code so we know why it failed. //GetLastError(); exit; end; // Add a sunken 3D edge (well, historically speaking) if SetWindowLong( self.hEdit, GWL_EXSTYLE, WS_EX_CLIENTEDGE )= 0 then begin //GetLastError(); exit; end; // Applying new extended style: the control's frame has changed if not SetWindowPos( self.hEdit, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or SWP_NOMOVE or SWP_NOZORDER or SWP_NOSIZE ) then begin //GetLastError(); exit; end; // The system's default font is no help, let's use this form's font (hopefully Tahoma) SendMessage( self.hEdit, WM_SETFONT, self.Font.Handle, 1 );在某些時候,您想要獲取編輯的內容。再說一遍:沒有Delphi的 VCL 而是直接使用WinAPI是如何做到的?這次我使用了一個按鈕的
Click事件:var sText: WideString; iLen, iError: Integer; begin // How many CHARACTERS to copy? iLen:= GetWindowTextLengthW( self.hEdit ); if iLen= 0 then iError:= GetLastError() else iError:= 0; // Could be empty, could be an error if iError<> 0 then begin exit; end; Inc( iLen ); // For a potential trailing #0 SetLength( sText, iLen ); // Reserve space if GetWindowTextW( self.hEdit, @sText[1], iLen )= 0 then begin // Copy text //GetLastError(); exit; end; // Demonstrate that non-ANSI text was copied out of a non-ANSI control MessageBoxW( Handle, PWideChar(sText), nil, 0 ); end;
有一些細節問題,比如無法通過 訪問這個新控制元件Tab,但我們基本上已經在重新發明Delphi的 VCL,所以這些是其他時候需要注意的細節。
轉換代碼頁
WinAPI處理代碼頁(字串)或UTF-16 LE(寬字串)。由于歷史原因(UCS-2 和更高版本)UTF-16 LE 適合所有內容,因此這始終是來自代碼頁時要實作的隱含目標:
// Converting an ANSI charset (String) to UTF-16 LE (Widestring)
function StringToWideString( s: AnsiString; iSrcCodePage: DWord ): WideString;
var
iLenDest, iLenSrc: Integer;
begin
iLenSrc:= Length( s );
iLenDest:= MultiByteToWideChar( iSrcCodePage, 0, PChar(s), iLenSrc, nil, 0 ); // How much CHARACTERS are needed?
SetLength( result, iLenDest );
if iLenDest> 0 then begin // Otherwise we get the error ERROR_INVALID_PARAMETER
if MultiByteToWideChar( iSrcCodePage, 0, PChar(s), iLenSrc, PWideChar(result), iLenDest )= 0 then begin
//GetLastError();
result:= '';
end;
end;
end;
源代碼頁由您決定:也許
1252對于“Windows-1252”= ANSI 拉丁語 1 多語言(西歐)932"Shift-JIS X-0208" = IBM-PC 日本 MIX (DOS/V) (DBCS) (897 301)28595對于“ISO 8859-5”= 西里爾文65001對于“UTF-8”
但是,如果您想從一個代碼頁轉換到另一個代碼頁,并且源代碼頁和目標代碼頁都不能是 UTF-16 LE,那么您必須來回轉換:
- 從 ANSI 轉換為 WIDE
- 從 WIDE 轉換為不同的 ANSI
// Converting UTF-16 LE (Widestring) to an ANSI charset (String, hopefully you want 65001=UTF-8)
function WideStringToString( s: WideString; iDestCodePage: DWord= CP_UTF8 ): AnsiString;
var
iLenDest, iLenSrc: Integer;
begin
iLenSrc:= Length( s );
iLenDest:= WideCharToMultiByte( iDestCodePage, 0, PWideChar(s), iLenSrc, nil, 0, nil, nil );
SetLength( result, iLenDest );
if iLenDest> 0 then begin // Otherwise we get the error ERROR_INVALID_PARAMETER
if WideCharToMultiByte( iDestCodePage, 0, PWideChar(s), iLenSrc, PChar(result), iLenDest, nil, nil )= 0 then begin
//GetLastError();
result:= '';
end;
end;
end;
根據每個Windows安裝,并非每個代碼頁都受支持,或者支持不同的代碼頁,因此轉換嘗試可能會失敗。立即針對Unicode程式會更加健壯,因為這是每個Windows安裝都明確支持的(除非您仍然處理Windows 95、Windows 98或Windows ME)。
結合一切
現在您已經獲得了將其組合在一起所需的一切:
- 您可以使用Unicode文本控制元件直接在 UTF-16 LE 中獲取它
- 您可以使用 ANSI 文本控制元件然后將輸入轉換為 UTF-16 LE
- 您可以從 UTF-16 LE (WIDE) 轉換為 UTF-8 (ANSI)
尺寸
UTF-8 通常是最好的選擇,但是當您的目標受眾是亞洲人時,UTF-16 的大小可能需要更少的位元組總數:在 UTF-8 中,兩者都能需要ラ3 個位元組,但在 UTF-16 中,兩者都只需要 2 個位元組. 我猜,根據您的 QR 條碼大小是一個重要因素。
同樣,不要浪費將二進制資料(每位元組 8 位)轉換為 ASCII 文本(每個字符顯示 4 位,但本身又需要 1 位元組 = 8 位)。看看Base64將 6 位編碼到每個位元組中。您已經在生活中遇到過無數次的概念,因為它用于電子郵件附件。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/460936.html
標籤:德尔福 统一码 十六进制 代码页 ansistring
上一篇:C convertStringToByteArray到DelphiconvertStringToByteArray
