关于vba:如何检查Access 2003表单(模态或非模态)的状态?

How to check the State of a Access 2003 Form, Modal or Modeless?

对于在Access 2003下运行的项目,我有一个通常设置为无模式的窗体,但是在某些情况下以acDialog形式打开,因此是有模式的。

此表单现在需要检查自身是否为模态,从而在相应地单击按钮时修改其行为。

1
Me.Form.Modal

仅返回在设计模式下指定的属性值,而不返回当前状态。

我已经找到了VB的类似答案,建议使用对"用户"的GetWindowLong API调用,但这不能转换为VBA(Microsoft知识库77316),恐怕:Access2003找不到\\'user \\'-文件。

简而言之:是否有可靠的方法可以从此表单中确定表单本身是模态的还是无模的?

TIA。

编辑:
我似乎记得Me.Form实际上等同于我。据我所知,"表单属性"是默认属性,因此,如果省略它,将被假定为默认属性。无论如何,无论打开窗体的方式如何,Me.Modal和Me.Form.Modal都传递值''false \\'。


我知道这很老了并且回答了。我只是想指出,p122的解决方案实际上不是读取窗口的模式状态,而是读取弹出状态,这对我来说很好,因为这就是我想要的。

如果在模式非弹出窗口中打开表单,则p122的IsModal函数将返回false。
如果在无模式弹出窗口中打开表单,则IsModal返回true。
因此,IsModal实际上是IsPopup。


弄清楚了API(我认为Access有点黑,我认为Access在表单方面做了一些有趣的事情)

将此放入模块中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Const GWL_EXSTYLE = (-20)
Const WS_EX_MDICHILD = &H40

Declare Function GetWindowLong Lib"user32" Alias"GetWindowLongA" _
    (ByVal hwnd As Long, ByVal nIndex As Long) As Long


Public Function IsModal(ByVal lHwnd As Long) As Boolean

Dim lWinstyle As Long

  lWinstyle = GetWindowLong(lHwnd, GWL_EXSTYLE)
  If (lWinstyle And WS_EX_MDICHILD) Then
    IsModal = False
  Else
    IsModal = True
  End If

End Function

然后在form_Load事件中(或在任何地方)

1
  MsgBox"Hi I'm" & IIf(IsModal(me.Hwnd),"Modal","Not Modal")

考虑在OpenArgs中传递一个值,以指示是否使用acDialog打开了表单。


对于当前的问题,我不一定推荐这样做(尽管它可能是一个解决方案),但是在某些情况下可以派上用场,那就是使用acDialog acHidden打开表单,更改其属性,然后设置.Visible = True。这将导致表单在其出现的位置而不是在其打开的位置变为模态。也就是说,代码将一直运行到将表单设置为.Visible为止,然后才暂停,就像在OpenForm命令中仅使用acDialog参数一样:

1
2
3
4
5
6
  DoCmd.OpenForm"dlgMyDialog", , , , , acDialog +acHidden
  With Forms!dlgMyDialog
    !cmbMyComboBox.Rowsource = ...
    !cmdClose.Tag ="Modal"
    .Visible = True ' <= code pauses here
  End With

这是您需要从使用acDialog打开的另一个表单中打开模式表单(使用acDialog)时可以使用的东西。也就是说,使用acDialog acHidden打开新对话框,然后在子表单集.Visible = True和父表单(即调用)表单的.Visible = False的OnOpen事件中。要将调用表单恢复为对话模式,请在子表单的OnClose事件中设置调用表单的.Visible = True。

从我的angular来看,这种方法的缺点是两种形式必须彼此了解太多。我更喜欢对话框形式可以在多个上下文中使用,这意味着没有任何可能调用它的形式的硬引用(并且可以在仅代码形式的上下文中调用,而不是从其他形式中调用)。但是,当您需要执行此类操作时,这是一种将其完成的方法。


我建议您引用" screen.activeForm"对象,而不要引用表单的" Me"实例。要了解我的意思,请尝试以下

(1)打开您的表单

(2)转到VBA调试窗口

类型:

1
2
? screen.activeForm.modal<Enter>
<Answer>True

类型

1
screen.activeForm.modal = False<Enter>

类型

1
2
? screen.activeForm.modal<Enter>
<Answer>False