Blue Link Developer
Guest
|
We have developed an add in using VS2015 add in express for MS Access application.
Everything runs fine EXCEPT one HUGE problem which can stop us from deploying the application with this add in as follows:
- when a user clicks on the custom addin navigation pane, any where on the pane that makes the pane get focus, when clicking back to an access application form the TAB and F keys do not work! If we open a modal form in Access then suddenly the TAB and F keys work again but as soon as the user clicks any where on the custom nav pane and then back to an application form the TAB and F keys are broken again.
One partial solution I have impemented is that when the user clicks on a node of the RadTreeView on the custom nav pane to open an access form I immediately do a "docmd.selectobject formname, true" and the form that was just openned gets proper focus such that the TAB and F keys work. This works for this one scenario of opening a form, but we also have a search text box on the nav pain and other quick search text boxes on our bottom nav pane such that if the user clicks inside the textbox and then clicks back to the access form the TAB and F keys are once again broken. I see no way of capturing when the user focus leaves the custom addin panes so I can do another selectobject etc... I cannot find a way to resolve this show stopper of a problem.
Any one else out there ever experience this? If so, was it resolved? How?
Thanks!!
Mike |
|
Andrei Smolin
Add-in Express team
Posts: 18821
Joined: 2006-05-11
|
Hello Mike,
In theory, this may relate to using a custom task pane (CTP) in Access but I seriously doubt it. Most probably, this relates to Telerik controls that you use. Could you please check if the issue occurs if you use standard controls supplied with Visual Studio? I'm pretty sure that Microsoft tested them on a CTP.
Andrei Smolin
Add-in Express Team Leader |
|
Blue Link Developer
Guest
|
I tried removing the telerik watermark textbox and replaced with plain Textbox using XAML/WPF and still experiencing the same issue. This was written usimng XAML/WPF/Telerik by a previous developer. See below view that I tested with. I removed the Telerik Presentation and Animation registries at the top, replaced the QuoteTextBox with a plain <Textbox> control, remarked out all the remaining Telerik Watermark Textbox controls and still experience the same issue when I click into the textbox and then back to the application form:
<UserControl x:Class="BottomBarView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:navigationAnimation="clr-namespace:Telerik.Windows.Controls.Animation;assembly=Telerik.Windows.Controls.Navigation"
xmlns:local="clr-namespace:BlueLinkAccessAddin"
mc:Ignorable="d" Height="25" Width="700">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/BlueLinkAccessAddin;component/ResourceDictionaries/GlobalResources.xaml" />
<ResourceDictionary Source="pack://application:,,,/BlueLinkAccessAddin;component/ResourceDictionaries/ApplicationStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid DataContext="{Binding Main, Source={StaticResource Locator}}" x:Name="LayoutGrid" Background="{Binding Stats.BackColor}" Margin="0,0,0,0">
<!-- Background="{Binding Stats.BackColor} -->
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*">
</ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Background="Transparent" Orientation="Horizontal" Height="25" VerticalAlignment="Center">
<Label FontWeight="Bold" FontSize="11" VerticalAlignment="Stretch" Background="White">Quick Find</Label>
<!-- Find Quote -->
<telerik:RadWatermarkTextBox x:Name="QuoteSearchTextbox" WatermarkContent="Quote#" Width="120" FontSize="12"
VerticalAlignment="Stretch" KeyUp="QuoteSearchTextbox_KeyUp" WatermarkBehavior="HideOnTextEntered" />
<!-- Find SO# -->
<telerik:RadWatermarkTextBox x:Name="SOSearchTextbox" WatermarkContent="SO#" Width="120" FontSize="12"
VerticalAlignment="Stretch" KeyUp="QuoteSearchTextbox_KeyUp" WatermarkBehavior="HideOnTextEntered" />
<!--Find Invoice#-->
<telerik:RadWatermarkTextBox x:Name="InvoiceSearchTextbox" WatermarkContent="Invoice#" Width="120" FontSize="12"
VerticalAlignment="Stretch" KeyUp="QuoteSearchTextbox_KeyUp" WatermarkBehavior="HideOnTextEntered" />
<!--Find PO-->
<telerik:RadWatermarkTextBox x:Name="POSearchTextbox" WatermarkContent="PO#" Width="120" FontSize="12"
VerticalAlignment="Stretch" KeyUp="QuoteSearchTextbox_KeyUp" WatermarkBehavior="HideOnTextEntered" />
<!--Find Individual-->
<telerik:RadWatermarkTextBox x:Name="IndividualSearchTextbox" WatermarkContent="Individual" Width="120" FontSize="12"
VerticalAlignment="Stretch" KeyUp="QuoteSearchTextbox_KeyUp" WatermarkBehavior="HideOnTextEntered" />
<!--Find Quote-->
<telerik:RadWatermarkTextBox x:Name="RMASearchTextbox" WatermarkContent="RMA#" Width="120" FontSize="12"
VerticalAlignment="Stretch" KeyUp="QuoteSearchTextbox_KeyUp" WatermarkBehavior="HideOnTextEntered" />
<!--Find Customer-->
<telerik:RadWatermarkTextBox x:Name="CustomerSearchTextbox" WatermarkContent="Customer" Width="120" FontSize="12"
VerticalAlignment="Stretch" KeyUp="QuoteSearchTextbox_KeyUp" WatermarkBehavior="HideOnTextEntered" />
<!--Find Customer PO#-->
<telerik:RadWatermarkTextBox x:Name="CustomerPOSearchTextbox" WatermarkContent="Customer PO#" Width="120" FontSize="12"
VerticalAlignment="Stretch" KeyUp="QuoteSearchTextbox_KeyUp" WatermarkBehavior="HideOnTextEntered" />
<!--Find Inventory-->
<telerik:RadWatermarkTextBox x:Name="InventorySearchTextbox" WatermarkContent="Inventory" Width="120" FontSize="12"
VerticalAlignment="Stretch" KeyUp="QuoteSearchTextbox_KeyUp" WatermarkBehavior="HideOnTextEntered" />
</StackPanel>
</Grid>
</UserControl>
Any other suggestions?
Thanks
Mike M. |
|
Andrei Smolin
Add-in Express team
Posts: 18821
Joined: 2006-05-11
|
Hello Mike,
You still use Telerik controls. In our practice many, many problems with panes (both Add-in Express panes and Microsoft CTPs) are caused by using non-standard controls; standard controls are supplied by Visual Studio. I suppose WPF itself is okay to use on the pane; I believe Microsoft has tested this scenario. The main suspect is Telerik controls.
Andrei Smolin
Add-in Express Team Leader |
|
Blue Link Developer
Guest
|
Thanks.
I removed all references to Telerik and converted all WPF Telerik controls to WPF controls... no change in behavior.
BUT, I did find the problem. The original author wrote a TaskPaneMaximizer class to "maximize" the nav panes so that there is no option for the user to close or move the pane... the pane control bar (at the very top) is hidden so the X to close or down arrow Icon to choose action on the pane is not present and the add in presents as we desire, locked in place with no option to move or close.
I kept the Telerik controls and once I commented out the instantiation of TaskPaneMaxmizer on each pane (we have 3 in total) we no longer experience the problem. We can freely click back and forth between the add in panes and the access application and never lose TAB or F keys.
Here is the vb class:
Imports PInvoke
Imports AddinExpress.MSO
Imports System.Text
Imports System.Windows.Forms
Imports Access = Microsoft.Office.Interop.Access
Public Class TaskPaneMaximizer
Implements IDisposable
Protected _paneInstance As ADXTaskPane.ADXCustomTaskPaneInstance
Protected _taskPaneControlHwnd As IntPtr
Protected _msoWorkPaneHwnd As IntPtr
Protected _nuiPaneHwnd As IntPtr
Protected _msoCommandBarHwnd As IntPtr
Protected _paddingRight As Integer = 0
Protected _paddingLeft As Integer = 0
Protected _paddingTop As Integer = 0
Protected _paddingBottom As Integer = 0
Private _msoWorkPaneSubclass As New FillParentSubclass
Private _nuiPaneSubclass As New FillParentSubclass
Private _msoCommandBarSubclass As ResizeChildrenSubclass
Private _timer As Timers.Timer
Private Class FillParentSubclass
Inherits NativeWindow
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WindowsInterop.WM_MOVE Then
m.LParam = 0
End If
If m.Msg <> 3328 Then
MyBase.WndProc(m)
End If
End Sub
End Class
Private Class ResizeChildrenSubclass
Inherits NativeWindow
Protected _msoCommandBarHwnd As IntPtr
Protected _msoWorkPaneHwnd As IntPtr
Protected _nuiPaneHwnd As IntPtr
Sub New(msoCommandBarHwnd As IntPtr, msoWorkPaneHwnd As IntPtr, nuiPaneHwnd As IntPtr)
_msoCommandBarHwnd = msoCommandBarHwnd
_msoWorkPaneHwnd = msoWorkPaneHwnd
_nuiPaneHwnd = nuiPaneHwnd
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WindowsInterop.WM_SIZE Then
SetSizing()
End If
MyBase.WndProc(m)
End Sub
Private Sub SetSizing()
Dim containerRect As RECT
WindowsInterop.GetClientRect(_msoCommandBarHwnd, containerRect)
User32.SetWindowPos(_msoWorkPaneHwnd, 0, 0, 0, containerRect.right - containerRect.left, containerRect.bottom - containerRect.top, User32.SetWindowPosFlags.SWP_NOACTIVATE Or User32.SetWindowPosFlags.SWP_SHOWWINDOW Or User32.SetWindowPosFlags.SWP_NOOWNERZORDER)
User32.SetWindowPos(_nuiPaneHwnd, 0, 0, 0, containerRect.right - containerRect.left, containerRect.bottom - containerRect.top, User32.SetWindowPosFlags.SWP_NOACTIVATE Or User32.SetWindowPosFlags.SWP_SHOWWINDOW Or User32.SetWindowPosFlags.SWP_NOOWNERZORDER)
End Sub
End Class
Public Sub New(paneInstance As ADXTaskPane.ADXCustomTaskPaneInstance, Optional paddingLeft As Integer = 0, Optional paddingTop As Integer = 0, Optional paddingRight As Integer = 0, Optional paddingBottom As Integer = 0)
_paneInstance = paneInstance
_paddingRight = paddingRight
_paddingLeft = paddingLeft
_paddingTop = paddingTop
_paddingBottom = paddingBottom
_taskPaneControlHwnd = DirectCast(_paneInstance.Control, Control).Handle
Initialize()
_timer = New Timers.Timer(50)
_timer.AutoReset = False
AddHandler _timer.Elapsed, Sub()
If Not _isInitialized Then
Initialize()
End If
SetSizing()
_timer.Start()
End Sub
SetSizing()
_timer.Start()
End Sub
Private _isInitialized As Boolean
Private Sub Initialize()
_msoCommandBarHwnd = FindAncester(_taskPaneControlHwnd, "MsoCommandBar")
If _msoCommandBarHwnd = 0 Then Exit Sub
_msoWorkPaneHwnd = FindAncester(_taskPaneControlHwnd, "MsoWorkPane")
If _msoWorkPaneHwnd = 0 Then Exit Sub
_nuiPaneHwnd = FindAncester(_taskPaneControlHwnd, "NUIPane")
If _nuiPaneHwnd = 0 Then Exit Sub
_msoCommandBarSubclass = New ResizeChildrenSubclass(_msoCommandBarHwnd, _msoWorkPaneHwnd, _nuiPaneHwnd)
AttachHandlers()
_isInitialized = True
End Sub
Private Function FindAncester(startHWnd As IntPtr, className As String) As IntPtr
Dim result As IntPtr = IntPtr.Zero
Dim currentHwnd As IntPtr
currentHwnd = startHWnd
While currentHwnd <> IntPtr.Zero
currentHwnd = User32.GetAncestor(currentHwnd, User32.GetAncestorFlags.GA_PARENT)
Dim currentClassName As New StringBuilder(256)
If WindowsInterop.GetClassName(currentHwnd, currentClassName, currentClassName.Capacity) > 0 Then
If currentClassName.ToString = className Then
result = currentHwnd
Exit While
End If
End If
End While
Return result
End Function
Private Sub SetSizing()
Dim containerRect As RECT
If WindowsInterop.GetClientRect(_msoCommandBarHwnd, containerRect) = 0 Then
_isInitialized = False
Exit Sub
End If
Dim left As Integer = _paddingLeft
Dim top As Integer = _paddingTop
Dim width As Integer = containerRect.right - containerRect.left - _paddingLeft - _paddingRight
Dim height As Integer = containerRect.bottom - containerRect.top - _paddingTop - _paddingBottom
User32.SetWindowPos(_msoWorkPaneHwnd, 0, left, top, width, height, User32.SetWindowPosFlags.SWP_NOACTIVATE Or User32.SetWindowPosFlags.SWP_SHOWWINDOW Or User32.SetWindowPosFlags.SWP_NOOWNERZORDER)
User32.SetWindowPos(_nuiPaneHwnd, 0, left, top, width, height, User32.SetWindowPosFlags.SWP_NOACTIVATE Or User32.SetWindowPosFlags.SWP_SHOWWINDOW Or User32.SetWindowPosFlags.SWP_NOOWNERZORDER)
End Sub
End Class
Once I remove the following code from the Addin module:
_topNavMaximizer = New TaskPaneMaximizer(TopBarTaskPane.Item(HostApplication))
_leftNavMaximizer = New TaskPaneMaximizer(SideNavTaskPane.Item(HostApplication), , , 1)
_bottomBarMaximizer = New TaskPaneMaximizer(BottomBarTaskPane.Item(HostApplication))
... we no longer experience the issue.
I did try removing the timer(50) object/instance and that did resolve the issue EXCEPT for the left nav pane, it continues to display the same issue. Also the nav panes would restore/maximize upon specific mouse click combos etc... not a good solution. Removing the use alltogether solves it all.
Question:
Is there any other way to lock the custom nav pane in place and not allow the user to close or move the nav pane? We also would like the X close option and top-bar where the user can click to grab and move.... hidden. That is what the above code achieved buit at the cost of losing our TAB and F key functionality when we click in the nav pane and back to the access app.
Thanks so much for your help.
Mike Margulies |
|
Andrei Smolin
Add-in Express team
Posts: 18821
Joined: 2006-05-11
|
|