我想开发一个hex-dump-view,并且在当前活动的ANSI代码页(CP_ACP)中无法打印的字符存在问题。如何检测它们并打印一个点呢?
我的功能目前看起来像这样:
function HexChar(j: byte): AnsiChar;
begin
if j < $20 then result := '.'
// Dirty workaround which only supports the undefined characters of Windows-1252
else if (GetACP=1252) and ((j=$81) or (j=$8D) or (j=$8F) or (j=$90) or (j=$9D)) then result := '.'
else result := AnsiChar(j);
end;
使用Delphi XE4和字体Courier New,字符$ 81,$ 8D,$ 8F,$ 90,$ 9D是不可见的。 GetACP
返回1252,所以我使用的是Windows-1252。根据{{3}},我发现的范围没有在Windows-1252中定义。如何检查当前活动代码页中是否定义了序号为j
的字符?
答案 0 :(得分:2)
调用支持详细字符分类的GetStringTypeW
函数。
也可以使用GetStringTypeEx
或已弃用的GetStringTypeA
函数,但两者都只根据MSDN调用GetStringTypeW
。此外,GetStringTypeEx
隐藏ANSI和Unicode版本之间的差异,并由MSDN推荐用于字符类型检索。
另一种可能性是使用TCharacter.GetUnicodeCategory()中的character.pas
方法。
答案 1 :(得分:1)
将GetGlyphIndices
与GGI_MARK_NONEXISTING_GLYPHS一起使用,以检查字体中是否存在特定字符。
以下是一个例子:
procedure ReplaceNonPrintableChars(var s: string);
var
GlyphIndicesA: PWordArray;
Len: Integer;
I: Integer;
Cnt: DWORD;
DC: THandle;
C: TCanvas;
begin
DC := GetDC(0);
try
C := TCanvas.Create;
try
C.Handle := DC;
C.Font.Name := 'Arial';
Len := Length(S);
GetMem(GlyphIndicesA, SizeOf(Word) * Len);
try
Cnt := GetGlyphIndices(C.Handle, PChar(S), Len, PWord(GlyphIndicesA), GGI_MARK_NONEXISTING_GLYPHS);
if not (Cnt = GDI_ERROR) then
for I := 0 to Cnt - 1 do
if GlyphIndicesA[I] = $FFFF then
S[I+1] := '.';
finally
Dispose(GlyphIndicesA);
end;
finally
C.Free;
end;
finally
ReleaseDC(0, DC);
end;
end;