0

I am currently working on a project and decided to create a user interface for it using visual studio with a windows forms application(Visual Basic).

The problem I'm facing is that the user interface doesn't respond as quickly and smoothly as I'd like it to. Mainly, I am using pictures as buttons to make the user form look more modern. However, when I hover my mouse over a "button" it takes a while until the "highlighted button" appears.

P1 is the picture of the "normal button" and P2 is the picture of the "highlighted button".

Here is the short code I have for now:

Public Class Main

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load


End Sub

Private Sub PictureBox1_MouseHover(sender As Object, e As EventArgs) Handles P1.MouseHover
    P1.Visible = False
    P2.Visible = True
End Sub

Private Sub P2_MouseClick(sender As Object, e As MouseEventArgs) Handles P2.MouseClick
    'Call cmdInit()
    'Call cmdConnectRobot()
    'Call cmdUnlock()
End Sub

Private Sub Main_MouseHover(sender As Object, e As EventArgs) Handles Me.MouseHover
    If P2.Visible = True Then
        P2.Visible = False
        P1.Visible = True
    End If
End Sub

Private Sub P4_Click(sender As Object, e As EventArgs) Handles P4.Click

End Sub
End Class

Another problem I'm facing is that when I call other subs, the user form becomes unresponsive while the sub is running. I researched and found that I could implement multi threading or async tasks but I'm a bit lost and would be extremely grateful if someone could guide me or point me in the right direction.

Thanks in advance!!

magicandre1981
  • 27,895
  • 5
  • 86
  • 127
  • Regarding multithreading you should really look at some proper tutorials. However I have a quick introduction in my answer here, which includes how you can access the user interface from your thread: https://stackoverflow.com/a/45571728/3740093 – Visual Vincent May 16 '18 at 16:08
  • I'm voting to close this question as off-topic because it's asking about improvement of existing code and or a review. Please move this over to [**Code Review**](https://codereview.stackexchange.com/) – Trevor May 16 '18 at 17:31

2 Answers2

1

I'll start by saying i'm not a programmer by trade, and i'm sure someone will point out better ways of doing these things, but in regards to the threading question it's fairly simple to implement.

Imports System.Threading
Public Class Form1
Dim WorkerThread As New Thread(AddressOf DoWork)

'WorkerThread' can be any name you like, and 'DoWork' is the name of the sub you want to run in the new thread, and is launched by calling:

WorkerThread.start()

However there is a catch, the new thread is not able to interact directly with the GUI, so you cannot change textbox text etc... I find the easiest way to get changes made to the GUI is to drag a timer onto your form, and have the new thread change variables (pre-defined just below Public Class Form1), then use the Timer1 Tick event to monitor the variables and update the GUI if there are any changes.

Brian Cox
  • 46
  • 4
  • 1
    If you find accessing the User Interface from a thread to be difficult you could also benefit from this answer of mine (read everything from _**Accessing the UI thread**_ and down): https://stackoverflow.com/a/45571728/3740093 – Visual Vincent May 16 '18 at 16:09
  • Thanks for the genuinely non-condescending reply. I had looked into the method provided in your link to the older post, tried it briefly and then found a way of making what i wanted to do to work and never mastered the invoke method, but i guess it's time i actually get that learned. Thanks again. – Brian Cox May 16 '18 at 17:40
  • Glad I could help, I suppose...? Call me stupid, but I currently actually find it hard to interpret whether you were ironic when you said _"genuinely non-condescending reply"_, so just to be on the safe side: I didn't intend to be or sound condescending _**if**_ that's what you thought, I'm just trying to help. :) – Visual Vincent May 16 '18 at 18:38
  • Specifically the part titled _**Making it simpler**_ is what you are after if you find invoking difficult, but I still recommend reading everything in order to get a hunch of how it works. :) – Visual Vincent May 16 '18 at 18:44
  • 1
    lol, i can see why, but it was meant literally, i do appreciate (as i'm sure the OP does) getting help and suggestions with examples, rather than the all too frequent alternative of "why do you want to do that?... that's stupid, you're stupid, all you need to do is pass the arguments to the object via a handle augmentation sub (<-intended to sound like the jibberish the responses sound like to people who don't code for a living when given with no context or example) – Brian Cox May 16 '18 at 18:55
1

In this case your UI is responsive, however the MouseHover event is only raised once the mouse cursor has hovered over the control for a certain amount of time (default is 400 ms), which is what is causing the delay.

What you are looking for is the MouseEnter event, which is raised as soon as the cursor enters ("touches") the control:

Private Sub P1_MouseEnter(sender As Object, e As EventArgs) Handles P1.MouseEnter
    P1.Visible = False
    P2.Visible = True
End Sub

You can then use that together with the MouseLeave event on the second picture box to switch back to the non-highlighted image:

Private Sub P2_MouseLeave(sender As Object, e As EventArgs) Handles P2.MouseLeave
    P1.Visible = True
    P2.Visible = False
End Sub

However switching picture boxes like this is not optimal. I recommend you to look into how you can use Application Resources, then modify your code to only switch the image that one picture box displays.

Here are the basic steps:

  1. Right-click your project in the Solution Explorer and press Properties.

  2. Select the Resources tab.

  3. To add an image either:

    a. Drag and drop the image onto the resource pane.

    b. Click the arrow next to the Add Resource... button and press Add Existing File....

Now, in your code add this right below Public Class Form1:

Dim ButtonNormal As Image = My.Resources.<first image name>
Dim ButtonHighlighted As Image = My.Resources.<second image name>

Replace <first image name> and <second image name> with the names of your button images.

Now you only need one picture box for the button:

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    P1.Image = ButtonNormal
End Sub

Private Sub P1_MouseEnter(sender As System.Object, e As System.EventArgs) Handles P1.MouseEnter
    P1.Image = ButtonHighlighted
End Sub

Private Sub P1_MouseLeave(sender As System.Object, e As System.EventArgs) Handles P1.MouseLeave
    P1.Image = ButtonNormal
End Sub
Visual Vincent
  • 18,045
  • 5
  • 28
  • 75