如何处理Popup,Modal,Resizable表格
我需要为其屏幕不像其他人那样大的用户调整大小的弹出窗体 - 将窗体设置为Popup和Modal以及BorderStyle Resizable有一个主要限制 - 代码现在启动弹出框的表单不会等待表单返回。如何处理Popup,Modal,Resizable表格
那么,如何让一个表单等待隐形?我尝试使用sleep和doevents循环,但这会使弹出窗体不能很快响应,并且会嚼碎CPU周期。我已经尝试设置启动窗体的form.gotfocus事件,但不会触发,这意味着我必须将打开弹出窗体的代码与弹出窗体关闭后执行的代码分开。
什么是最佳解决方案?
感谢
您可以打开acDialog选项的形式:
DoCmd.OpenForm "MyFormName", WindowMode:=acDialog
它会等到形成封闭或隐藏。
这里的问题是弹出窗口和模态窗体不会停止调用代码。
但更糟的是你需要停止调用代码。这需要一个对话框。
更糟糕的是对话框形式不允许重新调整大小。
你不想在这里混淆3种形式。
模态形式 - 它们不同于弹出形式,与对话形式截然不同。
对Popup表单也是如此。它们不是对话形式,事实上它们也不是模型。
如果您将Access应用程序设置为使用选项卡式文档或重叠窗口,您还必须考虑。 (这会再次限制你的选择)。
如果您使用选项卡式界面,那么您必须使用弹出式窗体,如果您想要重新调整大小的功能 - 但此类型的窗体不会停止调用代码。
如果您使用重叠的窗口,那么我推荐一个模态窗体。 (但它不会停止调用代码,但会允许重新调整大小)。
尽管您可以在调用窗体中采用一些“等待”第二种形式的循环代码,但这样的循环是处理器大量使用,并且在鼠标和打字方面通常会导致“较差”的响应。
所以我建议改变你的代码方法。让调用窗体以弹出窗口的形式启动窗体(如果不使用标签界面,则为模态)。
然后,当您关闭窗体时,它会调用一些更多的代码,您想要在调用窗体中运行。这意味着你必须在关闭第二个表单之后拆分出你想要运行的代码 - 并且让结束表单调用并运行该代码。
“通用”方法应该避免对表单名称进行硬编码,因为“许多”例程和表单可以调用第二个表单,并且设施可以重用这些表单。
那么试试这个: 在第二种形式,创建这样一个模块级表单变量:
Option Compare Database
Option Explicit
Dim frmPrevious As Form
在形态上开这种形式的活动,抢调用形式refeance这样的:
Set frmPrevious = screen.ActiveForm
现在的形式关闭事件,这样做:
frmPrevious.AfterClose
而在调形式,创建一个名为
AfterClose
所以在第一种形式的公共功能,您将您希望当您关闭第二个形式运行的代码公共职能。这是“不那么理想”,然后是称为第二种形式的漂亮程序代码,等待并继续 - 但我认为它仍然是最佳选择。
你关闭之前,你可以通过或“设置”值返回到像调用形式:
frmPreviuos.SomePubicVar = me!LastNameSelected
frmPrevious!Company = me!CompanySelected
frmPrevious.AfterClose
在第一线的上方设置在调用形式的公共变量(如果你想做到这一点,并将值传递回第一种形式的模块级变量)。下一行设置调用表单中控件的值(如果您想将值传递回调用表单上的某些控件)。
第三行执行调用表单中的MyClose代码。如果你有第二种形式的“确定”或选择按钮,那么将上面的代码移动到该按钮后面 - 因为如果表单有一个取消按钮,你可能不希望这样的代码运行(所以取消按钮将会简单关闭窗体 - 但不要在第一个窗体中调用+运行上面的代码)。击中X也会被认为是取消或退出。所以你的“保存”或“确定”或“选择”按钮将具有上述代码。
感谢您的详细解释 - 您提供了一个可行的解决方案和一些提示,以更好的编码 - 我将尝试解决方案,缩短睡眠时间,看看它是否有效,因为程序方法可以提供更清晰的代码,但如果响应时间或CPU周期过高,我会实施您的解决方案 - 谢谢 – Charlie
我从来没有与DoEvents/Sleep 50
循环有任何问题。 CPU负载保持最小并且形式响应。
用一台很旧的电脑,或许用Sleep 100
。
示例代码:
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub TestOpenForm()
If FormOpenWait("frmPopup") Then
MsgBox "Form was hidden.", vbInformation
Else
MsgBox "Form was closed.", vbInformation
End If
End Sub
' Open fName, wait until it is
' - closed : return False
' - hidden : return True
Public Function FormOpenWait(fName As String, Optional sOpenArgs As String = "") As Boolean
If IsFormLoaded(fName) Then DoCmd.Close acForm, fName, acSaveNo
DoCmd.OpenForm FormName:=fName, OpenArgs:=sOpenArgs
' default: signal "closed"
FormOpenWait = False
' Wait until form is closed or made invisible
Do While IsFormLoaded(fName)
If Not Forms(fName).Visible Then
' Signal "hidden"
FormOpenWait = True
Exit Do
End If
' Wait 50ms without hogging the CPU
DoEvents
Sleep 50
Loop
End Function
Public Function IsFormLoaded(fName As String) As Boolean
IsFormLoaded = (SysCmd(acSysCmdGetObjectState, acForm, fName) And acObjStateOpen) > 0
End Function
我不同意。它工作得很好。分割代码是更加丑陋的。如果你例如希望等待查询(数据表视图)关闭,这是唯一的选择。 @Enigmativity – Andre
我看到你有这些样板。 :)但是你知道这个问题是关于MS-Access和VBA的?不是C#。没有https://stackoverflow.com/questions/5721564/multi-threading-in-vba – Andre
啊,好点。我确实想念那个。然后,我可能会删除这些评论,因为它们具有误导性。 – Enigmativity
但是,这将使形式的非调整大小。 – Andre