好吧,使用查找表
" âºâ»â¥â¦â£â â¢ââââââªâ«â¼âºâââ¼Â¶Â§â¬â¨âââââââ²â¼"
解决了我问题的第一部分;在
DataGridView
现在看来是对的。(谢谢,
Reza Aghaei
)
â¢
,
¶
和
§
)我不能在0x00-0x1f范围内同时使用这些字符,也不能支持在其>127范围内包含其中一些字符的编码。
所以,相反,对于可编辑的
TextBox
,我选择将Unicode字符用于
C0 ASCII control codes
.
这种变化纯粹是视觉上的;因为我已经过滤了
文本框
,我最终控制并覆盖了所有的输入方法:键盘输入、通过快捷键的剪贴板和通过上下文菜单的剪贴板。考虑到动态编码交换系统,我直接用自己的系统替换了整个undo/redo系统,并由原始字节数组支持。
在预览和编辑中使用不同的字符可能有点奇怪,但是从模型中可以看到,字符串文件清楚地使用符号–151;_、–戥、–戥、–戥来表示左、右、上、下。如果我也在那里使用控制代码字符,那将丢失。
不过,一个重要的兼容性注意事项是:我最初使用默认的ms sans-serif字体,它似乎可以在我的win10笔记本上使用,但是
它在我的win7电脑上不起作用
,并给出了所有控制代码的替换字符矩形。最后,我不得不把所有的东西
数据表格控件
, the
文本框
,及其上下文菜单)到
卢西达无Unicode
让它工作。
两个功能
FilterText
和
FlattenText
是系统的核心。他们使用这三个侧面数据:
ASCII_CONTROL
是一个
const String
包含ASCII控制代码字符:
"ââââââ
ââââââââââââââââââââââââââ";
_validCharactersLowRange
是一个
Char[]
包含转换为选定文本编码的原始00-1f字节范围。每当编码发生更改时,都会更新它,尽管它似乎总是与unicode字符00-1f对应,所以不确定它是否需要更新。(正如我所说,整个问题或多或少是因为字体没有适合该范围的符号。)
_validCharacters
是另一个
字符[]
其中包含此编码的转换字符范围的其余部分,其中00-1f范围由
ascii_控件
,以获取编辑中实际允许的字符的完整范围。
文本框
.
功能:
过滤器文本
将筛选出要在
文本框
. 这包括用ascii控制代码字符替换00-1f范围。它的设计使得过滤后的文本可以再次通过同一个过滤器,而不会出现任何问题。
注意使用
\r
因为换行符是我正在编辑的文件格式规范的一部分。
/// <summary>
/// Filters illegal characters out of the given text, and converts
/// any characters in the 0x00-0x1F range to control code symbols.
/// Used for filtering file, keyboard and clipboard input.
/// </summary>
/// <param name="text">Input text</param>
/// <returns>Text containing only normal ASCII characters, special > 127 characters of the chosen encoding, or control code characters for the 0x00-0x1F range</returns>
private String FilterText(String text)
{
// Filter out null characters; they're completely illegal.
Char[] inputch = text.Replace(Environment.NewLine, "\r").Where(x => x != '\0').ToArray();
// Make string for easy IndexOf lookup
String validCharsLowRange = new String(_validCharactersLowRange);
for (Int32 i = 0; i < inputch.Length; i++)
{
Char inputChar = inputch[i];
// Ignore line breaks
if (inputChar == '\r')
continue;
// Check for low range characters to replace
Int32 index = validCharsLowRange.IndexOf(inputChar);
if (index == -1)
continue;
inputch[i] = ASCII_CONTROL[index];
}
// Filter out illegal characters
return new String(inputch.Where((x => x == '\r' || this._validCharacters.Contains(x))).ToArray()).Replace("\r", Environment.NewLine);
}
扁平文本
从
文本框
并将其转换为该文本编码中预期的裸字符,这意味着输入已准备好转换回字节或复制到剪贴板,它将用ascii控制代码字符还原00-1f范围的替换。
/// <summary>
/// Convert text from the input textBox to actual chars correpsonding to the chosen encoding.
/// This can be used for converting back to bytes; or for clipboard copy.
/// </summary>
/// <param name="text">Text from the TextBox.</param>
/// <returns>The normalized string.</returns>
private Char[] FlattenText(String text)
{
Char[] preparedOutput = text.Replace(Environment.NewLine, "\r").ToCharArray();
for (Int32 i = 0; i < preparedOutput.Length; i++)
{
Int32 index = ASCII_CONTROL.IndexOf(preparedOutput[i]);
if (index != -1)
preparedOutput[i] = this._validCharactersLowRange[index];
}
return preparedOutput;
}
然后,为了更好地测量,我为
文本框
,因为那些控制代码字符实在是太小了…并添加了一种插入它们的简单方法。
(忽略事实
0x0F
丢失了;这是我后来修复的一个小错误)
不管怎样,谢谢你的帮助;我希望这个错综复杂的混乱能对其他人有用。完整的代码可以找到
here
。可能对其他试图编写处理这些00-1f字符的内容的人有用。(或者,见鬼,有人在编写自己的撤消/重做历史系统;其中有一个相当漂亮的系统。)