2008年7月23日

全角→半角変換

文字列中の全角文字を(可能な範囲で)半角に変換するのにもLCMapStringを使用します。ちなみにLCMapStringのA版はバイト数で、W版は文字数で長さを扱うので注意が必要です。
uses
  Windows;

function ZenkakuToHankaku(const Str: String): String;
{$IFNDEF UNICODE}
const
  TestStr: String = '亜';
{$ENDIF}
var
  Size: Integer;
  Flags: DWORD;
{$IFNDEF UNICODE}
  Multiplier: Integer;
{$ENDIF}
begin

  Flags := LCMAP_HALFWIDTH;
{$IFNDEF UNICODE}
  Multiplier := 1;
{$ENDIF}

  { Calculate destination size }
{$IFNDEF UNICODE}
  if LCMapString(LOCALE_SYSTEM_DEFAULT,Flags,
                 PChar(TestStr),Length(TestStr),nil,0) = 1 then
  begin
    Multiplier := 2;
  end;
{$ENDIF}
  Size := LCMapString(LOCALE_SYSTEM_DEFAULT,Flags,
                      PChar(Str),Length(Str),nil,0);
{$IFNDEF UNICODE}
  Size := Size * Multiplier;
{$ENDIF}

  { Convert }
  SetLength(Result,Size);
  Size := LCMapString(LOCALE_SYSTEM_DEFAULT,Flags,
                      PChar(Str),Length(Str),PChar(Result),Size);
  if Size <= 0 then
  begin
    Result := Str;
    Exit;
  end;
  SetLength(Result,Size);

end;
2011/05/19追記: Windows 7の互換モードにおけるLCMapStringの不具合を回避するため、ANSI版の動作を修正しました。オリジナルのコードはこちら。
uses
  Windows;

function ZenkakuToHankaku(const Str: String): String;
var
  Size: Integer;
  Flags: DWORD;
begin

  Flags := LCMAP_HALFWIDTH;

  { Calculate destination size }
  Size := LCMapString(LOCALE_SYSTEM_DEFAULT,Flags,PChar(Str),Length(Str),nil,0);

  { Convert }
  SetLength(Result,Size);
  Size := LCMapString(LOCALE_SYSTEM_DEFAULT,Flags,
                      PChar(Str),Length(Str),PChar(Result),Size);
  if Size <= 0 then
  begin
    Result := Str;
    Exit;
  end;
  SetLength(Result,Size);

end;

0 件のコメント: