2

I have a C# winform application, that is installed on a Japanese windows 7. Some of the labels are presented with a very wide fonts, causing them to not mach the size of the from.

After some research I was told it might be a half/full width issue. Has it any way to force all strings to be presented as Half width?

For example, this part is not shown correctly:

modelSizeLabel.Text = String.Format("X:{0:0.0},Y:{1:0.0},Z:{2:0.0} [{3}]", 
                (Model.BBox.dx),
                (Model.BBox.dy),
                (Model.BBox.dz - Model.Sink),
                uc.To.ToString() //units enum
                );
Gilad
  • 21
  • 4
  • Show your label code – Phil3992 May 03 '17 at 07:42
  • `String.Normalize(System.Text.NormalizationForm.FormKC)` may solve your issue. Assume that full-width letters is used, it can converted automatically before displaying them to label. – Tetsuya Yamamoto May 03 '17 at 07:53
  • Thanks, should I do it for every sting separately? – Gilad May 03 '17 at 08:03
  • AFAIK there are 2 approaches, one with `Normalize` and another with P/Invoke. Depending what you want to use half-width, you can create a method to use it in general. – Tetsuya Yamamoto May 03 '17 at 08:05
  • It seems very unlikely to me that String.Format() produces full-width characters. It certainly does not on my machine with ja-JP in effect. Much more likely is that the Font you use is getting remapped to another one. One that the user might well prefer. Note that machines don't actually have "Microsoft Sans Serif", consider picking another one. – Hans Passant May 03 '17 at 08:57

1 Answers1

1

Basically there are 2 approaches I know to deal with full-width letters:

1. Using String.Normalize() method

This approach uses standard Unicode normalization forms when converting full-width (zenkaku) to half-width (hankaku):

public static string ToHalfWidth(string fullWidth)
{
    return fullWidth.Normalize(System.Text.NormalizationForm.FormKC);
}

NB: This is considered simplest approach to convert letters, numbers and punctuations covered by ANSI encoding written in Japanese IME, but I still don't know how it impact any kana/kanji letters.

2. Using P/Invoke to call LCMapString method in kernel32.dll

This approach requires calling external DLL resource kernel32.dll with API method LCMapString, with flag defined in LCMapStringEx function (note that some flags are mutually exclusive, implementation credit to rshepp/John Estropia):

// edited from /a/40836235
private const uint LOCALE_SYSTEM_DEFAULT = 0x0800;
private const uint LCMAP_HALFWIDTH = 0x00400000;

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern int LCMapString(uint Locale, uint dwMapFlags, string lpSrcStr, int cchSrc, StringBuilder lpDestStr, int cchDest);

public static string ToHalfWidth(string fullWidth, int size)
{
    StringBuilder sb = new StringBuilder(size);
    LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_HALFWIDTH, fullWidth, -1, sb, sb.Capacity);
    return sb.ToString();
}

Usage example:

// by default Japanese IME automatically convert all vocal letters to respective kana letters, 
// so I used consonants except "n"
Label1.Text = ToHalfWidth("0123456789bcdfghjklmpqrstvwxyz");
Label2.Text = ToHalfWidth("0123456789bcdfghjklmpqrstvwxyz", 256);

PS: You can wrap both methods above in a helper/service class for usage across the same namespace.

Related issues:

Converting zenkaku characters to hankaku and vice-versa in C#

Convert single byte character string (half width) to double byte (full width)

Community
  • 1
  • 1
Tetsuya Yamamoto
  • 24,297
  • 8
  • 39
  • 61
  • Maybe `Normalize(NormalizationForm.FormKC)` and `LCMapString()` work in same way, don't they? – 23W Nov 04 '17 at 21:08
  • Possibly they're working in similar way and concept, there `String.Normalize()` method uses direct access to base .NET library while `LCMapString` uses native Windows API handling. – Tetsuya Yamamoto Nov 05 '17 at 05:47