Addin for MS Access 2016

Add-in Express™ Support Service
That's what is more important than anything else

Addin for MS Access 2016
ApplicationTAB and F keys swallowed by add in 
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
Posted 21 Jul, 2017 16:11:22 Top
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
Posted 24 Jul, 2017 03:48:58 Top
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.
Posted 24 Jul, 2017 14:08:59 Top
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
Posted 25 Jul, 2017 03:56:33 Top
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
Posted 26 Jul, 2017 15:40:34 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Hello Mike,

Blue Link Developer writes:
If m.Msg = WindowsInterop.WM_MOVE Then


You should use the Office.CustomTaskPane.DockPositionRestrict property instead; see https://msdn.microsoft.com/en-us/vba/office-shared-vba/articles/customtaskpane-dockpositionrestrict-property-office.

Blue Link Developer writes:
If m.Msg = WindowsInterop.WM_SIZE Then


You should handle the WM_WINDOWPOSCHANGING message instead; see https://msdn.microsoft.com/en-us/library/windows/desktop/ms632653(v=vs.85).aspx.

Blue Link Developer writes:
We also would like the X close option and top-bar where the user can click to grab and move.... hidden.


This isn't that simple as there are several related areas that the solution must comply with. I suggest that you discuss your requirements with our guys managing custom development services at https://www.add-in-express.com/custom-development/index.php.


Andrei Smolin
Add-in Express Team Leader
Posted 27 Jul, 2017 06:19:50 Top