How to get noticed when ScrollBar is appeared on Panel? VB.Net - vb.net

I just want to resize a certain Control in a Panel at the certain point when the vertical ScrollBar of the Panel is appeared due to need of scrolling.
Panel.Resize or Panel.SizeChanged is not exactly what I wanted because it is called whenever the size of the Panel is changed rather than exact point when the inside of the Panel size is changed due to the Panel get a ScrollBar width.

The ClientSizeChanged event will fire. You could detect that the scrollbar became visible with code like this:
Private Sub Panel1_ClientSizeChanged(sender As Object, e As EventArgs) Handles Panel1.ClientSizeChanged
If Panel1.VerticalScroll.Visible Then
'' etc...
End If
End Sub
Beware that the event will fire multiple times. If you do anything to rearrange controls to make the scrollbar invisible again then beware that you'll induce a good deal of highly visible flicker.
Since there normally isn't anything that the user could do to resize controls, only your code does that, the much better alternative is to actively prevent the scrollbar from showing in the first place.

Related

Windows Forms DataGridView view gets distorted when scrolling across the fields

Good Day,
I am facing this issue in one of the VB .Net app I have. I am populating a datagridview. When scrolling the view to left or right to see other columns, the view appears bit distorted or broken. See attached image. Wondering if there's any fix to prevent this?
The rendering problem can be solved by invoking a Refresh() on the grid handling the Scroll event:
Private Sub DataGridView1_Scroll(sender As Object, e As ScrollEventArgs) Handles DataGridView1.Scroll
DataGridView1.Refresh()
End Sub
To avoid flickering when scrolling, I thought it was enough to do a type check
If e.Type = ScrollEventType.EndScroll Then DataGridView1.Refresh()
However, it seems that the EndScroll Type is never assigned due to a bug: DataGridView Scroll event (and ScrollEventType.EndScroll)
Anyway, there is a solution to this problem.
You can directly handle scrollbar events to get the correct ScrollEventType: How can I receive the "scroll box" type scroll events from a DataGridView?

How to avoid gridview mouse leave event when clicking on vertical scrollbar?

I have a form with a floating gridview that must appear when filling a textbox or clicking on a button. If item selected or mouse leaving grid, grid becomes invisible so user can see rest of the form. Grid data most cases exceed maximum vertical size, so a vertical scrollbar is needed. My problem is that when mousing to vertical scrollbar triggers MouseLeave event, so grid becomes invisible.
This time I think it's not a code matter, so is there some property to change to make the program identify vscrollbar as part of the GridView? Or else is there some code solution to ignore MouseLeave event when mousing to scrollbar?
Here is my event code, pretty simple:
Private Sub GridCliente_MouseLeave(sender As Object, e As System.EventArgs) Handles GridCliente.MouseLeave
GridCliente.Visible = False
End Sub
Also, I'm using Component One C1TrueDBGrid instead of standard gridview. It may be important.
I found a solution to my problem by adding the GridView to a panel and changing the MouseLeaveevent to the panel. For this to work, the panel must exceed the GridView size at least one pixel each side, since MouseLeave will not trigger if GridView is the same size of the panel (you must mouse over the panel and not any other component inside it to have vb.net consider mouse inside panel). Maybe it's not the best solution but it works for me.

Vertical & Horizontal scrollbars in a panel

Scenario:
Put a panel on a form.
Set the panel's BorderStyle to FixedSingle. (Just so you can see it when you run it.)
Set the panel's AutoScroll=True
Set the panel's Anchor to Top, Left, Bottom, Right
Inside the panel, place any sizable control (button, picturebox or whatever).
Adjust the control's bottom edge to be just a few pixels above the bottom of the panel.
Adjust the control's right edge should be a few pixels more narrow than the panel MINUS the width of a vertical scrollbar. (That is, it should be just narrow enough to leave room for a vertical scrollbar to may appear.)
Now run it, and vertically resize the form a little shorter so that you'd expect a VERTICAL scrollbar to appear.
Problem: BOTH scrollbars appear, because the very existence of the vertical scrollbar reduces the width of the client area, thus forcing a horizontal scrollbar to appear.
Apparently .NET evaluates whether a vertical scrollbar is necessary first, then evaluates whether the horizontal should appear, which is dependent upon whether the client size is reduced by the presence of a vertical scxrollbar. (i.e. the same experiment doesn't cause unnecessary VERTICAL scrollbars to appear... only horizontal ones.)
I'm using VB2008 Express but I'm guessing this carries over to later versions.
THE SOLUTION I NEED: I need either of: A) A "vertical autoscroll only" panel. B) I need a way to tell the panel to "rethink" whether the horizontal scrollbar is actually necessary. (Refreshes don't seem to do it.)
In order to use panel autoscroll property I do that:
panel.AutoScroll = False (is inverse I know :D)
panel.VerticalScroll.Visible = False or panel.HorizontalScroll.Visible = False
In order to know the dimensions of the scroolbars use
SystemInformation.HorizontalScrollBarHeight
SystemInformation.VerticalScrollBarWidth
So you can change the dimension of the panel when the scroolbar is shown.
The AutoScroll property does not allow you to have too much control on the scrollbars (even though you have VerticalScroll and HorizontalScroll properties).
Out of the proposed alternatives, I go for option A; the marked answer in this post gives a quite effective solution to an equivalent problem. Converted & adapted code (where Panel1 is the panel referred in your question):
Private Declare Function ShowScrollBar Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal wBar As Integer, ByVal bShow As Boolean) As Boolean
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Try
ShowScrollBar(Panel1.Handle, 0, False)
Catch ex As Exception
End Try
MyBase.WndProc(m)
End Sub
If you set the AutoScroll property of your panel to true and add this code, you would get what you are looking for.
NOTE: the proposed code works but at certain price: I personally intend to avoid Protected Overrides Sub WndProc codes as much as possible. If getting exactly this functionality is important for you, rely on the proposed methodology; otherwise, you might have to consider other alternatives (e.g., AutoScroll = False and adding a VScrollBar to the panel, which will always be there).
I ran into something that sounds like what you describe. I wanted just a Vertical scroll because it was going to contain many many things eventually, but not a Horizontal scroll. I used a table layout panel; set the Panel's Vertical size so that the VScroll shows; set the width to accommodate what will go in there plus whatever margin or gutter your code will use.
Then, in the TableLayoutPanel set the width of the scrolling panel's to absolute (I used 2 pixels more than the panel.width). If/when the user resizes, all the extra size gets distributed to everything else. Basically dont let the scrolling panel's width change. Might have to/want to set a minimum form size too.
The things I was adding were all the same width, if yours vary, you might have to set it to accommodate the widest.
Not sure if you are encountering the same thing, but sure sounds like it.

Is it possible to disable horizontal scrolling alone in listview?

Basically, I'm just wondering whether it's possible to disable horizontal scrolling while leaving vertical scrolling enabled with a listview in VB.NET without having to make a new class for it.
Why? Well, purely aesthetic, my listview currently has a tiny bit of horizontal scroll in it, which doesn't make it worth the effort to make a new class just for that, although if it can be coded without too much effort, I'd be more than willing to do that.
PS: I'm working in Windows Forms
I often use ListView controls in Details view with a single column in order to provide a list with drag-and-drop functionality, which is lacking in the ListBox control. ListView works beautifully for this apart from its annoying habit of wanting to scroll horizontally. It's possible to get around this to a degree by setting the column width to a suitable value (typically 4 less than the ListView's width) but this won't render well if the look-and-feel changes and will fail completely if the control decides to add a vertical scrollbar at run-time.
The workaround I use (and I'll admit it doesn't cope with every situation) is this. First, configure a ListView with a single column (the name is arbitrary) and hide its header:
lvList.View = View.Details
lvList.FullRowSelect = True
lvList.Columns.Add("ColName")
lvList.Columns(0).Width = lvList.ClientSize.Width
lvList.HeaderStyle = ColumnHeaderStyle.None
Then handle the ListView's ClientSizeChanged event and use it to set the width of the column to the width of the client area (which is essentially the area the list body has to fill):
Private Sub lvList_ClientSizeChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles lvList.ClientSizeChanged
If lvList.Columns.Count > 0 Then
lvList.Columns(0).Width = lvList.ClientSize.Width
End If
End Sub
As the list contents change and the vertical scrollbar is added or removed, the ClientSizeChange event is fired and adjusts the width of the column so that it exactly fills the client area.

How can I show scrollbars on a PictureBox control?

Sometimes, I have a picturebox lets say 100x100. But the image it will display is actually 100x400.
I don't want to increase the size of the picturebox itself. Instead, I would like to create a vertical scrollbar (or horizontal if needed).
I could not find a scrollbar in the toolbox, so I guess I have to code it. But, how?
And I still wonder if I didn't make a mistake and didn't see the scrollbar in the toolbox. My apologies then :(
I suppose you could add separate scrollbar controls and sync their Scroll events up with the offset at which the picture in the PictureBox is drawn, but that sounds like actual work. There's a better way.
Add a Panel control to your form, and set its AutoScroll property to "True". This will cause the control to automatically show scrollbars when it contains content that lies outside of its currently visible bounds. The .NET Framework will take care of everything for you under the covers, without you having to write a single line of code.
Drag and drop your PictureBox control inside of the Panel control that you just added. The Panel control will then detect that one of its child controls is larger than its visible area and show scrollbars, thanks to the AutoScroll property. When the user moves the scrollbars, the portion of the image in your PictureBox that is visible will be automatically adjusted. Magic.
(The reason you have to use a Panel control as a container is because PictureBox does not inherit directly from the ScrollableControl base class, which is what provides the AutoScroll property.)
I tried this and it worked well. But I noted that if the picturebox is docked in the panel, the picturebox is automatically set to the size of the parent panel, and can't be set larger (at least not in any way I could find). This defeats the purpose of the technique. So -- put the picturebox on the panel, but don't dock it, and it will work perfectly.
There are no automatic scroll bars on a picture box, but you can add the VScrollBar (and HScrollBar) control to the form and handle the image scrolling manually by redrawing it at a different offset each time the Scroll event is fired.