Visual Basic Auto Scroll with RichTextBox - vb.net

I want my Richtextbox to be always at the bottom and "autoscroll" to the end.
I found this with some google searches:
Private Sub RichTextBox1_TextChanged(sender As Object, e As EventArgs) Handles RichTextBox1.TextChanged
RichTextBox1.SelectionStart = RichTextBox1.TextLength
RichTextBox1.ScrollToCaret()
End Sub
This seems to work but as the text updates it jumps to the top of the box and with another update to the bottom. Can someone help me out? Or is there a better method to keep the Textbox at the end?
Thanks,
Max

Your code kind of works- What I would suggest to solve your initial problem is to alter your code slightly and add
RichTextBox1.SuspendLayout()
at the beginning of your sub, and
RichTextBox1.ResumeLayout()
at the end.
However, if your cursor isn't on the last line and you type something, the character will appear at the cursor before moving to the end of the text. I'm guessing you don't want that behaviour - In which case you should add the code into a KeyPress event.
There are several possible behaviours. Do you want to be able to type anywhere, or only at the end of the text? Or just to place the cursor at the end under certain circumstances - for example when the RichTextBox is first populated with a bunch of text? Or maybe something else.
The simplest solution would be for the user just to press the keys Ctrl-End. That doesnt need any code at all.

Related

Excel Userform Textbox Constant Set Focus

First of all I would like to thank all of you guys. Maybe you did not notice but you help me to grasp VBA to some level from scratch. I am still in learning process so I may be missing something really simple, please be gentle :)
First of all I would like to give a small backgroud update about my issue. I have been writing a small program to scan incoming parts to my work to be able to keep inventory status. Latest look of the program is like below:
And numbers on the picture are my nightmares lately:
1. Scanned Part Number: This is the textbox where scanner inputs the value. After I receive the input I immidietly convert that data to a variable and clear the textbox value as below:
Private Sub PN_CurrentScan_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 13 Then
EnteredPN = Replace(PN_CurrentScan.Value, Chr(32), "", 1) '<---PN_CurrentScan is the name of text box
EnteredPN = Left(EnteredPN, 12)
PN_CurrentScan.Value = ""
After making some corrections on the scanned data I basically write it to a sheet in the workbook. Then I also have a pivot table in the same workbook which uses this scanned data as source and counts how many parts scanned from each part number.
2. Current Status: This ListBox contains all the part numbers scanned (Coming from the pivot table mentioned above) and waiting to be scanned (Coming from another worksheet). Then it refreshes it self every time a new part is scanned.
3. ListBox Scroll Bar: Since I have very long part number list it is not possible for me to fit everything on the screen that is why listbox creates this scroll bar.
Enough with the background I think :)
So if we come to my concern. Since my collages using cordless scanner to do this operation sometimes they don't have the chance to see the screen so they can not understand if the cursor is on the "Scanned Part Number Text Box" or not. That is why I need focus to be on that box no matter what happens (Of course we can not do anything if warehouse burns down, earth quake or tsunami hits the place but let do not think about those).
WHAT I HAVE TRIED:
First of all I disabled all the remaining objects from properties window
Then I diabled tab stops of all controls:
Dim contr As Control
For Each contr In ScannerInterface.Controls
On Error Resume Next
contr.TabStop = False
Next
ScannerInterface.PN_CurrentScan.TabStop = True
Added setfocus property to all button clicks:
Me.PN_CurrentScan.SetFocus
Added setfocus property to listbox click:
Private Sub CurrentStatus_List_Click()
Me.PN_CurrentScan.SetFocus
End Sub
Added set focus to enter and exit events of listbox however this did not work:
Private Sub CurrentStatus_List_Enter()
Me.PN_CurrentScan.SetFocus
End Sub
Private Sub CurrentStatus_List_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Me.PN_CurrentScan.SetFocus
End Sub
So, with all these counter measures I have managed to improve up to somepoint, only concern remaining is when I click on the scroll bar next to the listbox, text box lose focus and without clicking in the textbox I could not manage to set the focus again. I tried all events with listbox non of them worked. Is there any way to solve this problem or do I need to deal with this? Thanks in advance for your supports.
SOLUTION:
Thanks to #Rory we have managed to solve my problem. As he noticed and explained in the answer below, both my textbox and listbox were in frames. I have tried several setfocus options but I always gave the focus to the textbox. However, solution was to give the focus to the frame which was containing the target textbox:
Private Sub CurrentStatus_Frame_Enter() '<-- Enter event of the frame which contains listbox
Me.PN_CurrentScan.SetFocus '<-- Setfocus to target textbox
Me.Scanned_Frame.SetFocus '<-- Setfocus to frame which contains target textbox
End Sub
Having (eventually) noticed that both of your controls are inside container Frame controls, you can actually use the Enter event of the Frame that contains the listbox to set focus to the Frame that contains the textbox, rather than to the textbox itself.

Cut status strip label to width of form

I have a form with a status strip, which contains a progress bar an a label. Both of these are used to show the user the status/progress of several background workers.
My problem is that sometimes the label is longer than the form is wide (it contains Parameter names that vary quite widely in length). The form has a constant width and is not re-sizable by the user. When this issue occurs the label just appears as blank, I would instead like to cut the label to the length of the form and concatenate "..." on the end.
Can anyone give me some advise on where to start with this? i have tried Google and SO searches and have been unable to come up with anything similar. I essentially need to find the length of the string as it will display on the form, but I don't know where to start with that.
First thing to do is to change the StatusStrip.LayoutStyle from Table to Flow. Which will prevent the label from disappearing. Next, you still want the user to have a chance to read the full text of the label even though it is truncated. Set the StatusStrip.ShowItemToolTips property to True and the label's AutoToolTip to True.
Getting the label's text to not overlap the grip is an uglier problem to fix but one you don't have since you made your form un-resizable. Set the form's SizeGripStyle property to Hide.
This will fix your problem, no code required.
You can try something like this:
Private Sub Label1_Click(sender As Object, e As EventArgs) Handles Label1.Click
If Label1.Text.Length > iMaxLblLenght Then
Label1.Text = Label1.Text.Substring(0, iMaxLblLenght) & "..."
End If
End Sub

I have a "bug/glitch" in my vb program need assistance

I have a program that replaces every letter of the alphabet with something new inside the same textbox by clicking a button then buy clicking the button it translates it back to original text.
However when i run this program, yes it does work as needed but not 100%
Because after i click the button to translate, (yes it shows translated)
If delete the translated text and type something new, it goes back to the old text.
(this does not happen if i click the button again, it shows the orignal text. But if i type something new it will translate it.)
Any suggestions?
This is a continuation of your other question. You will need to reset your Boolean variable when you type in your TextBox i.e.
Private Sub TextBox1_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
bConverted = False
End Sub

How can I refer to a control from within a control's method (like the "me" for classes)?

How can I refer to the control while I am inside a control's method in VB.NET?
For example, I want in a textbox to show a message box with that textbox's text every time the text changes. The code would be something like:
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
msgbox("The text is:"+ Me.text)
' ok the line above wont work i already know that, because "Me" refer to the form,
' not the control textbox1
' how i will refer to the textbox1's text???
' i dont want to use "textbox1.text" is there a way similar like the "Me" is for forms?
' because i want to copy-paste a code like this in a lot of controls and do not want to
' have to change in every copy the name to each control name
End Sub
I hope I made myself clear; my English needs some improvement :D
No, there's no keyword that allows you to do that. However, every event raised by a control passes in a sender parameter that you can use to determine which particular control raised that event.
Note that this parameter is always typed as a basic Object (because it can represent any possible control), so you'll need to downcast to a more specific control class if you need to access any of the unique members that it exposes. Since you're handling an event raised by a TextBox control, you know that the sender must be of type TextBox, so you can simply use DirectCast to handle the upcasting. You don't have to worry that an InvalidCastException will be thrown.
For instance, your above example would become:
Private Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As EventArgs) Handles TextBox1.TextChanged
Dim textBox As TextBox = DirectCast(sender, TextBox)
MessageBox.Show("The text is: " & textBox.Text)
End Sub
That being said, there are a couple of concerning things that jump out at me in your question:
Any time that your approach to solving a problem is "copy-pasting" code, you should stop, take a step back, and try to figure out if there's any better way to achieve your ultimate goal.
For example, if you need every textbox on your form to react in the same way whenever a particular event is raised, you should consider subclassing the existing TextBox control and consolidating all of your code in one place. Remember that you can inherit off of most of the standard controls to add custom functionality. This is often a far better solution than copying and pasting code to multiple places in your project. If you ever need to track down a bug or modify that functionality, you'll only have to change it one place in your code, rather than several. As a somewhat cheekier benefit, you'll be able to use Me to refer to that control when you're editing its subclass.
You should always prefer to concatenate (combine) strings using the & operator in VB.NET, rather than the + sign. Or perhaps even better, the String.Concat or String.Format methods.
There is no reason to use MsgBox in VB.NET, as opposed to MessageBox.Show. No, this won't improve performance of your application, but it's a good practice to get into for .NET languages.
The sender variable contains the TextBox instance you want to access. You only need to convert the sender to TextBox.

Odd ComboBox behavior on resize

I have an issue where a ComboBox control will change it's Text value when it is resized. Here is some sample code that I worked up:
Option Explicit On
Option Strict On
Public Class FMain
Private Sub FMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
uxComboBox.DropDownStyle = ComboBoxStyle.DropDown
uxComboBox.AutoCompleteSource = AutoCompleteSource.ListItems
uxComboBox.AutoCompleteMode = AutoCompleteMode.Suggest
ComboTest()
End Sub
Private Sub ComboTest()
Dim value As String = "6"
uxComboBox.Text = String.Empty
uxComboBox.Items.Clear()
uxComboBox.Items.AddRange(New String() {"4 9/16", "6 9/16", "7 9/16", "8 9/16"})
Dim index As Integer = uxComboBox.FindStringExact(value)
If uxComboBox.SelectedIndex index Then
uxComboBox.SelectedIndex = index
End If
If uxComboBox.SelectedIndex = -1 AndAlso _
Not String.Equals(uxComboBox.Text, value, StringComparison.OrdinalIgnoreCase) Then
uxComboBox.Text = value
End If
' unselect the text in the combobox
'
uxComboBox.Select(0, 0)
End Sub
End Class
Note that this form (FMain) has a single combobox on it (uxComboBox) that is docked to the top. When I run the code I see that the combobox has a value of "6" which is what I would expect. When I then resize the form, the combobox gets a value of "6 9/16" which is what I would NOT expect.
Does anyone know why this happens? Any suggested workarounds?
Thanks!
Stephen
Yes, this is a known bug in the native Windows implementation of ComboBox. There's another aspect to this bug. Put a button on your form and give it TabIndex = 0, change the CB's TabIndex to 1. Run it, the button will have the focus. Resize. Note that the ComboBox's text changes as before but now also gets highlighted, as though it has the focus. Even though it hasn't.
I think this bug has been around since Vista, it didn't get fixed in Win7. There's no known workaround for it.
When the form loads, ComboTest gets executed, and you see a '6', however when you resize it does not show the new data, sounds like you need to refresh the combo box, regardless of the resize or not.
Try uxComboBox.Refresh() immediately after the line uxComboBox.Items.AddRange.
And after the line 'ComboTest', set the selected index to 0 uxComboBox.Index = 0 also.
Hope this helps,
Best regards,
Tom.
I am using windows 10 and Visual Studio 2017. It appears that this bug is still around. With Hans Passant's answer above I worked around the problem in this way.
I had a combo as a control anchored left and right so it stretched when the form expanded. When the screen expanded, the combobox text was highlighted as if it had got focus even though it hadn't.
As a work around I took one of the anchors off and added it to text box that was next to it. Now my combo box doesn't expand with the screen, the text box does instead. I know its not a fix all solution but it may help someone in a similar situation to sort the problem.