在MS Access中使用.Net用户控件

5
可以使用Interop工具包或简单的ActiveX创建.Net用户控件,以通过COM在VB6/MS Access表单上使用,但需要注意一个主要问题:调整大小
在运行时无法调整表单上的控件大小。 将控件对齐到表单的相反侧会使它在每次调整表单大小时增长,即使你缩小表单也是如此...
似乎没有任何方法可以控制这种行为:
- 从 .Net,通过代码尝试调整UserControl的大小会失败。 - 从 MS Access,用户控件也不能通过代码调整大小。
显然,一种解决方案可能是将 .Net UserControl 包装在 VB6 UserControl 中。 不幸的是,除了使用另一个包装器和更多的特定代码之外,VB6 IDE已不再可用...
有没有办法解决这个问题?
3个回答

3
解决这个问题比预期的更加复杂。每次你认为你找到了一个解决方案,它就从你手中溜走...
在VB MSDN论坛上有一个简单的解决方案记录在案:Interop UserControl in MSAccess。虽不完美,但比我发现的那个更简单。
主要问题是Access擦除了控件外的区域。如果控件固定在右边和底部边缘,则没有问题;否则,可以将该控件用作子窗体或选项卡控件页面中的容器,并隐藏选项卡以使其起作用。

你为什么认为需要这样做呢?这似乎过于复杂,而且可能不稳定/不可靠。如果你必须在Access中构建前端,请使用Access提供的控件来构建,并学会接受Access的限制。如果你这样做,你将少很多白发! - David-W-Fenton
2
.Net 与 Access 的互操作性在所有领域中表现都相当不错,除了这个奇怪的问题。 - Renaud Bompuis
6
尊敬的David,希望你能理解,想要通过将现有应用程序逐步替换为可在访问应用程序和.Net版本中使用的.Net用户控件来将其迁移到.Net是合理的。这样可以使我们在不必扩展和维护两套实现的情况下处理应用程序。Access并不适合所有应用程序类型,对于这种情况,将前端代码简化并移至更丰富的环境中可以更好地发挥其作用。 - Renaud Bompuis

3

我不确定为什么MS Access和VB6的行为不同,但我发现使用C#中的.Net Interop可以找到一种有效的解决方案。 对于VB.Net,它也应该适用。

  1. Extend the IInteropUserControl interface with the following entry:

    void ResizeThis(int width, int height);

  2. Implement the ResizeThis function:

    public void ResizeThis(int width, int height)
    {
        this.UpdateBounds(Left, Top, width, height);
        this.SetBounds(0, 0, width + 1, height + 1, BoundsSpecified.Width | BoundsSpecified.Height);
    }
    
  3. In MS Access call the ResizeThis function with the appropriate width and height parameters.

  4. There is another strange behaviour. On each record movement in the Access form the UserControl shrinks by some pixels. I have solved this issue by overriding the SetBoundsCore function and implementing a property LockResizing. This property will assigned true, when the UserControl should not be resized.

    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
    {
        if (_LockResizing)
            throw new Exception();
    
        base.SetBoundsCore(x, y, width, height, specified);
    }
    
    public bool LockResizing
    {
        get { return _LockResizing; }
        set { _LockResizing = value; }
    }
    
已在MS Access 2010和2016(Office 365)中进行了测试。

2

虽然这是一个旧话题,但我有一个看起来正在运作的想法/解决方案。

在 .net com 控件内部

Private _ForceWidth As Integer = 0
Private _ForceHeight As Integer = 0

Public Property ForceWidth As Integer
    Get
        Return _ForceWidth
    End Get
    Set(value As Integer)
        _ForceWidth = value
    End Set
End Property


Public Property ForceHeight As Integer
    Get
        Return _ForceHeight
    End Get
    Set(value As Integer)
        _ForceHeight = value
    End Set
End Property



Private Sub MyControl_Resize(sender As Object, e As EventArgs) Handles MyBase.Resize
    If ForceWidth > 0 Then
        Me.Width = ForceWidth
    End If
    If ForceHeight > 0 Then
        Me.Height = ForceHeight
    End If
End Sub

在Access表单中

Private Sub Form_Current()
    MyControl1.ForceWidth = 800
    MyControl1.ForceHeight = 600
    MyControl1.Width = SignatureControl6.Width - 1   'force sending resize message
End Sub

仍处于测试阶段,但看起来可能会起作用。


感谢您对这个话题的贡献。请回来分享您的结果,即使它们不起作用,也可能会激发其他人得出可行的解决方案! - Renaud Bompuis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接