By Charles R Hankey - 6/4/2010
Ivan suggested code for the form.processcmdkey() which worked as far as getting out of a grid with Ctrl TAB but it was a mystery as to just where focus went after that. It left the groupbox holding the grid but then ...?
The problem became apparent when i realized he was calling the form's selectNextControl which uses the form TabOrder not the TabOrderController tab order. So I made a modification, adding a property my form baseclass which held a reference to the TabOrderController.
That's when I found out me.ActiveControl in a SF Maintenance form always returns ToolstripContainer1
Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, _
ByVal keyData As System.Windows.Forms.Keys) As Boolean
' Just break here and you'll see me.Activecontrol isn't the grid or groupbox or whatever you think it is
' so this code just sends the focus to whatever is next in the tab order after ToolstripContainer1
Select Case keyData
Case Keys.Control Or Keys.Tab
'-- created to be able to tab out of a Grid control
Me.SelectNextControl(Me.ActiveControl, True, True, True, True)
Case Keys.Control Or Keys.Shift Or Keys.Tab
Me.SelectNextControl(Me.ActiveControl, False, True, True, True)
End Select
'This code - orginally before the block above, blows up since GetNextFocusableControl
'does not see ToolstripContainer in its dictionary
'' If Not Me.TOC() Is Nothing Then
'Select Case keyData
' Case Keys.Control Or Keys.Tab
' '-- created to be able to tab out of a Grid control
' Me.TOC.GetNextFocusableControl(Me.ActiveControl).Focus()
' Case Keys.Control Or Keys.Shift Or Keys.Tab
' Me.TOC.GetPreviousFocusableControl(Me.ActiveControl).Focus()
' Return True
' End Select
'end if
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
So far I cannot find a way to determine - at the form level - what control really has focus.
Suggestions welcome.
This does explain why I needed to tell the groupbox in leave where to set the focus. Seems if I"m going to do that I might want to just raise the Leave event of the containng goupbox in response to the Ctrl-Tab ( then we also get into the question of how the leave of the groupbox knows what the last keypress was - i.e. ctrl-Tab or ctrl-Shift-Tab)
Have learned a lot along the way. Very surprised to find there is no generic way to find a TabOrderController on a form, though I settled on creating a property of that type in the baseform as was pleased to see the property become a cbo picker, just as Greg suggested on picking a control for the groupbox exit.
So, does anyone know :
- How to find the real activecontrol (from the form level)
- How to find a tabcontroller in a form baseclass
- How to determine the last key pressed in the Leave of a Groupbox
TIA
|
By Ivan George Borges - 6/7/2010
Hiya.That worked on that form because it didn't have a ToolStripContainer. Have you tried using ToolStripContainer1.ActiveControl?
|
By Ivan George Borges - 6/7/2010
Right, this could be a more generic approach: Dim activeControl as Control = Me.ActiveControl While TypeOf activeControl Is IContainerControl activeControl = DirectCast(activeControl, IContainerControl).ActiveControl End While Me.SelectNextControl(activeControl, True, True, True, True)
|
By Charles R Hankey - 6/7/2010
Very cool. Thanks Ivan.
Regarding finding the tabordercontroller : Here is where I am confused. In the designer of the form it appears that each component is being added to the Me.Components collection, but at run time Me.components and me.component.components appears to have nothing.
Since a TabOrderController ( or for that matter a businessobject, tooltip compenent etc ) is not in the controls collection, is there some kind of exposed collection we can use at the form level to find a component the way we would find a control?
I think it is there but it isn't exposed. Is this something that would have to be changed at the framework level if we wanted to be able to walk through the components of a form at run time?
|
By Ivan George Borges - 6/7/2010
Oh, OK. Sorry Charles...Try this if you want to iterate through the components: For Each iComp As System.ComponentModel.IComponent In Me.components.Components MessageBox.Show(iComp.ToString) Next
|
By Charles R Hankey - 6/7/2010
Interesting. I actually tried code just like this - but I put it in the base form
If you put it there, at run-time there is nothing in me.components.components.
But if you put it in the form itself, everything works the way I thought it should.
I feel like I should understand why that is true, but I don't. It would seem that once the code from the base class is called, a reference to me.components.components should get the same results as it does if the code is in the running form.
Anyway, thank you for your patience. This has been a real adventure
|
By Ivan George Borges - 6/7/2010
Would it be because the components container is private to the class, whichever it is?
|
By Greg McGuffey - 6/7/2010
How to find a tabcontroller in a form baseclass
Take a look at the access modifier on the components object in the designer form. It is private. This means that when on the base form, it access the base form's components. When on the inherited form, it access the inherited form's components. When you drop components on the form it gets added to the top level form (the inherited form), therefore, code like Ivan provided will only show components dropped on the base form directly, and none of the components on your inherited form.
To make this generic, in the base form, create a protected method and pass it the IContainer:
//-- In base form...
Protected Sub ShowComponents(container As IContainer)
For Each iComp As System.ComponentModel.IComponent In container.Components
MessageBox.Show(iComp.ToString)
Next
End Sub
A couple of things to note. First, this shows components. I.e. objects that are added to the components collection. This means that controls aren't in this collection (they are in the controls collection and the controls collection will work across base/inherited objects...i.e. if you drop a button on the base class, it can be accessed via the inherited form's Controls collection). Also, if you look at the code that sets up the TabController, it is neither added to the Controls collection nor to the components collection. It is just a class sitting out there in the form. So this won't work to discover if it exists on a form. You'll need to manually identify the controller as needed. You could add a property to your base form of type TabController to make this available to all inherited forms and to easily allow for base form code to work with it.
So the answer is that the way you're doing it via property is currently the best way to get this done.
|
|