Form loses focus after clicking button - vb.net

when clicking on the start button in the code below, the form seems to lose focus and I need to click the stop button twice to stop the count. (First click to activate the form, second to click the button) Can someone please explain this behavior or offer a better alternative?
Public Class Form1
Dim testrunning As Boolean
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
testrunning = True
test()
End Sub
Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click
testrunning = False
End Sub
Private Sub test()
Dim count As Integer
While testrunning = True
count += 1
TextBox1.Text = count.ToString
System.Threading.Thread.Sleep(100)
Application.DoEvents()
End While
End Sub
End Class

The form doesnt loose focus. The stop button does not gain focus after start-button is clicked- You could give it focus (btnStop.Focus()) in btnStart_Click.
The other problem is that you should change your test-function. It is more like a benchmark.
Read some articles about why using Application.DoEvents could be dangerous and is of poor design in general. It is better to use System.Windows.Forms.Timer or BackgroundWorkers instead.
I think in your code the Application.DoEvents first only let the stop button gain focus and you need a second click to perform the click event.

Related

How to make one-click buttons?

I have several buttons in which all of them have come codes. I want the user to only can make click the buttons once. How can I do it without having a long disable buttons code?
Dim oneClick As Integer
Private Sub btnPro_Click(sender As Object, e As EventArgs) Handles btnPro.Click
oneClick += 1
If oneClick = 1 Then
Dim ucP As New ucPro
fillMenu(ucP)
End If
End Sub
This is the code I come up with.
EDIT : The point is that I want to click a button once, but the others can be clicked. For example, I have a form with 6 buttons, every button has some codes. If I click Button1, it'll do such code only once, therefore if I click it again, it will not do that code, because it already did it. Then, if I click Button2, it'll do the code once. And what about if I click Button1 again? well, it'll be able to do that code because I clicked to another button.
Sorry for the way I explain myself. I hope you get it.
Keep track of last clicked button and you can use one handler for all involved buttons
Private _lastClickedButton As Button = Nothing
Private Sub Button_Click(sender As Object, e As EventArgs)
Dim button = DirectCast(sender, Button)
If button Is _lastClickedButton Then Exit Sub
_lastClickedButton = button
' Now based on button instance you can execute corresponding logic/method
End Sub
Based on your rather poor explanation, it sounds like what you actually mean is that you only want each button to act once in a row, i.e. once you click a button you need to click another button before the first button does anything again. In that case, the proper way to handle this is to not use Button controls.
Instead of using Button controls and handling their Click events, you should be using RadioButton controls and handling their CheckedChanged events. You can set the Appearance property to Button and they will look just like regular Buttons. When checked, they will appear depressed and that will indicate to the user that they can't be used again.
Here's an example of a form using such controls:
And here's what the appropriate code might look like:
Private Sub RadioButton1_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton1.CheckedChanged
If RadioButton1.Checked Then
'Do something.
End If
End Sub
Private Sub RadioButton2_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton2.CheckedChanged
If RadioButton1.Checked Then
'Do something else.
End If
End Sub
Private Sub RadioButton3_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton3.CheckedChanged
If RadioButton1.Checked Then
'Do yet something else.
End If
End Sub
Here's what the form might look like when a RadioButton has been checked:
As you can see, it's nice and clear to the user which one they cannot use.
EDIT:
If you are really determined to use Button controls then you absolutely should be disabling them as that is the standard way that feedback has been provided to the user for decades. It's very simple to disable a Button if and only if it is the last one clicked. Here's an example:
Private Sub AllButtons_Click(sender As Object, e As EventArgs) Handles Button3.Click,
Button2.Click,
Button1.Click
For Each btn In Controls.OfType(Of Button)
btn.Enabled = (btn IsNot sender)
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Do something.
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'Do something else.
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
'Do yet something else.
End Sub
Note that you can handle multiple events with a single method and multiple methods can handle a single event, both of which are demonstrated here. All four of those methods were generated automatically by the designer, so I just had to add the body code. Note that the first method assumes that all Button controls on the form will be treated this way. If that's not the case then would need a slight adjustment but nothing too major.

How to: Force users to focus a winform before selecting something from it

I am working on a project that uses WinForms, and I am running into concurrency problems when users click controls on a Form while it isn't the active window. My forms refresh whenever a user activates them to prevent them from showing old/dirty info, but if they click a button on an inactive Form the data doesn't get refreshed, which can cause a problem.
I know some programs in windows force you to select the window before you can preform any other actions, is there a way to do this in my VB.NET program?
This code run in my test, but some issues that must be handled to run as our need:
Dim mystts As Boolean = False
Private Sub Form2_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
'here your process, unfortunately this will be performed too after messagebox close back to form2
'for example the process are:
For myCnt As Integer = 1 To 4000
Debug.Print("Test") 'This only for waiting
Next
mystts = False
End Sub
Private Sub Form2_Deactivate(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Deactivate
'we must define the other criteria for make mystts=true, for example if
'we call messageBox.show, we can pass out from this for example we have msgFlag
'before call messageBox set msgFlag=true and after it set msgFlag=false
'and here you add: if msgFlag=true then exit sub
mystts = True
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'if we click this button and myStts=true, the next process will wait until process in form activate finish
MsgBox("this My Process, run after form2 activated and process finish")
End Sub

Looping backgroundworker

I have a vb.net application that I want to be made a) visible and b) topmost when the activewindow is set to my requirements - this part I have covered off fine.
What I want to be able to do is to use the backgroundworker to actively monitor this on a continuous loop - again I have covered this off fine.
The problem I am having is that when I am selecting a combobox, I cannot make a selection due to interference from the bgw - almost like when I click on the combobox to show the list, the bgw seems to almost do a click away from the combobox closing the list.
Any help would greatly be appreciated.
Here is my code:
Private Delegate Sub progressDelegate()
Private Sub frmApp_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.bgwActiveWindow.RunWorkerAsync()
End Sub
Private Sub bgwActiveWindow_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwActiveWindow.DoWork
Dim CheckWindow As progressDelegate
CheckWindow = New progressDelegate(AddressOf SetAppTopMost)
Me.Invoke(CheckWindow)
System.Threading.Thread.Sleep(100)
End Sub
Private Sub SetAppTopMost()
Dim bol As Boolean
If getActiveWindowTitle.IndexOf("Microsoft Outlook") <> -1 Or _
getActiveWindowTitle.IndexOf(My.Settings.AppName) <> -1 Then
bol = True
Else
bol = False
End If
Me.Visible = bol
Me.TopMost = bol
End Sub
Private Sub bgwActiveWindow_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgwActiveWindow.RunWorkerCompleted
bgwActiveWindow.RunWorkerAsync()
End Sub
as Praveen mentioned, check the state before setting it, to prevent setting focus to the window again. also, don't recreate the backworker thread each time:
Imports System.ComponentModel
Private Sub bgwActiveWindow_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bgwActiveWindow.DoWork
Do
' backworker code
Threading.Thread.Sleep(1000)
Loop While True
End Sub
of course, you'll either have to implement the 'supportscancellation' junk, or simple set a flag in your main thread and poll that on each loop and exit/break if you want to cancel.
you could also use a timer, which won't lock the thread.
i think you should add an additional check in your SetAppTopMost sub.
if Me.Visible = True then exit sub
This line should be 1st line. Since you are trying to show the form every 100ms, you are loosing focus.

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

what is the event for longpress in vb.net datagridview

How can I handle a long press in a cell/row in datagridview in vb.net?
I know how to handle events like click and double click. But I dont know how to handle a long press.
Any help is appreciated.
Thanks :)
You should start a timer on the mouse down event, stop it on the mouse up event, and draw you conclusion :)
Chew Chew:
Private ClickTime As DateTime
Private Sub DataGridView1_MouseDown(sender As Object, e As MouseEventArgs) Handles DataGridView1.MouseDown
ClickTime = Now
End Sub
Private Sub DataGridView1_MouseUp(sender As Object, e As MouseEventArgs) Handles DataGridView1.MouseUp
If (Now - ClickTime).TotalMilliseconds > 500 Then MsgBox("LongClick")
End Sub