What is the highlighting behavior when double-clicking on a text area or text field?

I noticed that many applications that expect you to do a lot of text editing will provide non-standard behavior for double-clicking the text, because the application highlights the text that, in its opinion, you are most likely trying to interact with.

As a quick example, this sentence behaves differently in different applications:

This is an "approximate" sentence.

If I print this in Notepad and double-click on the word β€œsample” (ideally in the middle of the word, say, between the β€œm” and β€œp” of the sample), then the notebook extracts from the first quote in the sample after the second quote inclusive. If this sentence is in a comment in Visual Studio, and I double-click in the same place, it stands out from the β€œs” to β€œe” of the sample without quotation marks.

How can I customize these highlighting behaviors in my application? Is it different from winforms to WPF? I suppose I could hack my way to work on the double-click event, but is there a more elegant / intentional solution designed solely for this?

+6
source share
3 answers

Yes, using the DoubleClick event to do what you need is kludgy, as it seems to make a choice twice, which is slower, looks worse and can cause unwanted events / code.

So, the code below should do the trick for Winforms at least. Create a new class and extend the TextBox (or RichTextBox) in the usual way (using a newly created control that should magically appear in the designer). I made a simple procedure in which you can specify the separator to use. With a bit of work, it should be easy to account for a range of characters, not just one, or even create other more advanced ways of choosing.

If you use a TextBox instead of a RichTextBox, simply remove the β€œRich” bit that appears twice in the class definition.

class RichTextBoxX : RichTextBox { char delimiter = ','; // Specify what character to use for start and end of selection protected override void WndProc(ref System.Windows.Forms.Message m) { if (m.Msg==0x0203) // WM_LBUTTONDBLCLK { // Perfect situation for off-by-one bugs! Checked thoroughly for at least 10 mins, so should be okay now: int start = this.SelectionStart; if (start < 1) start = 1; int left = this.Text.LastIndexOf(delimiter, start - 1); int right = this.Text.IndexOf(delimiter, start); if (right == -1) right = Text.Length; this.SelectionStart = left + 1; this.SelectionLength = right - left - 1; return; } base.WndProc(ref m); } } 
+2
source

The improved answer from DarkPh03n1X worked almost for me, however it has an unpleasant error: if no separator character is found , Text.IndexOf(c, start) will return -1 , which will set right to -1 , and then if (right == -1) right = Text.Length triggers.

So, now we have chosen to the end of the text, although the expected choice should be shorter. I think the launch is being processed correctly.

I removed if (right == -1) right = Text.Length , but added && pos != -1 . Here is the corrected version:

 class RichTextBoxX : RichTextBox { // implement selection to work with "whole words" on double-click // and without selecting the leading/trailing spaces/blanks/line breaks private char[] delimiterList = new[] { '\n', ',', ' ', '(', ')', '_', '/' }; protected override void WndProc(ref Message m) { if (m.Msg == 0x0203) // WM_LBUTTONDBLCLK { int start = SelectionStart; if (start < 1) start = 1; int left = -1; int right = Text.Length; int pos; foreach (char c in delimiterList) { pos = Text.LastIndexOf(c, start - 1); if (pos > left) left = pos; pos = Text.IndexOf(c, start); if (pos < right && pos != -1) right = pos; } SelectionStart = left + 1; SelectionLength = right - left - 1; return; } base.WndProc(ref m); } } 

To test the behavior, here is an example of the text I used:

 12.34.56.78 (ab1-2-3-4-5.test-1.example.com) Jersey City New Jersey US, United States ASN: Example.com/12345 

I added a few other separators, feel free to choose what you need.

+1
source

Adding DanW to the work, I added a few delimiters that seem to work well.

 class RichTextBoxX : RichTextBox { private char[] delimiterList = new[] { ',', ' '}; protected override void WndProc(ref System.Windows.Forms.Message m) { if (m.Msg == 0x0203) // WM_LBUTTONDBLCLK { int start = this.SelectionStart; if (start < 1) start = 1; int left = -1; int right = Text.Length; foreach (char c in delimiterList) { if (this.Text.LastIndexOf(c, start - 1) > left) { left = this.Text.LastIndexOf(c, start - 1); } if (this.Text.IndexOf(c, start) < right) { right = this.Text.IndexOf(c, start); if (right == -1) right = Text.Length; } } this.SelectionStart = left + 1; this.SelectionLength = right - left - 1; return; } base.WndProc(ref m); } } 

One more thing: to insert the code above into your "code" that you are going to use, now use the "Form Designer" to drag the RichTextBox onto your form, now go to the form designer class in my case form1.desigener.cs and find the line implementations, for example:

 this.richTextBox1 = new System.Windows.Forms.RichTextBox(); 

and replace it with

 this.richTextBox1 = new project.form1.RichTextBoxX(); 

After that, this control will work like a regular RichTextBox implementation using the optional override function

0
source

Source: https://habr.com/ru/post/891566/


All Articles