C# 解決文字方塊輸入surrogate 字元(如 CJK 擴充字集字元長度為 2 的漢字)的問題
因為 textBox 的 TextChanged 事件,會引發2次 KeyDown事件,故字元長度為2的字在程式碼執行中其實會「輸入」2次。如何正確判斷字元長度 2的 surrogate字元已完全輸入完畢呢?以下是末學的解決方法。
在C# 中,只有在 TextChanged事件有此問題,若是比對或操作已經輸入完成的字元,則surrogate字元並不會造成任何障礙。也就是說如 IndexOf() 的方法,不論是在surrogate字元或非surrogate字元的操作,都不會造成問題,唯獨在TextChanged事件中判斷時會有所影響。此問題應該係 TextChanged事件尚未跟上surrogate字元的腳步,猶如目前在MS Access作篩選與查詢的判斷時,一樣會出錯。
int surrogate = 0;
bool isKeyDownSurrogate(string x)
{/*解決輸入CJK字元長度為2的字串問題 https://docs.microsoft.com/en-us/previous-versions/windows/desktop/indexsrv/surrogate-pairs
*
https://stackoverflow.com/questions/50180815/is-string-replacestring-string-unicode-safe-in-regards-to-surrogate-pairs */
UnicodeCategory category = UnicodeCategory.Surrogate;//https://docs.microsoft.com/zh-tw/dotnet/api/system.globalization.unicodecategory?view=net-6.0
char[] xChar = x.ToArray();
foreach (char item in xChar)
{
//if (CharUnicodeInfo.GetUnicodeCategory(item) == category)
if (Char.IsSurrogate(item))
{
surrogate++;
}
}
if (surrogate % 2 != 0) { surrogate = 0; return true; }
else { surrogate = 0; return false; }
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
string x = textBox2.Text, x1 = textBox1.Text;
if (x == "" || x1 == "") return;
if (isKeyDownSurrogate(x)) return;//surrogate字在文字方塊輸入時會引發2次keyDown事件
var sa = findWord(x, x1);
if (sa == null) return;
int s = sa[0], nextS = sa[1];
if (s > -1)
{
textBox1.Select(s, x.Length);
textBox1.ScrollToCaret();
if (nextS > -1) { textBox2.BackColor = Color.Yellow; doNotLeaveTextBox2 = false; return; }
}
else
{
textBox2.BackColor = Color.Red;
doNotLeaveTextBox2 = false; return;
}
textBox2.BackColor = Color.GreenYellow;
SystemSounds.Hand.Play();//文本唯一提示
doNotLeaveTextBox2 = true;
textBox2.SelectAll();
}
int[] findWord(string x, string x1)
{
if (x == "" || x1 == "") return null;
int s, nextS;
s = x1.IndexOf(x);
nextS = x1.IndexOf(x, s + x.Length);
return new int[] { s, nextS };
}
留言