How continually output text to a RichTextBox with it being visually noticeable? - vb.net

I am just trying to make my own VB project right now to get familiar with the language, and all I would like for it to do is continually print a string to the next line in a RichTextBox.
The issue that I can't figure out is to have it print one after another, it is printing all at once. Ill have some code down below to show where I am at right now.
I've tried using different counting methods, and depending on how it is set up, the debugger won't even load...
Friend WithEvents TableLayoutPanel1 As System.Windows.Forms.TableLayoutPanel
Friend WithEvents Button1 As System.Windows.Forms.Button
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
End Sub
Private Sub RTB1_TextChanged(sender As System.Object, e As System.EventArgs)
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim counter1 As Integer = 0
Dim i As String = "- I" & vbCrLf
While counter1 <= 10
Timer1.Interval = 1000
Timer1.Start()
i = i + i
counter1 += 1
End While
RichTextBox1.Text = i
'Loop
'Environment.NewLine
End Sub
Friend WithEvents TableLayoutPanel2 As System.Windows.Forms.TableLayoutPanel
Private Sub TableLayoutPanel2_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles TableLayoutPanel2.Paint
End Sub
Friend WithEvents RichTextBox1 As System.Windows.Forms.RichTextBox
Private Sub RichTextBox1_TextChanged(sender As System.Object, e As System.EventArgs) Handles RichTextBox1.TextChanged
RichTextBox1.SelectionStart = RichTextBox1.Text.Length
RichTextBox1.ScrollToCaret()
End Sub
Friend WithEvents Timer1 As System.Windows.Forms.Timer
Thank you to anyone that takes the time to look at this and help me out!
I really am looking for my output to scroll down the RichTextBox and continually to output a string on a new line over and over again one at a time.

As described:
Create a System.Windows.Forms.Timer. There are different types of Timers available. This is the one you need to update an UI component, since it's Tick event is raised in the UI thread.
Initialize the Timer and set its Interval to 1 second (1000 ms). The initialization is performed in the Shown() event of the Form, which is raised when the Form is ready to be presented (see the Docs).
Add the Timer.Tick event handler (here is added in code)
Initialize an Integer field (here, called timerCounter) which is incremented each time the Timer Ticks.
In the Tick event, add a line of text to the RichTextBox control using it's AppendText() method, which allows to add text to the control without clearing it. This method is common to all controls that inherit TextBoxBase.
Note:
I'm adding the text to the RichTextBox using an interpolated string $"{Some value}". If your version of VB.Net doesn't suppport it, use the older format:
RichTextBox1.AppendText("Line number " & timerCounter.ToString() & Environment.NewLine)
Private rtbTimer As System.Windows.Forms.Timer
Private timerCounter As Integer = 0
Protected Sub TimerTick(sender As Object, e As EventArgs)
timerCounter += 1
RichTextBox1.AppendText($"Line number {timerCounter} {Environment.NewLine}")
RichTextBox1.ScrollToCaret()
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
rtbTimer = New Windows.Forms.Timer With { .Interval = 1000 }
AddHandler rtbTimer.Tick, AddressOf TimerTick
rtbTimer.Start()
End Sub

Related

VB fires changetext event before control is loaded

I need to add some controls to a Visual Basic 2017 form programmatically. One of the controls is a textbox that needs a changetext event handler. Below is some code that accomplishes that task.
HOWEVER, the changetext event handler seems to fire right away, before the form even loads... before the textbox itself even loads! A "click" handler works fine, as expected. But changetext? Nope.
I've thrown together a simplified version to demonstrate. The line with the "DIES RIGHT HERE" comment causes the problem (not the comment, but the code to the left of it).
A textbox that is added at design time will work fine, not cause this problem, but that isn't an option.
What's causing this the changetext handler to be run early? How do I work around this?
Public Class Form1
Dim txtTest As TextBox
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim pntTextBox As Point
pntTextBox.X = 100
pntTextBox.Y = 100
txtTest = New TextBox
With txtTest
.Location = pntTextBox
.Width = 100
AddHandler txtTest.TextChanged, AddressOf txtTest_TextChanged
End With
Me.Controls.Add(txtTest)
End Sub
Private Sub txtTest_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyClass.TextChanged
Dim strTest As String
strTest = Str(txtTest.Width) ' ****** DIES RIGHT HERE
MsgBox(strTest)
End Sub
End Class
Made a few changes. Works.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For x As Integer = 1 To 2 'create multiple TB's
Dim pntTextBox As Point
pntTextBox.X = 100 * x
pntTextBox.Y = 100
Dim txtTest As TextBox = New TextBox
With txtTest
txtTest.Name = "tb_" & x.ToString
AddHandler txtTest.TextChanged, AddressOf txtTest_TextChanged
.Location = pntTextBox
.Width = 100
End With
Me.Controls.Add(txtTest)
Next
End Sub
Private Sub txtTest_TextChanged(ByVal sender As Object,
ByVal e As System.EventArgs) 'no handler at design time
Dim tb As TextBox = DirectCast(sender, TextBox)
Dim strTest As String
strTest = tb.TextLength.ToString
Debug.WriteLine("{0} {1}", tb.Name, strTest) 'put breakpoint here
End Sub
End Class

VB.NET Timer stops working after it ticks the first time

the timer in my code stops working after the first tick, I have it set to start ticking every second when the form loads:
Private Sub FormIdleTimeWaster_Load(sender As Object, e As EventArgs) Handles MyBase.Load
timerCPS.Interval = 1000
timerCPS.Start()
End Sub
but after the first tick, it stops working:
Private Sub TimerCPS_Tick(sender As Object, e As EventArgs) Handles timerCPS.Tick
lblCPS.Text = CStr(CPS)
lblTotalHW.Text = CStr(CPS + HWTotal)
End Sub
All the other code refrencing timerCPS is
Me.timerCPS = New System.Windows.Forms.Timer(Me.components)
Friend WithEvents timerCPS As Timer
Nowhere else references timerCPS in my code and I'm not sure what's wrong
I have replicated your code as given in the question and it is working perfectly fine. It is ticking over every second.
I have modified your code to this:
Public Class FormIdleTimeWaster
Private CPS As Integer = 1
Private Sub timerCPS_Tick(sender As Object, e As EventArgs) Handles timerCPS.Tick
CPS += 1
lblCPS.Text = CStr(CPS)
End Sub
Private Sub FormIdleTimeWaster_Load(sender As Object, e As EventArgs) Handles MyBase.Load
timerCPS.Interval = 1000
timerCPS.Start()
End Sub
End Class
I can clearly see the value in the label increasing by one each tick.
The call to timerCPS.Start() is not needed in timerCPS_Tick.
If you still have an issue then there is some other code you haven't shown.

vb.net form load and render speed too slow

I have a mdi parent form which, when clicking a specific button on the screen, opens a new child form. When this form loads, it needs to call the database to retrieve information, the problem is that the form takes a lot of time to load, like 15 seconds, there's not too much code in the load sub, also, I tried to remove the database code from the load event, and, although it did make it a little faster, it still takes some time to load, is there a way to fix this?
This is my form
This is my code
Public Class Deposito
Dim FormPadre As MDICajero = New MDICajero
Private monedas As ArrayList = New ArrayList
Private Sub Deposito_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.WindowState = FormWindowState.Maximized
FormPadre = Me.MdiParent
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim ProximoForm As MenuPrincipal = New MenuPrincipal
FormPadre.LimpiarForm()
ProximoForm.MdiParent = FormPadre
ProximoForm.WindowState = FormWindowState.Maximized
ProximoForm.Show()
ProximoForm.CargaMenu(1)
End Sub
Private Sub BDepositar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BDepositar.Click
Dim dato As Emovimientos = New Emovimientos
dato.monto = montodeposito.Text
dato.idcuenta = nrocuenta.Text
dato.fecha = fechacobro.Value
End Sub End class
I've worked with java before and never seen so much load time between forms, even when retrieving information off a database.
EDIT: added a few lines to the constructor to make the form load faster, however, the rendering process it's still buggy.
Sub New()
Me.SetStyle(ControlStyles.DoubleBuffer Or ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.UserPaint, True)
InitializeComponent()
End Sub
EDIT 2: on the MDI parent form i used the same code that is automatically written when adding a mdi form to your solution, the only thing i added was an event for when the buttons are pressed to open the child forms:
Private Sub BRetiro_Click(sender As System.Object, e As System.EventArgs) Handles BRetiro.Click
Dim ProximoForm As Retiro = New Retiro
Me.LimpiarForm()
ProximoForm.MdiParent = Me
ProximoForm.WindowState = FormWindowState.Maximized
ProximoForm.Show()
End Sub
This is the code of the "LimpiarForm" function:
Public Sub LimpiarForm()
'borro todos los form hijos para no ocupar memoria, debe ser lo primero que tengo que hacer
Dim num As Integer
For num = 0 To Me.MdiChildren.Count - 1
Dim a = Me.MdiChildren(num)
a.Dispose()
Next
End Sub

How can I make Timer do different things based on how it was started

How can I make my Timer do different things depends on what activated it? I've tried using this code
Dim a As Integer = 0
Dim b As Integer = 0
Private Sub Button1_MouseHover(sender As Object, e As EventArgs) Handles Button1.MouseHover
Timer1.Start
End Sub
Private Sub Button2_MouseHover(sender As Object, e As EventArgs) Handles Button2.MouseHover
Timer1.Start
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick, Button2.MouseHover, Button1.MouseHover
If sender Is Button1 Then
a = a + 1
TextBox1.Text = a
End If
If sender Is Button2 Then
b = b + 1
TextBox2.Text = b
End If
End Sub
but Textbox just add 1 once. This means that the Timer just act one time not continuously like Timer usually do. So is there anything I do wrong there, or i can do something different?.
Another possibly simpler approach, would be to use the Timer.Tag property and use one handler for both buttons:
Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click
Timer1.Tag = sender
Timer1.Start()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
a += 1
If Timer1.Tag Is Button2 Then
TextBox1.Text = a.ToString
End If
If Timer1.Tag Is Button1 Then
TextBox2.Text = a.ToString
End If
End Sub
Since Tag is already of type Object no external casting is needed.
I included the Start function, since I wasn't sure how you're initially starting the timer. If you're doing in a different manner it can be left out of the button event handler
I am not sure what is value of this and this is not, generally speaking, something people do, but if you want to know which action activated timer you need to register it
Private _timer As Timer
Private _activatingControl As Object
Private Sub ActivateTimer(c as Object)
_activatingControl = c ' this is first
_timer.Start()
End Sub
Private Sub Button2_MouseHover(sender As Object, e As EventArgs) Handles Button2.MouseHover
ActivateTimer(sender)
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick, Button2.MouseHover, Button1.MouseHover
. . . . . .
System.Diagnostics.WriteLine("timer was activated by" + _activatingControl.ToString())
If DirectCast(_activatingControl, Control).Name = "Button1" Then
. . . .
ElseIf DirectCast(_activatingControl, Control).Name = "Button2" Then
. . . .
End If
End Sub
So, you will always need to activate timer via ActivateTimer. Timer1_Tick(sender As Object will always be Timer itself
I like tinstaafl's Tag property method. A similar approach would be to create a custom timer which inherits from System.Windows.Forms.Timer and has a Button property which can be set in the button's MouseHover event handler.
The timer's Start method only needs to be called once so I moved this to the form's load event handler. I am not sure exactly what you are wanting to achieve. Depending on this, the timer's Start method could be left where it was in the button MouseHover event handler and Timer1.Stop could be called at the end of the timer's tick event handler. This would then increment the value of the counter (a) only once in response to each MouseHover event. Alternatively Timer1.Stop could be called in the buttons' MouseLeave events if you only wanted the counter to increment while the mouse is hovering over the buttons.
Public Class Form1
Private Class CustomTimer
Inherits System.Windows.Forms.Timer
Private m_myButton As Button
Public Property Button() As Button
Get
Return m_myButton
End Get
Set(ByVal value As Button)
m_myButton = value
End Set
End Property
End Class
Private WithEvents Timer1 As New CustomTimer
Private a As Integer
Private Sub Form1_Load(sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Timer1.Interval = 100
Timer1.Start()
End Sub
Private Sub Button_MouseHover(sender As Object, e As EventArgs) Handles Button1.MouseHover, Button2.MouseHover
Timer1.Button = DirectCast(sender, Button)
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
a += 1
If Timer1.Button Is Button1 Then
TextBox1.Text = a.ToString
ElseIf Timer1.Button Is Button2 Then
TextBox2.Text = a.ToString
End If
End Sub
End Class

Mouse click and hold event?

Does anyone have an idea how to handle a mouse click and hold event in VB.NET?
Suppose I want to click and hold in a button and do some stuff behind the code like change the button BackColor or close a window faster( just like when you click in the ms office 2013 file menu then use a left-arrow to close that menu).
Hope you know what I mean
Thank you
You could create a timer that is defined globally that begins when MouseDown is called, then ends on Mouse Up. You can then set a condition on how many milliseconds need to pass before you deem it a 'long click'. See example code below:
Public Class Form1
Dim WithEvents timer As New Timer
Dim milliseconds As Integer
Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown
timer.Start()
End Sub
Private Sub Form1_MouseUp(sender As Object, e As MouseEventArgs) Handles MyBase.MouseUp
timer.Stop()
Label1.Text = "Button held down for: " & milliseconds & " milliseconds"
If milliseconds >= 10 then 'Mouse has been down for one second
DoSomething()
End If
End Sub
Private Sub EggTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timer.Tick
milliseconds += 1
End Sub
End Class
MouseDown is what you are looking for