How to check if some text in a RichTextBox is selected - vb.net

I am creating a text editor and I want to add copy, paste and cut functions in the Edit Menu. I want these MenuItems to only to be enabled when there's an active selection.
I have a function that searches and highlights but there doesn't seem to be a trigger to check for in order to do it.

The RichTextBox.SelectionChanged event (documentation) fires when the selection of text within the control has changed.
The RichTextBox.SelectionLength property (documentation) will return the number of characters selected in control.
Handle the SelectionChanged event and set the Enabled property of the menu items based on if the SelectionLength is greater than 0:
Private Sub MyRichTextBox_SelectionChanged(sender as Object, e as EventArgs) Handles MyRichTextBox.SelectionChanged
MyMenuItem1.Enabled = MyRichTextBox.SelectionLength > 0
MyMenuItem2.Enabled = MyMenuItem1.Enabled
MyMenuItem3.Enabled = MyMenuItem1.Enabled
End Sub

Related

Use a virtual Keyboard on focused Textboxes and DataGridView Cells

In my Form I have various Textboxes that I write into with an in Form keyboard I created using Buttons. I have this code in Form.Load, which uses an event handler to determine which Textbox has the Focus:
For Each control As Control In Me.Controls
If control.GetType.Equals(GetType(TextBox)) Then
Dim textBox As TextBox = control
AddHandler textBox.Enter, Sub() FocussedTextbox = textBox
End If
Next
Then I use this on each button to write a specific character:
Private Sub btnQ_Click(sender As Object, e As EventArgs) Handles btnQ.Click
If btnQ.Text = "Q" Then
FocussedTextbox.Text += "Q"
ElseIf btnQ.Text = "q" Then
FocussedTextbox.Text += "q"
End If
End Sub
Up to that point I'm good and everything works as intended. The problem is I also have a DataGridView I want to write into but can't focus on it selected cells as I do on Textboxes.
I tried this:
For Each control As Control In Me.Controls
If control.GetType.Equals(GetType(TextBox)) Then
Dim textBox As TextBox = control
AddHandler textBox.Enter, Sub() FocussedTextbox = textBox
ElseIf control.GetType.Equals(GetType(DataGridViewCell)) Then
Dim DGVC As DataGridView = control
AddHandler DGVC.CellBeginEdit, Sub() FocussedTextbox = DGVC
End If
Next
But it just selects my last Textbox.
I declared the variable FocussedTextbox as Control so it's not specific to Textbox but any control.
Any help will be greatly appreciated.
To add text to the current ActiveControl using Buttons, these Button must not steal the focus from the ActiveControl (otherwise they become the ActiveControl).
This way, you can also avoid all those FocusedTextbox = textBox etc. and remove that code.
You just need Buttons that don't have the Selectable attribute set. You can use a Custom Control derived from Button and remove ControlStyles.Selectable in its constructor using the SetStyle method:
Public Class ButtonNoSel
Inherits Button
Public Sub New()
SetStyle(ControlStyles.Selectable, False)
End Sub
End Class
Replace your Buttons with this one (or, well, just set the Style if you're already using Custom Controls).
To replace the existing Buttons with this Custom Control:
Add a new class object to your Project, name it ButtonNoSel, copy all the code above inside the new class to replace the two lines of code you find there.
Build the Project. You can find the ButtonNoSel Control in your ToolBox now. Replace your Buttons with this one.
Or, open up the Form's Designer file and replace (CTRL+H) all System.Windows.Forms.Button() related to the Virtual KeyBoard with ButtonNoSel.
Remove the existing event handlers, these are not needed anymore.
Add the same Click event handler in the Constructor of the class that hosts those Buttons (a Form or whatever else you're using).
You can then remove all those event handlers, one for each control, that you have now; only one event handler is needed for all:
Public Sub New()
InitializeComponent()
For Each ctrl As Control In Me.Controls.OfType(Of ButtonNoSel)
AddHandler ctrl.Click, AddressOf KeyBoardButtons_Click
Next
End Sub
Of course, you also don't need to add event handlers to any other control, this is all that's required.
Now, you can filter the Control types you want your keyboard to work on, e.g., TextBoxBase Controls (TextBox and RichTextBox), DataGridView, NumericUpDown etc.
Or filter only special cases that need special treatment (e.g., MonthCalendar).
To add the char corresponding to the Button pressed, you can use SendKeys.Send(): it will insert the new char in the current insertion point, so you don't need any other code to store and reset the caret/cursor position as it happens if you set the Text property of a Control.
In this example, I'm checking whether the ActiveControl is a TextBoxBase Control, then just send the char that the clicked Button holds.
If it's a DataGridView, first send F2 to enter Edit Mode, then send the char.
You could also just send a char (so, no filter would be required), but in this case, you'll replace, not add to, the existing value of that Cell.
Private Sub KeyBoardButtons_Click(sender As Object, e As EventArgs)
Dim selectedButton = DirectCast(sender, Control)
Dim keysToSend = String.Empty
If TypeOf ActiveControl Is TextBoxBase Then
keysToSend = selectedButton.Text
ElseIf TypeOf ActiveControl Is DataGridView Then
Dim ctrl = DirectCast(ActiveControl, DataGridView)
If TypeOf ctrl.CurrentCell IsNot DataGridViewTextBoxCell Then Return
SendKeys.Send("{F2}")
keysToSend = selectedButton.Text
Else
' Whatever else
End If
If Not String.IsNullOrEmpty(keysToSend) Then
SendKeys.Send(keysToSend)
End If
End Sub
► Note that {F2} is sent just once: when the Cell enters Edit Mode, the ActiveControl is a DataGridViewTextBoxEditingControl, hence a TextBox Control, handled by the TextBoxBase filter.
This is how it works (using just the code posted here):

Forcing a combo box to update its text field

I have a typical combobox with drop down items. An item in the dropdown consists of a string with a code then a space, then the description of the code. I'm trying to get the text of the combo box to show just the code after the selection has been made, but there is a race condition in which my the text field is not being updated by the combobox until AFTER I change it. How do I force the combobox to update itself, so I can change the text afterwards.
With code_combo_box
AddHandler .SelectedIndexChanged, AddressOf update_desc
End With
Private Sub update_desc()
If code_combo_box.SelectedIndex >= 0 Then
Dim temp_string As String() = code_combo_box.SelectedItem.split(" ")
code_combo_box.Text = temp_string(0)
End If
End Sub
The combobox gets updated to the selected item after update_desc is called wiping out my change.
I figured out the answer which is to flag the event as handled when I enter the update_desc subroutine. So I needed to catch the events when entering the routine with
update_desc(sender as object, e as system.eventargs)
and then inside the routine simply use
e.handled = true
and the event would not continue to fire after leaving the routine and my changes would remain.

Show ContextMenuStripItem without clicking off the current cell

I'm using an UltraGrid which has a ContextMenuStrip with 2 items. These are shown when right-clicking an UltraGridCell.
However, in order to show them, the user has to first click off the cell to take it out of edit mode, then right click on it to show the ContextMenuStripItems.
This has become confusing and irritating to the user, so I was wondering if there is any way that it can be changed to show them when right clicking whilst still in edit mode?
I've tried this to take it out of edit mode after a key is pressed, but it doesn't work.
Private Sub ugComm_keyup(sender As Object, e As KeyEventArgs) Handles ugComm.KeyUp
ugComm.UpdateData()
If ugComm.ActiveCell.IsInEditMode = True Then
ugComm.ActiveCell.Row.Update()
End If
End Sub
I also tried something in the MouseClick that was suggested on the Infragistics forums, but again it didn't work.
Is there any way that a user right-clicking a cell that is in edit mode can bring up the ContextMenuStripItems rather than this menu?
The above image shows what is currently show when right-clicking a cell in edit mode (The cell is the bottom right white cell). I don't want this to appear, but the CMS instead.
EDIT
I've tried the suggestions in the current answers, but neither of those worked for me. Possibly because the grids are a slightly older version?
My most recent effort was done with the following code:
Private Sub ugComm_MouseDown(sender As Object, e As MouseEventArgs) Handles ugComm.MouseDown
If e.Button = Windows.Forms.MouseButtons.Right Then
Me.cmCommRate.Show(mouseX, mouseY)
End If
End Sub
But this wasn't triggered until the cell was no longer in edit mode.
NEITHER OF THE ANSWERS BELOW RESOLVE THE ISSUE. STILL NEEDS AN ANSWER
When any cell of the grid enters in edit mode a TextBox is drawn over the cell. The nice part here is this text box is reused for all the cells in the grid. When you right click on the cell in edit mode the default context menu, that comes from MS, shows. What you need to do is get this text box and assign it your context menu strip. You can do this by handling ControlAdded event of the grid like this:
' create a field to store the TextBox
Private cellTextBox As TextBox
Private Sub grid_ControlAdded(sender As Object, e As ControlEventArgs) Handles grid.ControlAdded
' Check if added control is TextBox
If TypeOf e.Control Is TextBox Then
' If added control is TextBox store it in your private field and set its ContextMenuStrip
If Me.cellTextBox Is Nothing Then
Me.cellTextBox = DirectCast(e.Control, TextBox)
Me.cellTextBox.ContextMenuStrip = Me.ctx
End If
End If
End Sub
I have tried to write an event handler for the MouseUp event with this code
Private Sub grid_MouseUp(sender As Object, e as MouseEventArgs) Handles grid.KeyUp
grid.PerformAction(UltraGridAction.ExitEditMode)
grid.ContextMenuStrip.Show()
End Sub
and it works.
The ContextMenuStrip was added in code with this text (as example)
ContextMenuStrip ctx = new ContextMenuStrip()
ctx.Items.Add("Test1")
ctx.Items.Add("Test2")
ctx.Items.Add("Test3")
grid.ContextMenuStrip = ctx

How to remove highlight of combobox when an Item is selected in Vb?

In load page event:
I read some data from DB and then add this data to Combo box then select an item as default and enable of combo box changes to false.
When I load this page, the item witch selected highlights with blue color.
How to remove this highlight?
You can modify its SelectionLength property, which gets or sets how many characters have been selected (highlighted).
Just set it to 0 after you have selected the default item and you should be good to go:
ComboBox1.SelectionLength = 0
EDIT:
In your case this code is executed before the Load event has finished. Due to this the form has not been rendered yet, which is why it is not working for you.
The simple fix is to add this in the form's Shown event too:
Private Sub Form1_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
ComboBox1.SelectionLength = 0
End Sub
If you don't want the caret to be in the beginning you can also add this line to set it to the end of the text:
ComboBox1.SelectionStart = ComboBox1.Text.Length
The proposed solution does not work in VB.NET 2016
The easiest way to do is to pass focus to another element like a label in the SelectedIndexChanged event

Are ListviewItems ever truely deselected?

I have a listview with several items in it. If I have an item selected and click in an empty white space or anywhere else on the form the highlight is removed but .FocusedItem & .SelectedItems still report an item is selected.
I have events that I want to trigger when no listviewitems are selected, but that never seems to occur. How do I detect if no items are selected or does that ever actually happen after that first item gets clicked?
Private Sub lstCats_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstCats.SelectedIndexChanged
If IsNothing(lstCats.FocusedItem) Then
DisableGUI()
Else
EnableGUI()
DisplayQuestions()
End If
End Sub
Basically DisableGUI() will never execute.
Thanks!
You can deselect all items in the ListView by clicking on an empty part of the ListView control (that is not on one of the items). For example:
Private Sub lstCats_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstCats.SelectedIndexChanged
If lstCats.SelectedItems.Count = 0 Then
DisableGUI()
Else
EnableGUI()
DisplayQuestions()
End If
End Sub
Note if you click on an item in the ListView, SelectedItems will be > 0. If you click on the background of the ListView (not on an item), SelectedItems will be = 0. This assumes that there is part of the ListView control that does not contain an item.