PictureBox is not showing up on button click event - vb.net

I am using a PictureBox inside a button click event. When the button is clicked I am enabling the PictureBox and I am running a long database call and at the end of the process, I am trying to disable the PictureBox. Inside the PictureBox I have a loading GIF.
But I don't know what's happening. My PictureBox does not show up..
Please suggest how can I fix this. I tried Thread.Sleep(1000), but it didn't work.
Private Sub btnRetrieve_Click(sender As Object, e As EventArgs) Handles btnRetrieve.Click
Me.PictureBox1.Visible = True
lblSuccess.Text = Nothing
UltraNumberOfConveyance.Value = Nothing
GetData() --Long Running Query
Me.PictureBox1.Visible = False
End Sub
My GetData Function:
Private Function GetData()
dsCheckPointTimes = GetCheckPointTimesByTerminalID()
dtDataTable = dsCheckPointTimes.Tables(0)
chkdtDataTable = dsCheckPointTimes.Tables(1)
If Not DBNull.Value.Equals(chkdtDataTable.Rows.Item(0).Item("ConveyanceName")) Then
lblConveyanceNameText.Text = chkdtDataTable.Rows.Item(0).Item("ConveyanceName").ToString()
End If
If Not DBNull.Value.Equals(chkdtDataTable.Rows.Item(0).Item("NumberOfConveyance")) Then
UltraNumberOfConveyance.Value = chkdtDataTable.Rows.Item(0).Item("NumberOfConveyance")
End If
If Not DBNull.Value.Equals(chkdtDataTable.Rows.Item(0).Item("Dock")) Then
UltratxtChangeLabel1.Value = chkdtDataTable.Rows.Item(0).Item("Dock")
End If
If Not DBNull.Value.Equals(chkdtDataTable.Rows.Item(0).Item("Lines")) Then
UltratxtChangeLabel2.Value = chkdtDataTable.Rows.Item(0).Item("Lines")
End If
If Not DBNull.Value.Equals(chkdtDataTable.Rows.Item(0).Item("CHECKPOINTTYPE")) Then
SetFields(chkdtDataTable.Rows.Item(0).Item("CHECKPOINTTYPE"))
End If
If dtDataTable.Rows.Count > 0 Then
LoadFlow()
Else
lblSuccess.Text = "No Records Found! Please check the ordernumber"
lblSuccess.ForeColor = Color.Red
End If
Return Nothing
End Function

Use a BackgroundWorker to do this:
Private WithEvents bgw As New BackgroundWorker
Private Sub btnRetrieve_Click(sender As Object, e As EventArgs) Handles btnRetrieve.Click
PictureBox1.Visible = True
bgw.RunWorkerAsync()
End Sub
Private Sub bgw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgw.DoWork
GetData() --Long Running Query
End Sub
Private Sub bgw_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
PictureBox1.Visible = False
End Sub

Related

Change the color of a button(s) for a duration of time

I have a small VB.net app that has a LOT of buttons. I need to change the back color of the buttons when they are clicked and then set it back to its original color after a duration of 10 seconds. I am struggling with either using a timer or the time process both of which have their own issues.
Any ideas to make this work and work efficiently?
Code:
Private Sub MyButtons_Click(sender As Object, e As EventArgs) _
Handles Button1.Click,
Button2.Click
Dim myButton = DirectCast(sender, Button)
MakeCall()
myButton.BackColor = Color.Green
'TurnOnActiveCallCOLOR.Enabled = True
For i As Integer = 0 To 10000 - 1
Threading.Thread.Sleep(10000)
Next
myButton.BackColor = Color.FromArgb(64, 64, 64)
End Sub
Here is an example of using a Windows Forms Timer to accomplish what you need:
Private MyButton As Button
Private Sub MyButtons_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click
MyButton = DirectCast(sender, Button)
MyButton.BackColor = Color.Green
Timer1.Enabled = True
MakeCall()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
MyButton.BackColor = Color.FromArgb(64, 64, 64)
Timer1.Enabled = False
End Sub
To handle an arbitrary number of buttons, you could have something like this:
Public Class Form1
Dim buttonTimers As New Dictionary(Of Control, ButtonTimer)
Class ButtonTimer
Property Timeout As Integer = 2000
Property Target As Control
Property ActiveColor As Color = Color.Green
Property DefaultColor As Color = Color.FromArgb(64, 64, 64)
Private tim As Timer
Sub TimTick(sender As Object, e As EventArgs)
tim.Stop()
Target.BackColor = DefaultColor
End Sub
Sub New()
' empty constructor
End Sub
Sub New(target As Control)
Me.Target = target
Me.Target.BackColor = Me.ActiveColor
tim = New Timer With {.Interval = Timeout}
AddHandler tim.Tick, AddressOf TimTick
tim.Start()
End Sub
Sub Restart()
Target.BackColor = Me.ActiveColor
If tim IsNot Nothing Then
tim.Stop()
tim.Start()
End If
End Sub
Public Sub DisposeOfTimer()
If tim IsNot Nothing Then
tim.Stop()
RemoveHandler tim.Tick, AddressOf TimTick
tim.Dispose()
End If
End Sub
End Class
Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click
Dim myButton = DirectCast(sender, Button)
'MakeCall()
If buttonTimers.ContainsKey(myButton) Then
buttonTimers(myButton).Restart()
Else
buttonTimers.Add(myButton, New ButtonTimer(myButton))
End If
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
For Each x In buttonTimers
x.Value.DisposeOfTimer()
Next
End Sub
End Class
If a button is clicked again before the timeout, the time is restarted.
You can add other constructors if you want to have a different timeout/colours for different buttons.
The MyBase.FormClosing code should be included in your form closing handler (if there is one) so that the timers are cleaned up properly.
I expect it would be tidier overall to make your own custom button class which inherits from Button, so you might want to investigate doing that. (How to: Inherit from Existing Windows Forms Controls.)
asynh and await if you don't want use timer. Simple method using task.delay
Private Async Sub ButtonClick(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click, Button3.Click, Button4.Click
DirectCast(sender, Button).BackColor = Color.Red 'after click setcolor to red
Await setColorAfterDelay(sender) 'Add this comand on button click and don't forget add asynh before sub in this method
End Sub
Public Async Function setColorAfterDelay(sender As Object) As Task
Await Task.Delay(1000) ''Milisecound how long you wana dealey
DirectCast(sender, Button).BackColor = Color.White 'and set colorto white
End Function
With the use of lambda expressions (and a lookup table if you want to interact with it further) you can do this pretty easily:
'Lookup table for if you want to be able to interact with the timers even more.
Dim ButtonTimers As New Dictionary(Of Button, Timer)
Private Sub MyButtons_Click(sender As Object, e As EventArgs) _
Handles Button1.Click, Button2.Click
MakeCall()
Dim myButton = DirectCast(sender, Button)
myButton.BackColor = Color.Green
'If a timer already exists for the button, restart it.
Dim existingTimer As Timer = Nothing
If ButtonTimers.TryGetValue(myButton, existingTimer) Then
existingTimer.Stop()
existingTimer.Start()
Return 'Do not execute the rest of the code.
End If
'Create the timer and set its Interval to 10000 ms (10 seconds).
Dim buttonTimer As New Timer() With {.Interval = 10000}
'Add a handler to its Tick event.
AddHandler buttonTimer.Tick, _
Sub(tsender As Object, te As EventArgs)
myButton.BackColor = Color.FromArgb(64, 64, 64)
'Dispose timer and remove from lookup table.
ButtonTimers.Remove(myButton)
buttonTimer.Stop()
buttonTimer.Dispose()
End Sub
ButtonTimers.Add(myButton, buttonTimer)
buttonTimer.Start()
End Sub
If you want to interact with a button's timer (if one exists) you can do:
Dim buttonTimer As Timer = Nothing
If ButtonTimers.TryGetValue(yourButtonHere) Then
'Do something with buttonTimer...
End If
This could probably be done better by dynamically creating timer controls so each button has it's own timer but here is what I came up with.
Oh, an set your timer to 1000 interval and enabled to 'False'.
Public Class Form1
Dim T1 As Integer = 0
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
T1 = T1 + 1
If T1 = 10 Then
For Each button In Controls
button.backcolor = Color.FromArgb(225, 225, 225)
Next
Timer1.Stop()
T1 = 0
End If
Me.Text = T1
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Button1.BackColor = Color.Red
Timer1.Start()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Button2.BackColor = Color.Orange
Timer1.Start()
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Button3.BackColor = Color.Yellow
Timer1.Start()
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Button4.BackColor = Color.Green
Timer1.Start()
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Button5.BackColor = Color.Blue
Timer1.Start()
End Sub
End Class

vb.net radiobutton progromatically setting 'Checked' and not cause 'Click' event

I am loading a form with values from stored settings from the registry
Typically :
If sFormat = TG_ReportFormatDft Then
RadioButton1.Checked = True
........
Else
RadioButton2.Checked = True
..........
End If
TG_ReportFormatDft is a string constant and is of no significance. The radio buttons are grouped correctly and manually clicked behave correctly.
Later in the procedure I check if there has been a manual change :
'Follow what the user is doing
Private Sub RadioButton1_Click(sender As Object, e As EventArgs) Handles RadioButton1.Click
msReports_Format2 = TG_ReportFormatDft
DoButtons(True)
End Sub
Private Sub RadioButton2_Click(sender As Object, e As EventArgs) Handles RadioButton2.Click
msReports_Format2 = TG_ReportFormatAlt
DoButtons(True)
End Sub
Imagine my surprise when these downstream subroutines are triggered without a mouse click. It would appear that :
RadioButton1.Checked = True --- triggers the mouse click event.
I can understand an 'On Change' event but the mouse click has not happened.
How can I prevent this 'click' event from propagating ?
Declare a class level boolean variable "ClickedFromCode". Now when you are setting the values from code set the boolean to true. See below sample code.
Private ClickedFromCode As Boolean
Private Sub Intialize
ClickedFromCode = True
If sFormat = TG_ReportFormatDft Then
RadioButton1.Checked = True
Else
RadioButton2.Checked = True
End If
ClickedFromCode = False
End Sub
Private Sub RadioButton1_Click(sender As Object, e As EventArgs) Handles RadioButton1.Click
If ClickedFromCode Then
Return
End If
msReports_Format2 = TG_ReportFormatDft
DoButtons(True)
End Sub
Private Sub RadioButton2_Click(sender As Object, e As EventArgs) Handles RadioButton2.Click
If ClickedFromCode Then
Return
End If
msReports_Format2 = TG_ReportFormatAlt
DoButtons(True)
End Sub

How to make a label blink

I have a Stopwatch in my form with Interval = 1000 displayed in the hh:mm:ss format.
When it reaches the 5th second it should start to blink the label background as green but so far I can only make the background color turn to green without any flash.
This is how I turn the background color to green:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Label1.Text = SW.Elapsed.ToString("hh\:mm\:ss")
If Label1.Text = "00:00:05" Then
Label1.BackColor = Color.Green
End If
End Sub
How do I make the label blink?
You could use a simple Async method to do this.
The following code will give Label1 the effect of flashing. Since we have used While True this will continue indefinitely once you hit "00:00:05".
Private Async Sub Flash()
While True
Await Task.Delay(100)
Label1.Visible = Not Label1.Visible
End While
End Sub
You would call this inside your Timer1_Tick method:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Label1.Text = SW.Elapsed.ToString("hh\:mm\:ss")
If Label1.Text = "00:00:05" Then
Label1.BackColor = Color.Green
Flash()
End If
End Sub
If you only want to flash a couple of times we can make a simple change to Flash():
Private Async Sub Flash()
For i = 0 To 10
Await Task.Delay(100)
Label1.Visible = Not Label1.Visible
Next
'set .Visible to True just to be sure
Label1.Visible = True
End Sub
By changing the number 10 to a number of your choice you can shorten or lengthen the time taken to flash. I have added in Label1.Visible = True after the For loop just to be sure that we see the Label once the flashing has finished.
You will have to import System.Threading.Tasks to make use of Task.Delay.
You need a label, two textboxes, and a button.
The screen allows you to 'set' a couple of colours - this could be taken further, by adding an Error colour, a Warning colour (where you haven't filled a field in...?) and more.
This colour selection would, in a real application, be done by an admin person, from a separate screen, and stored in the DB.
The timer frequency would also be set in the Admin screen/function.
This particular screen needs the textboxes to be double-clicked, and a colour selected for each one.
The back colour for each box changes. Then press the Start button.
If you press the Start button again, it toggles the timer (on/off)
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' not quite correct for what I want, but close...
' https://bytes.com/topic/visual-basic-net/answers/368433-blinking-text
Me.Label1.Text = "A blinking text box"
Me.Label1.BackColor = TextBox2.BackColor
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If Me.Label1.BackColor = TextBox2.BackColor Then
Me.Label1.BackColor = TextBox1.BackColor
Else
Me.Label1.BackColor = TextBox2.BackColor
End If
End Sub
Private Sub TextBox1_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles TextBox1.MouseDoubleClick
Dim dlg As New ColorDialog()
If dlg.ShowDialog() = DialogResult.OK Then
TextBox1.BackColor = dlg.Color
End If
End Sub
Private Sub TextBox2_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles TextBox2.MouseDoubleClick
Dim dlg As New ColorDialog()
If dlg.ShowDialog() = DialogResult.OK Then
TextBox2.BackColor = dlg.Color
End If
End Sub
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
Timer1.Enabled = Not Timer1.Enabled
End Sub
End Class
Try to put something like this in Timer1_Tick event handler -
Label1.Visible = Not Label1.Visible
Set the timer to enabled and it will do the job.
If you specify the color when the Text is 00:00:05 then you should also specify what the Backcolor should be when the text is something else i.e 00:00:06
Try this and see if it works:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Label1.Text = SW.Elapsed.ToString("hh\:mm\:ss")
If Label1.Text = "00:00:05" Then
Label1.BackColor = Color.Green
else
Label1.Backcolor = Color.Yellow '(Change color as needed)
End If
End Sub

result of a modal form in vb.net

I create a form 'frmX' and i call it as a modal form :
res = frmX.ShowDialog()
This form has 3 buttons, Abort(3), Retry(4) and Ignore(5), but when the form opens, all the buttons on the first click return 2.
I don't know why this occurs--all of the buttons has their property DialogResult right.
*Private Sub btnIgnorar_Click(sender As Object, e As EventArgs) Handles btnIgnorar.Click
btnIgnorar.DialogResult = DialogResult.Ignore
End Sub
Private Sub btnAbortar_Click(sender As Object, e As EventArgs) Handles btnAbortar.Click
btnAbortar.DialogResult = DialogResult.Abort
End Sub
Private Sub btnReintentar_Click(sender As Object, e As EventArgs) Handles btnReintentar.Click
btnReintentar.DialogResult = DialogResult.Retry
End Sub*
Can someone help me?
Could do with seeing a bit more context, but the following should do what I think you want:
Private Sub btnIgnorar_Click(sender As Object, e As EventArgs) Handles btnIgnorar.Click
DialogResult = DialogResult.Ignore
Close
End Sub
This will close the dialog and return the associated result code to the caller. As to the original code, it seems a bit strange setting the values in the buttons click handlers?
The error comes from the fact that you set the DialogResult of the buttons. You must set the DialogResult of the form !
You actually have more than one option.
Option 1 : Set the Form.DialogResult
Private Sub btnIgnorar_Click(sender As Object, e As EventArgs) Handles btnIgnorar.Click
Me.DialogResult = DialogResult.Ignore
End Sub
Private Sub btnAbortar_Click(sender As Object, e As EventArgs) Handles btnAbortar.Click
Me.DialogResult = DialogResult.Abort
End Sub
Private Sub btnReintentar_Click(sender As Object, e As EventArgs) Handles btnReintentar.Click
Me.DialogResult = DialogResult.Retry
End Sub
Option 2 : Set the Button.DialogResult
Public Sub New()
InitializeComponents()
'Your init code here
'...
'By setting the buttons DialogResults, you don't even have to handle the click events
btnIgnorar.DialogResult = DialogResult.Ignore
btnAbortar.DialogResult = DialogResult.Abort
btnReintentar.DialogResult = DialogResult.Retry
End Sub
'However, if you need to do some stuff before closing the form, you can
Private Sub btnAbortar_Click(sender As Object, e As EventArgs) Handles btnAbortar.Click
'Do some stuff
'You don't need the following line, as it will be done implicitly
'Me.DialogResult = DialogResult.Abort
End Sub

Adding 150,000 records to a listview without freezing UI

I have a listview loop that is adding 150,000 items to my listview. For testing purposes I moved this code to a background worker with delegates, but it still freezes up the UI. I am trying to find a solution so that it can add these items in the background while I do other stuff in the app. What solutions do you guys recommend?
this is what I am using
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ListView1.Clear()
ListView1.BeginUpdate()
bw.WorkerReportsProgress = True
bw.RunWorkerAsync()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If bw.IsBusy Then bw.CancelAsync()
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
For x = 1 To 125000
Dim lvi As New ListViewItem("Item " & x)
If bw.CancellationPending Then
e.Cancel = True
Exit For
Else
bw.ReportProgress(0, lvi)
End If
Next
End Sub
Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bw.ProgressChanged
Try
Dim lvi As ListViewItem = DirectCast(e.UserState, ListViewItem)
Me.ListView1.Items.Add(lvi)
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
ListView1.EndUpdate()
If Not e.Cancelled Then
Debug.Print("Done")
Else
Debug.Print("Cancelled")
End If
End Sub
End Class
Give this a try, it's a great example for what you would need... I also had a progress bar that shows the progress and such, see example image that is attached. Also I wasn't seeing any delegate that you need to perform such operation, mine has one that will be required. The reason is you are adding items to a control on the UI thread, in order to add items we need to know if an Invoke is required, if so we invoke otherwise we add the item to the control... Also I made the thread sleep, so it can take a break; this also prevents the UI from wanting to lock up here and there, now it's responsive with NO FREEZING.
Option Strict On
Option Explicit On
Public Class Form1
Delegate Sub SetListItem(ByVal lstItem As ListViewItem) 'Your delegate..
'Start the process...
Private Sub btnStartProcess_Click(sender As Object, e As EventArgs) Handles btnStartProcess.Click
lvItems.Clear()
bwList.RunWorkerAsync()
End Sub
Private Sub AddListItem(ByVal lstItem As ListViewItem)
If Me.lvItems.InvokeRequired Then 'Invoke if required...
Dim d As New SetListItem(AddressOf AddListItem) 'Your delegate...
Me.Invoke(d, New Object() {lstItem})
Else 'Otherwise, no invoke required...
Me.lvItems.Items.Add(lstItem)
End If
End Sub
Private Sub bwList_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bwList.DoWork
Dim intCount As Integer = CInt(txtCount.Text)
Dim dblPercent As Integer = 100
Dim intComplete As Integer = 0
Dim li As ListViewItem = Nothing
For i As Integer = 1 To CInt(txtCount.Text)
If Not (bwList.CancellationPending) Then
li = New ListViewItem
li.Text = "Item " & i.ToString
AddListItem(li)
Threading.Thread.Sleep(1) 'Give the thread a very..very short break...
ElseIf (bwList.CancellationPending) Then
e.Cancel = True
Exit For
End If
intComplete = CInt(CSng(i) / CSng(intCount) * 100)
If intComplete < dblPercent Then
bwList.ReportProgress(intComplete)
End If
If li IsNot Nothing Then
li = Nothing
End If
Next
End Sub
Private Sub bwList_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bwList.ProgressChanged
pbList.Value = e.ProgressPercentage
End Sub
Private Sub bwList_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bwList.RunWorkerCompleted
If pbList.Value < 100 Then pbList.Value = 100
MessageBox.Show(lvItems.Items.Count.ToString & " items were added!")
End Sub
Private Sub btnStopWork_Click(sender As Object, e As EventArgs) Handles btnStopWork.Click
bwList.CancelAsync()
End Sub
Private Sub btnRestart_Click(sender As Object, e As EventArgs) Handles btnRestart.Click
pbList.Value = 0
lvItems.Items.Clear()
txtCount.Text = String.Empty
End Sub
End Class
Screenshot in action...