Microsoft.VisualBasic.Strings.StrConv の第2引数である、VbStrConv 列挙体の定義は
[Flags]
public enum VbStrConv
{
None = 0x0,
Uppercase = 0x1,
Lowercase = 0x2,
ProperCase = 0x3,
Wide = 0x4,
Narrow = 0x8,
Katakana = 0x10,
Hiragana = 0x20,
SimplifiedChinese = 0x100,
TraditionalChinese = 0x200,
LinguisticCasing = 0x400,
}
になっています。
ここに、FromUnicode, Unicode を追加して、VbStrConvEx 列挙体を作成します。
[Flags]
public enum VbStrConvEx
{
UpperCase = 0x01,
LowerCase = 0x02,
ProperCase = 0x03,
Wide = 0x04,
Narrow = 0x08,
Katakana = 0x10,
Hiragana = 0x20,
Unicode = 0x40,
FromUnicode = 0x80,
SimplifiedChinese = 0x100,
TraditionalChinese = 0x200,
LinguisticCasing = 0x400,
}
実際の変換は、StrConv メソッドを使います。
文字が シフトJIS に変換できるかどうかは一文字ずつでよいのですが、Wide 変換は、「プ」→「プ」になる等、単純に一文字ずつというわけにはいきません。
文字列をブロック単位で処理することになります。
private static Encoding encShiftJis = Encoding.GetEncoding("Shift_JIS");
public static VBString StrConvEx(VBString value, VbStrConvEx Conversion)
{
if ((object)value == null) return string.Empty;
if (value.LengthB == 0) return string.Empty;
// vbUnicode は先に変換する
if ((Conversion & VbStrConvEx.Unicode) == VbStrConvEx.Unicode)
{
value = encShiftJis.GetString(value.ToByteArray());
Conversion = Conversion & ~VbStrConvEx.Unicode;
}
// vbFromUnicode は後で変換するので、フラグとして保存する
bool fromUnicode = (Conversion & VbStrConvEx.FromUnicode) == VbStrConvEx.FromUnicode;
Conversion = Conversion & ~VbStrConvEx.FromUnicode;
// シフト JIS に変換可能な部分は変換
// それ以外の文字は無変換とする
VbStrConv newConversion = (VbStrConv)Conversion;
StringBuilder resultBuffer = new StringBuilder();
StringBuilder shiftJisBuffer = new StringBuilder();
string stringValue = value.ToString();
bool state = false;
foreach (char c in stringValue)
{
bool currentState = c.IsShiftJis();
// 前の文字と違う場合
if (currentState != state)
{
// シフトJIS 文字の変換を行う
if (shiftJisBuffer.Length > 0)
{
resultBuffer.Append(VBStrConv(shiftJisBuffer.ToString(), newConversion));
shiftJisBuffer.Length = 0;
}
state = currentState;
}
if (currentState)
// シフトJIS なら変換用バッファに積む
shiftJisBuffer.Append(c);
else
// その他の文字は無変換
resultBuffer.Append(c);
}
// 最後のバッファを変換
if (shiftJisBuffer.Length > 0)
{
resultBuffer.Append(VBStrConv(shiftJisBuffer.ToString(), newConversion));
}
// シフト JIS に変換
if (fromUnicode)
return encShiftJis.GetBytes(resultBuffer.ToString());
else
return resultBuffer.ToString();
}
// Microsoft.VisualBasic.Strings.StrConv を呼び出す
private static string VBStrConv(string value, VbStrConv Conversion)
{
return Microsoft.VisualBasic.Strings.StrConv(value, Conversion);
}
StrConv のソースを見ると、LCMapStringA を呼び出しているので、LCMapStringW を呼び出すと良い感じですが、実装が面倒そうなので、暇ができたら実装したいと思います。