AutoCorrect in WPF Richtextbox - c#

I read on MSDN that .NET 4.6.1 supports auto correct now.
The files in %appdata%/Microsoft/Spelling// were created automatically and I added the following line to the default.acl (file is still UTF-16 with BOM):
tramampoline|trampoline
I have set the project to target 4.6.1 and enabled SpellCheck on a RichTextBox:
<RichTextBox SpellCheck.IsEnabled="True" Language="de-DE"/>
While it highlights the word when typed wrong in the usual manner, there is no autocorrection happening.
What am I missing here?
I don't quite understand the note:
Note: These new file-formats are not directly supported by the WPF spell checking API’s, and the custom dictionaries supplied to WPF in applications should continue to use .lex files.

I know this is old, but as far as I know you need to handle AutoCorrect on your own (if I'm wrong please correct me with an example). You can do this as follows:
var caretPosition = richTextBox.CaretPosition;
// Make sure you're passing a textpointer at the end of the word you want to correct, i.e. not like this ;)
errorPosition = richTextBox.GetNextSpellingErrorPosition(caretPosition, LogicalDirection.Backward);
if(errorPosition == null)
{
return;
}
var errors = richTextBox.GetSpellingError(errorPosition);
// Default would be to only replace the text if there is one available replacement
// but you can also measure which one is most likely with a simple string comparison
// algorithm, e.g. Levenshtein distance
if (errors.Suggestions.Count() == 1)
{
var incorrectTextRange = richTextBox.GetSpellingErrorRange(errorPosition);
var correctText = error.Suggestions.First();
var incorrectText = incorrectTextRange.Text;
// Correct the text with the chosen word...
errors.Correct(correctText);
}
// Set caret position...
An important note would be not to use the RTB's CaretPosition, but rather to use a textpointer at the end of the word you wish to correct. If your textpointer/caret is in a weird spot (e.g. the end of 20 whitespaces), the GetNextSpellingErrorPosition method may take up to 60 seconds before it returns (depending on the hardware/number of words in your RTB).

Related

How do I set a property to the last typed symbol in richtextbox in wpf?

I want to set some background or foreground properties to the latest symbol in RichTextBox.
I tried getting the latest textrange by saving the caret position before the input and then getting the textrange like that: new TextRange(previousCaret, currentCaret).
However this is a bug-prone decision, because you can actually get 2 or more last symbols in case if the caret position wasn't updated in time (for example, you are typing very quickly and pressing the buttons at the same time)
Now, maybe I don't even have to get the latest symbol's TextRange? Are there other ways, like some built-in methods?
So, how do I change the latest symbol's properties properly?
To get the latest TextRange, simply use this code:
private TextRange LatestSymbol
{
get
{
var previous = InputString.CaretPosition.GetPositionAtOffset(-1);
if (previous != null)
{
return new TextRange(
previous,
InputString.CaretPosition
);
}
return null;
}
}
}
The thing here is, that CaretPosition.GetPositionAtOffset(-1) returns the position that is 1 symbol behind the currentPosition.
And this works well and without any bugs.

Find a range of text with specific formatting with Word interop

I have a MS Word add-in that needs to extract text from a range of text based solely on its formatting: in my case in particular, if the text is underlined or struck through, the range of characters/words that are underlined or struck through need to be found so that I can keep track of them.
My first idea was to use Range.Find, as is outlined here, but that won't work when I have no idea what the string is that I'm looking for:
var rng = doc.Range(someStartRange, someEndRange);
rng.Find.Forward = true;
rng.Find.Format = true;
// I removed this line in favor of putting it inside Execute()
//rng.Find.Text = "";
rng.Find.Font.Underline = WdUnderline.wdUnderlineSingle;
// this works
rng.Find.Execute("");
int foundNumber = 0;
while (rng.Find.Found)
{
foundNumber++;
// this needed to be added as well, as per the link above
rng.Find.Execute("");
}
MessageBox.Show("Underlined strings found: " + foundNumber.ToString());
I would happily parse the text myself, but am not sure how to do this while still knowing the formatting. Thanks in advance for any ideas.
EDIT:
I changed my code to fix the find underline issue, and with that change the while loop never terminates. More specifically, rng.Find.Found finds the underlined text, but it finds the same text over and over, and never terminates.
EDIT 2:
Once I added the additional Execute() call inside the while loop, the find functioned as needed.
You need
rng.Find.Font.Underline = wdUnderline.wdUnderlineSingle;
(At the moment you are setting the formatting for the specified rng, rather than the formatting for the Find)

C# window application get word from the cursor position from the other application

I have C# window application and I want to get text where the cursor is currently located or text is selected from the other application like notepad, notepad++ or any browser etc.
Did you already have a look at this CodeProject article ? This could be a start even if this is not exactly what you are looking for.
See http://msdn.microsoft.com/en-us/library/windows/desktop/ms632604(v=vs.85).aspx.
If it do not solve your issue, have a look at http://msdn.microsoft.com/en-us/library/system.windows.automation.textpattern.getselection(v=vs.110).aspx, as suggested in the comments.
Getting the text under the cursor (or from the caret) requires UI Automation and TextPattern support from the application. The problem is that not all applications support this, and the older the application, the less likely it is to have TextPattern support.
Getting selected text is, ironically enough, somewhat easier, although still not 100%. I outlined a solution in this answer. It does involve managing focus and manipulating the clipboard for the most general solution, and it is by no means perfect.
Another option, that involves a ton of work, is to use a mirror driver to capture the screen contents, and then use other technologies (OCR, etc.) to capture the text. I don't really recommend this; it's not supported in Windows 8 and above, but if you absolutely have to have 100% support across applications with the least impact, then it's a possibility. It's a lot of work, though. Definitely not for the squeamish.
This is possible using Accessibility technologies (like screen readers). However, it will require a great deal of troubleshooting:
The answer about MSAA on the following question is where you will need to start.
Best way to get the 'word before the cursor' in any open app's text field
Also, the following question is helpful about implementing it:
How to get the word under the cursor in Windows?
The problem is that you are trying to get data from another application. Unless that application supports a way to provide this to you it will be very difficult.
It would be much easier if the info could be retrieved from within the application, like from within a textbox or rich text control on a form
You can use clipborad to copy or get that text and then transfer it to your desired window.
You can use SendKeys class to demonstrate the keyboard.
For example you can use SendKeys.Send("^C") in your program and then a code to focus on Notepad++ and then SendKeys.Send("^V").
SendKeys.Send("^C");
// code to change active window and focus on Notepad++.
SendKeys.Send("^V");
Thanks for help me.
Still I'm not able to get the text from the caret position. So finally I get the all the text from the active window and fetch my text using Regex.
private string SelectText(IntPtr hWnd)
{
string text = string.Empty;
Regex regex = new Regex(#"(\d{3}-\w{5,8})");
if (InputSimulator.IsKeyDown(VirtualKeyCode.SHIFT))
{
InputSimulator.SimulateKeyUp(VirtualKeyCode.SHIFT);
}
if (InputSimulator.IsKeyDown(VirtualKeyCode.MENU))
{
InputSimulator.SimulateKeyUp(VirtualKeyCode.MENU);
}
InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);
text = Clipboard.GetText();
if (!string.IsNullOrEmpty(text) && regex.IsMatch(text))
{
Thread.Sleep(100);
text.Trim();
string[] textArr = text.Split(' ');
text = textArr[textArr.Length - 1];
}
else
{
InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.VK_A);
InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);
ClickOnPoint();
Thread.Sleep(100);
text = Clipboard.GetText();
MatchCollection matchCollection = regex.Matches(text);
if (matchCollection.Count > 0)
{
text = matchCollection[0].Value;
}
else
{
text = string.Empty;
}
}
Clipboard.Clear();
return text;
}

Is there a free tool/plugin that can format code ect on the fly for VS C#?

Ive just moved from VB.Net to C#. I dont understand why people are using it/prefer it as it is soo much more time consuming!
In VB.NET, you simply type your code and VB.NET formats is as you go, For example:
removes unneccessary whitespace,
automatically puts in brackets,
tabs blocks of code,
automatically creates the NEXT, END IF, statements for blocks.
and the opposite/nuiances in C#
if you change the name of an event handler it creates a new one, doesnt rename the existing one
you must have the () at the end of a method
and im sure theres more.
Why is C# backwards like this? Surely there must be a way to improve productivity somehow. Any ideas or free tools out there?
This has nothing to do with the language, and everything to do with the editor.
Regardless, the editor for C# in visual studio does support automatic formatting in several ways.
If you delete and reinsert the closing brace }, it will reformat/reindent automatically.
There are several menu items and corresponding keyboard shortcuts that will reformat code for you:
Ctrl+k+d - this will reformat the whole document.
Ctrl+k+f - this will reformat the selection.
There are also extensive refactoring capabilities - the rename refactoring will rename a member everywhere it is mentioned, even if it is in other projects.
Not automatic BUT.....
Use
Ctrl+K+Ctrl+D
to format document keystroke
Use
Ctrl+K+Ctrl+F
to format selection keystroke
From Visual Studio Format entire file?
I'm using C# in Visual Studio 2008 and it behaves exactly as you describe. Pretty much every time I type a semi-colon or curly brace, it corrects all formatting within the context.
For example...
if (myValue!= null) {
someValue = myValue;
If I type the closing curly brace, it turns into this:
if (myValue != null)
{
someValue = myValue;
}
All dependent on the style settings in Tools > Options
Also there exits some so called code snippets. If you simply type if and press tab tab this will automatically result into
if (true)
{
}
setting the cursor directly onto the true.
Even better is the switch snippet. If you enter switch and press the tab twice you'll get
switch (switch_on)
{
default:
}
where your cursor stands on switch_on.
If you now enter something meaningful like a variable name that holds an enum value (e.g. var color = Color.Red;) and press Enter it will automatically fill in all possible cases.
There are more code snippets available and some are very handy like foreach, try, prop, propg.

What's a good way to perform hit testing on a FormattedText?

I'm rendering text using FormattedText, but there does appear to be any way to perform per-char hit testing on the rendered output. It's read-only, so I basically only need selection, no editing.
I'd use RichTextBox or similar, but I need to output text based on control codes embed in the text itself, so they don't always nest, which makes building the right Inline elements very complex. I'm also a bit worried about performance with that solution; I have a large number of lines, and new lines are appended often.
I've looked at GlyphRun, it appears I could get hit-testing from it or a related class, but I'd be reimplementing a lot of functionality, and it seems like there should be a simpler way...
Does anyone know of a good way to implement this?
You can get the geometry of each character from a FormattedText object and use the bounds of each character to do your hit testing.
var geometry = (GeometryGroup)((GeometryGroup)text.BuildGeometry(new Point(0, 0))).Children[0];
foreach (var c in geometry.Children)
{
if (c.Bounds.Contains(point))
return index;
index++;
}
In OnRender you can render these geometry objects instead of the formatted text.
The best way is to design a good data structure for storing your text and which also considers hit-testing. One example could be to split the text into blocks (words, lines or paragraphs depending on what you need). Then each such block should have a bounding-box which should be recomputed in any formatting operations. Also consider caret positions in your design.
Once you have such facility it becomes very easy to do hit-testing, just use the bounding boxes. It will also help in subsequent operations like highlighting a particular portion of text.
Completely agree with Sesh - the easiest way you're going to get away with not re-implementing a whole load of FormattedText functionality is going to be by splitting up the individual items you want to hit-test into their own controls/inlines.
Consider using a TextBlock and adding each word as it's own Inline ( or ), then either bind to the inline's IsMouseDirectlyOver property, our add delegates to the MouseEnter & MouseLeave events.
If you want to do pixel-level hit testing of the actual glyphs (i.e. is the mouse exactly in the dot of this 'i'), then you'll need to use GlyphRuns and do manual hit testing on the glyphs (read: hard work).
I'm very late to the party--if the party is not over, and you don't need the actual character geometry, I found something like this useful:
for (int i = 0; i < FormattedText.Text.Length; i++)
{
characterHighlightGeometry = FormattedText.BuildHighlightGeometry(new Point(), i, 1);
CharacterHighlightGeometries.Children.Add(characterHighlightGeometry);
}
BuildGeometry() only includes the actual path geometry of a character. BuildHighlightGeometry() generates the outer bounds of all characters--including
spaces, so an index to a space can be located by:
foreach (var c in CharacterHighlightGeometries.Children)
{
if (c.Bounds.Contains(centerpoint))
{
q = c;
cpos = index;
break;
}
index++;
}
Hope this helps.

Categories

Resources