Mousewheel scroll inconsistent with two tablelayoutpanels - vb.net

I have two tablelayoutpanels side by side.
The scroll events of both panels are linked so the user scrolls one and the other scrolls too. This works fine:
Private Sub Layout_SidePanel_Scroll(sender As Object, e As ScrollEventArgs) Handles Layout_SidePanel.Scroll
If e.ScrollOrientation = ScrollOrientation.VerticalScroll Then
'make the other panel scroll too
Layout_Main.VerticalScroll.Value = Layout_SidePanel.VerticalScroll.Value
End If
End Sub
Private Sub Layout_Main_Scroll(sender As Object, e As ScrollEventArgs) Handles Layout_Main.Scroll
If e.ScrollOrientation = ScrollOrientation.VerticalScroll Then
'make the other panel scroll too
Layout_SidePanel.VerticalScroll.Value = Layout_Main.VerticalScroll.Value
End If
End Sub
However, when the user uses the mousewheel to scroll it doesn't work at all well. One side will scroll and not the other. Or one will scroll a bit more than the other. I've checked the vertical scroll values of the two panels and can see they don't match up. I need to either get the scrolling to work consistently or disable the mousewheel scrolling.
This is my code for handing the mousewheel events:
Private Sub Layout_Main_MouseWheel(sender As Object, e As MouseEventArgs) Handles Layout_Main.MouseWheel
Layout_SidePanel.VerticalScroll.Value = Layout_Main.VerticalScroll.Value
End Sub
Private Sub Layout_Sidepanel_MouseWheel(sender As Object, e As MouseEventArgs) Handles Layout_SidePanel.MouseWheel
Layout_Main.VerticalScroll.Value = Layout_SidePanel.VerticalScroll.Value
End Sub

Found it!
https://stackoverflow.com/a/5565804/3953342
I need to include .PerformLayout
Layout_SidePanel.VerticalScroll.Value = Layout_Calendar.VerticalScroll.Value
Layout_SidePanel.PerformLayout()

Related

Improve UI responsiveness on windows form application

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!!
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:
Right-click your project in the Solution Explorer and press Properties.
Select the Resources tab.
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
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.

Mouse hovering event

I want to do an mouse hovering event, when the mouse is over an button I want to change button text color and font size, I have try this code but doesn't work:
Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Command1.ForeColor.MediumBlue()
Command1.FontSize = 10
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Command1.ForeColor.White()
Command1.FontSize = 8
End Sub
Can anyone give me a suggestion i have search on Google and try different ways with mouse event handler but didn't work.
First, instead of tracking every mouse move, you can rely on MouseEnter and MouseLeave events of the button.
Second, do not forget to add Handles <Control>.<Event> clause at the declaration of your event-handling procedures.
Result:
Private Sub Command1_MouseEnter(sender As Object, e As EventArgs) _
Handles Command1.MouseEnter
Command1.FontSize = 10
End Sub
Private Sub Command1_MouseLeave(sender As Object, e As EventArgs) _
Handles Command1.MouseLeave
Command1.FontSize = 8
End Sub
Also please do not forget that some users are preferring keyboard control.
This means that
You might want to equip the button with an accelerator.
Command1.Text = "&Launch" (now Alt+L activates the button)
Note: accelerator character for winforms is &, for wpf is _.
You might want to make your entry/leave effect also when the button receives/looses keyboard focus (focus is moved using Tab and Shift+Tab key).
You can try making your changes into MouseEnter and MouseLeave
Private Sub RightButton_MouseEnter(sender As System.Object, e As System.EventArgs) Handles RightButton.MouseEnter
RightButton.ForeColor = Color.AliceBlue
RightButton.Font = New Font(RightButton.Font, 12)
End Sub
Private Sub RightButton_MouseLeave(sender As System.Object, e As System.EventArgs) Handles RightButton.MouseLeave
RightButton.ForeColor = Color.White
RightButton.Font = New Font(RightButton.Font, 10)
End Sub

Getting a panel within a panel with mouse position

I've been looking for this thing... It should be working yet it is not. There must be something I don't get understand or that I'm missing. It's quite a simple problem but I can't seem to solve it.
I got Panel1 and Panel2 as shown in this picture.
I want to catch when mouse is over Panel2 within Panel1 MouseLeave event. My code goes like this :
Private Sub Panel1_MouseLeave(sender As Object, e As EventArgs) Handles Panel1.MouseLeave
If sender.ClientRectangle.Contains(PointToClient(Control.MousePosition)) Then
For Each ctrl As Object In sender.controls
If ctrl.ClientRectangle.Contains(PointToClient(Control.MousePosition)) Then Exit Sub
Next
If Not IsNothing(sender.BackgroundImage) Then sender.BackgroundImage = Nothing
End If
End Sub
Private Sub Panel2_MouseLeave(sender As Object, e As EventArgs) Handles Panel2.MouseLeave
If Not sender.ClientRectangle.Contains(PointToClient(Control.MousePosition)) Then
If Not IsNothing(sender.BackgroundImage) Then sender.BackgroundImage = Nothing
End If
End Sub
I'm successfully getting into the first if, but the 2nd one within the For Each just never equals true. So I thought maybe there was a problem with the 2nd panel, so I tried placing the same code for Panel2 MouseLeave, but it's working just fine.
I really need this code to work for a big control flickering problem I'm having.
Thanks to Hans Passant for the hint. I just had to call the PointToClient with the right control :
Private Sub Panel1_MouseLeave(sender As Object, e As EventArgs) Handles Panel1.MouseLeave
If sender.ClientRectangle.Contains(Panel1.PointToClient(Control.MousePosition)) Then
For Each ctrl As Object In sender.controls
If ctrl.ClientRectangle.Contains(ctrl.PointToClient(Control.MousePosition)) Then Exit Sub
Next
If Not IsNothing(sender.BackgroundImage) Then sender.BackgroundImage = Nothing
End If
End Sub

.NET TrackBar MouseDown follow cursor?

I currently use this code to fix the bug where if you click somewhere on the Horizontal TrackBar it jumps to the middle then to the end of the TrackBar. So this code fixes that bug, which now jumps to the location you click.
But still a problem remains when I keep my mouse down and move it around the TrackBar the slider should follow but it just resets to beginning position, how do I make it follow right on top of cursor? would I need a timer control for that?
Private Sub tbTest_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles tbTest.MouseDown
Dim dblValue As Double
'Jump to the clicked location, bug FIX.
dblValue = (Convert.ToDouble(e.X) / Convert.ToDouble(tbTest.Width)) * (tbTest.Maximum - tbTest.Minimum)
tbTest.Value = Convert.ToInt32(dblValue)
End Sub
Make the method handle both the MouseDown() and MouseMove() events like this:
Private Sub tbTest_MovePointer(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles tbTest.MouseDown, tbTest.MouseMove
If e.Button = Windows.Forms.MouseButtons.Left Then
Dim dblValue As Double
'Jump to the clicked location, bug FIX.
dblValue = (Convert.ToDouble(e.X) / Convert.ToDouble(tbTest.Width)) * (tbTest.Maximum - tbTest.Minimum)
tbTest.Value = Convert.ToInt32(dblValue)
End If
End Sub
*Note the multiple events listed after the Handles keyword at the end of the first line. I also added a check to ensure the left mouse button is down.

Change Cursor as Feedback in DragDrop VB.NET 2010

Working on a DragDrop application. I have a class object (built as an object) which has a GroupBox that is enabled for DragDrop.
In the class I have set it up so that the cursor will change when it enters the groupbox, leaves the groupbox, mouse is down within the groupbox and drag/drop is working. I also set up a label in the class object and changed the text in that label as well. Basically, the text changes in the label as expected including 'FEEDBACK' appearing when I am dragging the object BUT the cursor stays stubbornly as a pointer. This is tghe state of affairs either when I debug the class or when, after I build the class, it is run as part of the main program.
Here are the subs set up in the class.
Private Sub GroupBoxSourceMouseDown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GroupBoxSource.MouseDown
GroupBoxSource.DoDragDrop(GroupBoxSource.Text, DragDropEffects.Copy)
lbl1.Text = "DOWN"
End Sub
Private Sub GroupBoxSourceMouseMove(ByVal sender As Object, ByVal e AsSystem.Windows.Forms.MouseEventArgs) Handles GroupBoxSource.MouseMove
If bolDragDropMouseDown Then
' Initiate dragging.
'GroupBoxSource.DoDragDrop(GroupBoxSource.Text, DragDropEffects.Copy)
End If
bolDragDropMouseDown = False
lbl1.Text = "MOVE"
End Sub
Private Sub GroupBoxSourceMouseEnter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GroupBoxSource.MouseEnter
Windows.Forms.Cursor.Current = Cursors.Hand
lbl1.Text = "ENTER"
End Sub
Private Sub GroupBoxSourceMouseLeave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GroupBoxSource.MouseLeave
Windows.Forms.Cursor.Current = Cursors.Arrow
lbl1.Text = "LEAVE"
End Sub
Private Sub GroupBoxSourceDragDropFeedback(ByVal sender As Object, ByVal e As GiveFeedbackEventArgs) Handles GroupBoxSource.GiveFeedback
Windows.Forms.Cursor.Current = Cursors.SizeAll
lbl1.Text = "FEEDBACK"
End Sub
Now for the unusual stage. I decided to change the cursor during FormLoad of the main program (which has the class object defined on the form) to a hand and nothing changed. In desperation I set up a 1mS timer and coded that to change the cursor to a hand and sure enough the cursor is now a hand but momentarity flicks back to a pointer when I move the cursor so it looks as if something else is causing the cursor to revert to its default value.
You have to set e.UseDefaultCursor = False in your GiveFeedback event handler to make your cursor change visible. Without it, drag and drop always uses the default cursors.
The cursor you get when the mouse hovers a control is set by the Control.Cursor property. Changing the Cursor.Current property has no effect, the property causes the cursor to change back instantly when you move the mouse.
To easily change the cursor, click on the form and bring up the properties. Then go to Cursor and change it to whatever you want.