RichTextBox doesn't update caret position correctly - winforms

I have a handler consuming the keyDown event of a WinForms RTB, that has the following code:
GetTextAtLoc(RTB->SelectionStart); // selects some text at the caret's position
RTB->SelectedText = "SomeOfMyOwn";
GetTextAtLoc(RTB->SelectionStart); // selects the replacement string
RTB->SelectionStart += RTB->SelectionLength - 1;
While this code seems to do its job (SelectionStart/Length properties are updated correctly), the caret doesn't move to the end of the new string - It says right where it was at the time of GetTextAtLoc's first call. Redrawing the textbox doesn't seem to have any effect either.

The problem seems to have fixed itself. Dunno what brought about the change, unfortunately. Closing this thread.

You did not specify the new length (and is therefor: 1-1=0). Try something like:
SelectionStart += (length("SomeOfMyOwn"))

Related

Changing Many Null Textboxes to 0 in Access

I have a problem with changing all textboxes in a form with Null to a Value 0.0 after Lost Focus. Specifically, if the textbox is blank after pressing tab it would revert back to 0 since it affects calculations in the other part of the form. Writing the code for every textbox event procedure (57 or so boxes) seems tedious and the names for all the boxes are different.
I was wondering if there was an efficient way to go about changing the textbox value after losing focus easily rather than changing the event procedure for every textbox in the form.
Thanks
Figured I would give an example along with my comments. You could use something along these lines:
Public Function DefaultToZero(frm As Form)
Dim ctrl As Access.Control
For Each ctrl In frm
If ctrl.Tag = "Default" Then
If Nz(ctrl.Value, "") = "" Then
ctrl.Value= "0.0"
End If
End If
Next ctrl
End Function
Then you just select all controls while in design mode and set the tag to 'Default'. Not the best answer but I don't really see any other options besides using each "Lost Focus" event.

Clear SelectionBackColor from text in RichTextBox [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
RichTextBox syntax highlighting in real time--Disabling the repaint
I'm using a RichTextBox control to find and change the SelectionBackColor property of some words. The words are not fixed so basically the text that has different BackColor varies.
I've already tried two methods of clearing the BackColor from the previous text before applying it to the new words:
Selecting all the text and setting the SelectionBackColor to the Controls BackColor.
Saving the text to string then putting it back to RichTextBox to clear it's formatting.
Although both methods work an issue arises when you have a lot of text in the control. For the first method, it becomes clearer that all text gets selected (you can notice it for a few milliseconds), which becomes annoying since this happens in the TextChanges event, so basically every letter that gets removed/added triggers this. As for the second method, it's not that obvious as the first, but since the text is removed and then insert back, the scrolling becomes a bit odd since even after using .ScrollToCaret() the scrollbar isn't exactly were it was before the SelectionBackColor clearing.
It feels like there should be a better way of clearing the existing SelectionBackColor without all these issues. Especially in this case since it has to do the cleaning in the TextChanged event.
Waiting for your thoughts. Thanks in advance.
Edit: You can see below the method I'm using for the first example I mentioned above (selecting all).
private void ClearSelection(RichTextBox rtb)
{
if (rtb.Text.Length > 0)
{
int currentIndex = rtb.SelectionStart;
rtb.SelectAll();
rtb.SelectionBackColor = Color.White;
rtb.SelectionLength = 0;
rtb.SelectionStart = currentIndex;
}
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
if (!_working)
{
ClearSelection(richTextBox1);
}
}
The _working bool is just to make sure that the method doesn't get trigged when the program is changing the colour of certain words so that it will only be trigged when it's the user changing the text.
Edit2: For those interested, the solution at Reset RTF in RichTextBox? seems to do the trick. I would avoid the one that was voted as duplicate (for some odd reason) since it produces more graphical issues.
Have you tried using double buffering? Maybe something like:
richTextBox1.SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer,true);

How to detect styling applied to DataGridView via e.CellStyle.BackColor in the CellFormatting event?

If we've applied styling (e.CellStyle.BackColor say) to some rows via the CellFormatting event of a DataGridView, is it then possible to detect that styling at a later stage?
For example, currently we use a generic bloc of code to handle printing and exporting to Excel for any and all our DataGridViews. Until now the code hasn't catered for any styling.
So we want to add it in.
If we check the .DefaultCellStyle of the row or cell then our styling doesn't show up (it just shows as 0 or Black, which is completely wrong).
I assume that's because we've applied the styling via a CellFormatting event, instead of embedding it into the DefaultCellStyle.
Unfortunately I could not find a complete solution to your issue, only a work around.
Some experimenting with the CellFormatting event using the example from MSDN resulted in me seeing exactly what you were seeing - the BackColor was clearly being set but the CellStyle was not reflecting that. 1
The work around I found was to not use the DataGridViewCellFormattingEventArgs CellStyle property but to instead go straight to the grid. This has the downside that you now need to manually handle the case where you do not want to format the cell.
I've got some code below showing this - it is again just modifying the MSDN code:
void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
// If the column is the Artist column, check the
// value.
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "Artist")
{
if (e.Value != null)
{
// Check for the string "pink" in the cell.
string stringValue = (string)e.Value;
stringValue = stringValue.ToLower();
if ((stringValue.IndexOf("pink") > -1))
{
// With the commented line below we cannot access the new style
//e.CellStyle.BackColor = Color.Pink;
// With this line we can!
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BackColor = Color.Pink;
}
else
{
// With the original MSDN code the else block to reset the
// cell style was not needed.
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BackColor = dataGridView1.DefaultCellStyle.BackColor;
}
}
}
}
1. My theory is that this is similar to the confusion people have over the .Refresh() method, where the DataGridView has two very distinct views of itself, one being the rectangle painted on screen and the other being the underlying data. With the .Refresh() method you only repaint the rectangle, you do not refresh the data. I think this is like that - the CellFormatting event only formats during painting and doesn't do anything to the grid styles themselves.
A possible solution would be to add a second handler to the generic printing block of code (just before the actual printing). This handler should be attached to the CellFormatting event and only save the e.cellstyle in a temporary storage (such as a dictionary of cellstyles).
All cellstyles applied during your original cellformatting will be readable in your generic printing code without the need of adjusting specific cellformatting-events that have been tied to the datagridview.
At the end of the printing you can remove the handler again.
See also Is there a way to force a DataGridView to fire its CellFormatting event for all cells?

How to use a TextBlock that allows the left-most characters to be dropped

I have the following scenario which I thought would have a simple solution, but I'm stumped...
I have constructed a WPF user control with a set of numeric Buttons and a TextBlock to record what buttons have been selected. When the user control opens, the TextBlock is empty. As a button is selected, the digit it represents is appended to the right-hand-side of the displayed text.
What I need is a solution where the digits keep getting appended on the right-hand-side and if that results in exceeding the fixed displayable size of the TextBlock dropping the left-most character. In effect I am after a one-character-at-a-time marque effect.
I can not use scroll bars. Any thoughts would be welcome
Databindings are you friend here.
suppose you got a ViewModel. and in the ViewModel you got a property of string which is binded to the TextBlock Text propetry.
Now you only need to manipulate that string inside the ViewModel using regular c# string methods to display correctly.
HTH
Ariel
There's nothing special at the TextBlock level... Just pass it the string that is formatted correctly using something like string.SubString.
UPDATE: This code should do the trick:
const int maxLength = 8;
string value = "sdfdfdfsdffdsfsdf";
if (value.Length > maxLength)
value = value.Substring(value.Length - maxLength);

WPF TextBox - programatically select text while preserving "selection direction"

When editing text the user is able to use the keybord shift button and direction keys to modify the selection - one position stays anchored while the other moves. By pressing left it is possible to get the movable part on the left of the anchored part.
I'm trying to dinamicaly modify the users selection in WPF's TextBox (for the purpose of the discussion, lets say I want to select the characters in pairs, eg. when pressing shift+left, 2 characters would get selected, not just one). However, when using SelectionStart/SelectionIndex/CaretIndex/Select the "movebale end" of the selection is always ends up on the far right end of the selection, rendering the shift+left combination useless.
Any way to preserve the "selection direction"?
This is not quite the answer you are looking for but it'll work. Invoke the command and do it the way WPF does it.
EditingCommands.SelectLeftByCharacter.Execute(null, textBox1);
None of those work. SelectionLength doesn't allowed to be negative, and CaretIndex is always identical to SelectionStart. This is a design bug in TB, as you cannot achieve a valid state of it even in the protected scope.
The command actually works, but you still cannot determine the selection's direction of the currently analyzed textbox. There's only one solution, which is an ugly workaround: You can write your own observer code by overriding the mouse and keyboard event handlers.
The only possibility I can think of is to set the SelectionStart and then make the SelectionLength negative.
Have you tried setting the CaretIndex property before or after setting SelectionStart/SelectionLength?

Resources