ActiveControl is hidden - vb.net

To boil the situation down, I have a panel with 3 textboxes on it. When I hide the panel, the first textbox in the tab order for the panel gets assigned to Me.ActiveControl (The form), regardless of which one was focused when the panel was hidden.
I thought a hidden control could never have focus. I have other controls on my form where the issue was originally found, so I thought it would have to choose a non hidden control to focus on. Is this a bug, or designed this way?
I use a timer on my simple form that fires every 5 seconds, recording the active control name in a label.

I have been able to recreate your scenario and it revealed an interesting possibility (more on this later).
WinForms has the concept of the Selected (or activated) control. The Control.Select Method is related to the Control.Focus Method. The Focus Method-Remarks section documentation is relevant.
A control can be selected and receive input focus if all the following
are true: the Selectable value of ControlStyles is set to true, it is
contained in another control, and all its parent controls are both
visible and enabled.
...
Focus is a low-level method intended primarily for custom control
authors. Instead, application programmers should use the Select method
or the ActiveControl property for child controls, or the Activate
method for forms.
The ContainerControl.ActiveControl Property points to the last selected control.
The reason that the first control by tab order in the Panel is selected is due to the code that executes when the Panel.Visible property is set to false. The Visible Property setter calls SetVisibleCore that in turn calls SelectNextIfFocused that calls SelectNextControlInternal that finally calls Control.SelectNextControl that selects the your TextBox1.
This is where it gets interesting. At this point the Panel and TextBox are both visible. Therefore, the TextBox receives focus and retains it when the Panel is hidden. This condition allows for a hidden TextBox to have keyboard input and no rules about a hidden control not being able to receive focus are violated.

Related

Can we keep the Form scrollbar but prevent the form from auto-scrolling to the focused control?

I want to prevent my form from automatically scrolling when a control at the bottom is focused but still keep the scrollbars if they ever appear.
Since some users have a slightly lower screen's resolution than the form, the scrollbars do sometimes appear. This created a problem with some DataGridView. Since the AutoScroll option is enabled, when clicking the DataGridView, it does a multiselect since we click and it moves.
When I disable the AutoScroll property, the scrollbars go away. Therefore, the user can't see everything.
Is there a way to disable the AutoScroll, but still keep the scrollbar?
If I understand your situation correctly, you basically want the user to have the ability to scroll the form manually but prevent the form from scrolling automatically to the control that gets focused.
Put this code in your form:
Protected Overrides Function ScrollToControl(activeControl As Control) As Point
'Return MyBase.ScrollToControl(activeControl) ' <-- Keep this line commented.
End Function
Result:

panel autoscroll turns off when switching between windows

I created an interface it has several forms you can switch between using a panel as the parent form. My problem is that when i switch between my forms on the second time i open a form if that form has autoscroll on a panel it will not allow you to scroll and the window is stuck on the view you previously had.
In this image i open the form internet. after doing so i will click on instruction( any form switch triggers this)
now i open the same form again and the scroll bar is gone and it locks in on the last position the form was in.
the very curious thing in this is that this only happens on the internet form word also has a scroll bar however even though the properties and settings for both are identical only one does not work.
What could be causing this and how do i go about troubleshooting errors like this.
The forms are removed from the panel and re-added, they are not closed.
Assumption 0:
The forms are removed from the panel and re-added, they are not
closed.
Store the state of panel autoscroll and set it after you have re-added it. Note that if you add controls to the panel first and panel is not docked, then scroll will not appear because panel dimensions can be huge. You should set following property as well:
vScrollBar1.Vericalscroll.Value = 0
Assumption 1:
I assume what is actually going on is that you do not add controls to that panel, but to the form behind it or something similar. In that case - program is correct, you just asked it to do a wrong thing.
Assumption 2:
Assuming is panel is anchored top, left, bottom, right. There is currently a limitation in Windows Forms that prevents all classes derived from ScrollableControl from acting properly when both RightToLeft is enabled and AutoScroll is set to True.
Manual : link
Assumption 3:
You add the controls back, by recreating them, but forget to add handlers or create them in order where scrollbar is out of view. Instead of absolute positions you could use dockstyle:
Dim vScrollBar1 As VScrollBar = New VScrollBar
vScrollBar1.Dock = DockStyle.Right
Controls.Add(vScrollBar1)

Don't autoscroll on button click

I am working on an application that works as a dashboard. The form includes a flowlayoutpanel that contains several datagridviews. The flowlayoutpanel is set to autoscroll because there are usually more datagrids than will fit on the visible page. Each datagrid has a buttonclick event that opens a chart form when a particular column (3) is selected. All of the chart functionality works fine. The problem I'm having is that when I click a datagrid that is only partially visible, the page scrolls to bring that datagridview completely onto the page. Because that happens on the click (MouseDown), the page scrolls so quickly that it doesn't actually trigger the clickevent, but selects several cells in the column, as if the user did a click/drag down the column.
What I would like to have happen is when the user clicks on a datagridview that is only partially visible, the chart would open, then the page would scroll on the chart close event. That actually happens if the datagridview in question has focus, but is partially off the page. For example, if I selet the datagridview, then scroll down/up until it is partially off the visible page, then click a cell in column 3. It will display the chart, then autoscroll when I close the chart. But if the datagridview does not have focus, it does the autoscroll thing. I have tried putting the flowlayoutpanel inside another panel, and that worked to some degree, but it was inconsistent.
Sorry for the long description, but I'm trying to be as detailed as possible. Any help would be greatly appreciated. The application is being built in .NET, using VS 2013.
This seems similar to a issue I had with multiple datagridviews inside a panel, this article was the solution for me.
In short, all you need to do is create a custom panel and override the ScrollToControl method. I belive you can do the same with a FlowLayoutPanel.
EDIT:
Your CustomPanel class should look something like this (code converted with developer fusion
Public Class CustomPanel
Inherits System.Windows.Forms.FlowLayoutPanel
Protected Overrides Function ScrollToControl(activeControl As System.Windows.Forms.Control) As System.Drawing.Point
' Returning the current location prevents the panel from
' scrolling to the active control when the panel loses and regains focus
Return Me.DisplayRectangle.Location
End Function
End Class
If this doesn't work you could try inheriting a regular Panel and place a FlowLayoutPanel inside it.

Slow label and picturebox event firing which are child of Button

i have developed custom control which inherits Button control, actually i`m creating button with one picturebox and label on Button(picturebox and label are child controls). I created same method and wired child controls to behave as clicking on parent(Button), it works but its slow no mather what i do(tried with InvokeOnClick, me.performclick, Me.OnClick(New EventArgs()), tried with same method for all events), but clicking on label or picture box is slow, i need it to be fast as clicking directly on button cause in my application is very important to be able to click on button twice in second for example, if you click on label or picturebox twice at second it will fire just one time not 2.
What i have been thinking of is to make label and picturebox invisible for event is it possible or anyother idea ?
Thanks in forward
You are doing battle with ControlStyles.StandardDoubleClick. Which is turned on for the PictureBox and Label controls but turned off for Button.
So when you are clicking rapidly on either the picturebox or the label then they'll generate the DoubleClick event instead of the Click event. You'll interpret that as "slow" since you probably didn't write a handler for that event. Subscribing the event and calling Me.OnClick is a workaround.
Just don't do this. PictureBox and Label are point-and-click convenience controls but they are extraordinarily wasteful. It takes just two lines of code in the button's OnPaint() method override to get the exact same outcome, minus the overhead and the event problems. Use e.Graphics.DrawImage() to draw the pb's image and TextRenderer.DrawText() to draw the label's text.
Using MouseDown event ensures the event is triggered once per click, regardless of click/doubleclick.

VB.NET MDI Children Focus only on Title Bar Click

One would imagine that clicking anywhere within the MDI Child form (or on any control) will focus that form. But in my application I can only focus a MDI child by clicking on its titlebar, which is an abnormal behavior on the part of the user. My forms are filled with either controls or panels so I don't have the luxury of just "clicking on the form." But clicking anywhere within it should focus it.
I haven't been able to find a solution to this problem although it seems others are having it as well.
I figured it out. If you are setting the child form mdiParent property after you are calling Form.Show then it messes up the focus of all the child forms.
When I set mdiParent property of the form first and then call .Show(), everything works perfectly as expected.