Delphi 确定字符是否可打印

Delphi 确定字符是否可打印,delphi,winapi,codepages,Delphi,Winapi,Codepages,我想开发一个十六进制转储视图,但在当前活动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 (G

我想开发一个十六进制转储视图,但在当前活动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;
函数HexChar(j:byte):AnsiChar;
开始
如果j<$20,则结果:='。'
//肮脏的解决方法,仅支持Windows-1252的未定义字符
否则,如果(GetACP=1252)和((j=81美元)或(j=8D)或(j=8F)或(j=90美元)或(j=9D)),则结果:='
其他结果:=AnsiChar(j);
结束;
使用Delphi XE4和字体Courier New,字符$81、$8D、$8F、$90、$9D是不可见的
GetACP
返回1252,所以我使用的是Windows-1252。根据,我发现的范围在Windows-1252中没有定义。如何检查序数值为
j
的字符是否在当前活动代码页中定义?

调用支持详细字符分类的函数

也可以使用或弃用函数,但根据MSDN,这两个函数都只调用
GetStringTypeW
。另外,
GetStringTypeEx
隐藏ANSI和Unicode版本之间的差异,以及MSDN推荐用于字符类型检索的差异


另一种可能是使用。

使用带有GGI_标记_不存在_字形的
GetGlyphIndex
方法,以检查字体中是否存在特定字符

下面是一个例子:

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;

您需要定义您的角色集。你的代码一下子就犯了严重的错误
Char
是一个双字节UTF-16字符。这不是你想要的。对于十六进制编辑器,您希望使用ASCII或ANSI代码页之一。你需要在这方面做出一些决定。双字节
Char
一点用都没有。我想要一个ANSI转储。我认为
Char
可以,因为ANSI字符将自动映射到unicode
HexChar
将由
HexDump
函数调用,该函数将使用
s:=s+HexChar(x)
在右侧构建人类可读的列。有许多ANSI代码页。你想要哪一个?为什么要以16位类型存储8位数据。请注意,
Chr(j)
并不像您想象的那样从ANSI转换为Unicode。它产生一个UTF-16字符元素,其序号值为
j
。我希望ANSI字符集在用户系统(CP_ACP)中处于活动状态。因此,他/她将看到与大多数十六进制编辑器完全相同的输出。现在我将使用AnsiChar(j)。
Memo1.Text:=AnsiChar($88)
在我的机器上生成插入符号,备忘录的字体设置为新。给我们一个SSCCE怎么样。唉,
IsCharAlphaNumeric
也不打印
^
~
之类的内容,因为它们既不是数字也不是字母。谢谢您的提示
GetStringType
似乎非常可靠。这是我的,也是过时的。我还有一个问题$98在我的计算机上映射到Unicode。因此,该瓷砖将自动与其邻居合并(因此十六进制转储看起来不太好)。使用
GetStringTypeW
/
CT\u CTYPE3
可以查询此合成信息吗?使用哪个函数显示结果字符串?我认为,如果您使用适当的函数将原始ANSI字符作为输入输出到
IsAnsiPrintable()
,那么这应该不会有任何问题…我将每个字符连接到我在TMemo中显示的宽字符串。使用
AnsiString
连接原始ANSI字符,然后将其分配给TMemo字符串。Hm。。。我该如何使用它呢<代码>变量x:word;dc:hdc;begindc:=GetDc(Memo1.Handle);GetGlyphIndex(dc,PChar(Char(AnsiChar(j))),1,pword(@x),GGI_MARK_NONEXISTING_glyph)始终返回
GDI_ERROR
。我添加了一个示例。您的代码检测字符是否定义为字体。但问题是,字符是否在代码页中定义。