我有一个带一个按钮的子窗体,可以打开另一个窗体。
在辅助表格上,用户可以选择一个地址。
所选地址应应用于呼叫表单。
打开子窗体时,我通过了窗口句柄。
但是,当它尝试在Forms集合中查找调用表单时,它不存在。
我怀疑这是因为调用表单实际上是子表单。
我不知道从这里去哪里。
调用表单,传递Windows句柄
OpenCCCustAddr [CustFID], "CCInt", Me.hWnd
在Form Close事件中,我尝试在调用表单上设置地址值,但GetFormByHWND返回null。
Set frm = GetFormByHWND(Me!txtCallingHWND)
// Me!txtCallingHWND here is populated and looks reasonable
frm!BillStreet = strAddr // This blows up since frm is null
frm!HolderZipCode = strZip
frm!AddressUpdated = -1
Set frm = Nothing
Public Function GetFormByHWND(lngHWND As Long) As Form
Dim frm As Form
Dim nm As String
Select Case lngHWND
Case 0
Case Else
For Each frm In Forms
nm = frm.NAME // the name of the parent form shows, but not my calling subform
If frm.hWnd = lngHWND Then
Set GetFormByHWND = frm
Exit For
End If
Next
End Select
End Function
对于For Each和For I = 0到Count-1都给出相同的结果。表单不在表单中。可能是因为它是子窗体。
我尝试搜索子表单,但是当我使用“对象不支持此属性”检查ctl.hWnd时,此操作会爆炸
Public Function GetFormByHWND(lngHWND As Long) As Form
Dim frm As Form
Dim ctl As Access.Control
Dim nm As String
Select Case lngHWND
Case 0
Case Else
For Each frm In Forms
nm = frm.NAME
If frm.hWnd = lngHWND Then
Set GetFormByHWND = frm
Exit For
End If
Next
Rem If we didn't find the form, check for a subform
If GetFormByHWND Is Nothing Then
For Each frm In Forms
nm = frm.NAME
For Each ctl In frm.Controls
If ctl.Properties("ControlType") = acSubform Then
nm = ctl.NAME
If ctl.hWnd = lngHWND Then // Error: "Object doesn't support this property"
Set GetFormByHWND = ctl
Exit For
End If
End If
Next
Next
End If
End Select
End Function
首先,根本不清楚为什么需要所有这些代码和拥有的东西?
我们假设您有一个表格。
在该表单上,您有一个按钮,它会启动第二个表单。
因此,在第一种形式中,我们有:
' write data to table before launching form
If Me.Dirty = True Then Me.Dirty = False
DoCmd.OpenForm "formB"
好的,现在在formB加载事件中,我们有以下内容:
Option Compare Database
Option Explicit
Dim frmPrevious As Form
Dim frmPreviousSub As Form
Private Sub Form_Load()
Set frmPrevious = Screen.ActiveForm
Set frmPreviousSub = frmPrevious.MySubFormControl.Form
' do whatever
End Sub
因此,现在我们既可以引用以前的表单,也可以引用子表单。
假设用户选择了某个地址,然后单击“确定”按钮。
然后代码执行以下操作:
frmPreviousSub!AddressID = me!ID ' get/set the PK address ID
docmd.Close acForm, me.name
因此,世界上没有任何贫穷,没有必要抢劫和缠住土地或任何类似的手掌。
只需几行简洁的代码即可。
现在,我确实有一个递归循环,该循环将始终返回表单句柄作为对象引用,因此您甚至不必对表单名称进行硬编码。
因此,假设主表单有2个子表单,在这些子表单上,您有
公司地址和地址。因此,您想从这两个子表单的EITHER中启动表单B,并且当您选择一个地址时,您将返回该值,因此实际上有两个甚至三个潜在的3个子表单可以这样调用弹出地址选择器表单。
您执行此操作的方式与上面的代码类似,但是我们不需要对子表单进行硬编码。
现在的代码将如下所示:
Private Sub Form_Load()
Dim f As Form
Set f = Screen.ActiveForm ' pick this up RIGHT away -
' previous active form only valid
' in open/load event
' we have the previous active form, get the sub form.
Set frmPrevous = GetSubForm(f)
End Sub
请注意,子表单的深度可能为3甚至5级。此例程是“递归的”。它获取上一个表格,然后检查子表格是否具有焦点。如果子窗体具有焦点,则它将获得该控件,而如果该控件是子窗体,则它将一直继续下去,直到我们钻出该兔子孔并且不再发生更多钻取为止。
该例程应放在表格之外,并放在例程的标准“全局”模块中。
Public Function GetSubForm(f As Form) As Form
Static fs As Form
If f.ActiveControl.Controltype = acSubform Then
GetSubForm f.ActiveControl.Form
Else
Set fs = f
End If
Set GetSubForm = fs
End Function
因此,请注意,如果发现子表单具有焦点,该怎么办?好吧,它只是使用该表单再次调用自身,并继续进行深入挖掘。结果,表格的深度是1还是5层都没有关系。结果“ frmPrevous”将是对该子表单的有效引用,因此,在您选择或以假定的弹出表单进行操作之后?您可以设置一些PK或其他值,然后关闭表格。
没有hwnd,非常干净的代码,递归技巧意味着即使对于嵌套的子表单多于一个深层,您的frmPrevious实际上也是对表单的引用,该表单启动我们弹出的表单供用户选择。
如果没有通用的“地址ID”列?然后,我们的弹出表单应确保您始终在调用表单中定义了一个公共变量。
只要说ReturnAddressID
确保您将值设为公开值,这样说:
Public ReturnAddressID as long
因此,现在在我们的弹出窗口中,我们可以执行以下操作:
frmPrevious.ReturnAddressID = me!PD
frmPrevous.MyUpdate
(我们假设所有调用弹出窗口的表单也都具有一个名为MyUpdate的公共函数。
因此,现在我们有了一种通用的方法,即2或10种不同的地址形式,即使子形式现在可以调用一个地址选择器。只要这些形式中的任何一个都采用该公共ReturnAddressID和一个公共函数MyUpdate,那么我们就可以传回这些值,并且MyUpdate将把/ ReturnAddressID推入/采用/设置为该子表单中用于地址ID的任何列和值。 。
当然,如果没有子窗体,该例程将只返回调用弹出窗体的最上面的窗体。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句