C# 文本框拼写检查器检查所有大写单词
C# Texbox Spell Checker Check All Caps Words
使用 WPF 中的文本框拼写检查,它似乎不检查大写单词的拼写。我知道这是为首字母缩略词等设计的,因此它不会将所有这些都标记为拼写错误并且它对此很有用。然而,在我的行业(建筑和工程)中,有许多公司使用所有大写字母来写他们的笔记,所以基本上使拼写检查变得无用......
有什么方法可以改变拼写检查器使其不忽略大写单词吗?
您可以简单地 toLowerCase()
之前的字符串 运行 通过拼写检查器。
好的,所以我终于有时间再试一次,并根据 Tom 的回答想出了一个方法(尽管它并不像那样简单)。我会警告你这绝对是一个黑客......但对于其他为此苦苦挣扎的人来说,它似乎有效。基本上逻辑是这样的:
- 创建一个从不显示的 'shadow' 文本框并将其文本设置为主文本框的小写版本并启用拼写检查。
- 根据代码在阴影文本框中搜索拼写错误,并获取框中任何拼写错误的起始位置和长度。
- 查找找到的字符索引与主文本框的相对位置。
- 使用装饰层为任何拼写错误的单词添加红色下划线。
- 每当文本更改或框的大小更改时,更新文本并重新运行以上内容。
我有点担心性能,但我的应用程序中有相当多的文本框,而且在使用它时我没有注意到任何减速。这是代码:
在文本框中加载处理程序:
//Create a shadow textbox to run spell check in - set text to the lower version of main text
TextBox tbSpell = new TextBox();
tbSpell.Text = tb.Text.ToLower();
//Enable spelling on the shadow box if we have spell checking enabled
tbSpell.SpellCheck.IsEnabled = tb.DataContext is KeynoteVM && (tb.DataContext as KeynoteVM).EnableSpelling;
//Set the shadow as a tag to the main textbox so we have access to it directly
tb.Tag = tbSpell;
//Adde handlers for size change or text change as we may need to update adorners
tb.SizeChanged += tb_SizeChanged;
tb.TextChanged += tb_TextChanged;
大小和文本更改处理程序只需调用如下所示的更新方法:
//Remove existing adorners
AdornerLayer lyr = AdornerLayer.GetAdornerLayer(tb);
if (lyr != null)
{
Adorner[] ads = lyr.GetAdorners(tb);
if (ads != null)
{
foreach (Adorner ad in lyr.GetAdorners(tb))
{ lyr.Remove(ad); }
}
}
//Get the shadow textbox from the tag property
TextBox tbSpell = tb.Tag as TextBox;
if (tbSpell == null || !tbSpell.SpellCheck.IsEnabled)
{ return; }
//Make sure we have the latest text
tbSpell.Text = tb.Text.ToLower();
//Loop to get all spelling errors starting at index 0
int indx = 0;
while (true)
{
//Find the spelling error
indx = tbSpell.GetNextSpellingErrorCharacterIndex(indx, LogicalDirection.Forward);
if (indx > -1)
{
//Have a match, get the length of the error word
int len = tbSpell.GetSpellingErrorLength(indx);
//Get a rectangle describing the position of the error to use for drawing the underline
Rect r = tb.GetRectFromCharacterIndex(indx);
Rect rEnd = tb.GetRectFromCharacterIndex(indx + len);
//Modify the rectangle width to the width of the word
r.Width = rEnd.Right - r.Right;
//Create an adorner for the word and set the 'draw location' property to the rectangle
AdornerSpell ad = new AdornerSpell(tb);
ad.drawLocation = r;
//Add the adorner to the textbox
AdornerLayer.GetAdornerLayer(tb).Add(ad);
//Increment the index to move past this word
indx += len;
}
else
{ break; }
}
这是我创建的装饰器 class 的代码(它只是用红色下划线):
public class AdornerSpell : Adorner
{
public Rect drawLocation { get; set; }
public AdornerSpell(UIElement adornedElement) : base(adornedElement) { }
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
drawingContext.DrawLine(new System.Windows.Media.Pen(new SolidColorBrush(Colors.Red), 1), drawLocation.BottomLeft, drawLocation.BottomRight);
}
}
当然,如果您使用右键单击获取建议,则必须修改它以从阴影文本框而不是常规文本框获取建议。
我发现的唯一问题是,由于它总是检查小写字母,因此它会识别像 I've 和 I'll 这样的拼写错误,因为 I 应该大写。我敢肯定也有办法解决这个问题,但我还没有尝试过。
无论如何,它不是很确定,但它似乎有效,如果不完全创建一个新的拼写检查系统,我找不到更好的东西......如果有人有其他建议,我仍然愿意接受,但这个至少是可行的。
编辑:
意识到我实际上可以通过告诉它在调度程序上使用 'BeginInvoke' 更新为异步 运行 来进一步降低性能影响。现在文本更改和大小更改方法如下所示:
Dispatcher.BeginInvoke(new Action(() => UpdateSpellingAdorners(sender as TextBox)));
使用 WPF 中的文本框拼写检查,它似乎不检查大写单词的拼写。我知道这是为首字母缩略词等设计的,因此它不会将所有这些都标记为拼写错误并且它对此很有用。然而,在我的行业(建筑和工程)中,有许多公司使用所有大写字母来写他们的笔记,所以基本上使拼写检查变得无用......
有什么方法可以改变拼写检查器使其不忽略大写单词吗?
您可以简单地 toLowerCase()
之前的字符串 运行 通过拼写检查器。
好的,所以我终于有时间再试一次,并根据 Tom 的回答想出了一个方法(尽管它并不像那样简单)。我会警告你这绝对是一个黑客......但对于其他为此苦苦挣扎的人来说,它似乎有效。基本上逻辑是这样的:
- 创建一个从不显示的 'shadow' 文本框并将其文本设置为主文本框的小写版本并启用拼写检查。
- 根据代码在阴影文本框中搜索拼写错误,并获取框中任何拼写错误的起始位置和长度。
- 查找找到的字符索引与主文本框的相对位置。
- 使用装饰层为任何拼写错误的单词添加红色下划线。
- 每当文本更改或框的大小更改时,更新文本并重新运行以上内容。
我有点担心性能,但我的应用程序中有相当多的文本框,而且在使用它时我没有注意到任何减速。这是代码:
在文本框中加载处理程序:
//Create a shadow textbox to run spell check in - set text to the lower version of main text
TextBox tbSpell = new TextBox();
tbSpell.Text = tb.Text.ToLower();
//Enable spelling on the shadow box if we have spell checking enabled
tbSpell.SpellCheck.IsEnabled = tb.DataContext is KeynoteVM && (tb.DataContext as KeynoteVM).EnableSpelling;
//Set the shadow as a tag to the main textbox so we have access to it directly
tb.Tag = tbSpell;
//Adde handlers for size change or text change as we may need to update adorners
tb.SizeChanged += tb_SizeChanged;
tb.TextChanged += tb_TextChanged;
大小和文本更改处理程序只需调用如下所示的更新方法:
//Remove existing adorners
AdornerLayer lyr = AdornerLayer.GetAdornerLayer(tb);
if (lyr != null)
{
Adorner[] ads = lyr.GetAdorners(tb);
if (ads != null)
{
foreach (Adorner ad in lyr.GetAdorners(tb))
{ lyr.Remove(ad); }
}
}
//Get the shadow textbox from the tag property
TextBox tbSpell = tb.Tag as TextBox;
if (tbSpell == null || !tbSpell.SpellCheck.IsEnabled)
{ return; }
//Make sure we have the latest text
tbSpell.Text = tb.Text.ToLower();
//Loop to get all spelling errors starting at index 0
int indx = 0;
while (true)
{
//Find the spelling error
indx = tbSpell.GetNextSpellingErrorCharacterIndex(indx, LogicalDirection.Forward);
if (indx > -1)
{
//Have a match, get the length of the error word
int len = tbSpell.GetSpellingErrorLength(indx);
//Get a rectangle describing the position of the error to use for drawing the underline
Rect r = tb.GetRectFromCharacterIndex(indx);
Rect rEnd = tb.GetRectFromCharacterIndex(indx + len);
//Modify the rectangle width to the width of the word
r.Width = rEnd.Right - r.Right;
//Create an adorner for the word and set the 'draw location' property to the rectangle
AdornerSpell ad = new AdornerSpell(tb);
ad.drawLocation = r;
//Add the adorner to the textbox
AdornerLayer.GetAdornerLayer(tb).Add(ad);
//Increment the index to move past this word
indx += len;
}
else
{ break; }
}
这是我创建的装饰器 class 的代码(它只是用红色下划线):
public class AdornerSpell : Adorner
{
public Rect drawLocation { get; set; }
public AdornerSpell(UIElement adornedElement) : base(adornedElement) { }
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
drawingContext.DrawLine(new System.Windows.Media.Pen(new SolidColorBrush(Colors.Red), 1), drawLocation.BottomLeft, drawLocation.BottomRight);
}
}
当然,如果您使用右键单击获取建议,则必须修改它以从阴影文本框而不是常规文本框获取建议。
我发现的唯一问题是,由于它总是检查小写字母,因此它会识别像 I've 和 I'll 这样的拼写错误,因为 I 应该大写。我敢肯定也有办法解决这个问题,但我还没有尝试过。
无论如何,它不是很确定,但它似乎有效,如果不完全创建一个新的拼写检查系统,我找不到更好的东西......如果有人有其他建议,我仍然愿意接受,但这个至少是可行的。
编辑:
意识到我实际上可以通过告诉它在调度程序上使用 'BeginInvoke' 更新为异步 运行 来进一步降低性能影响。现在文本更改和大小更改方法如下所示:
Dispatcher.BeginInvoke(new Action(() => UpdateSpellingAdorners(sender as TextBox)));