2017-10-07 94 views
1

我需要爲其屏幕不像其他人那樣大的用戶調整大小的彈出窗體 - 將窗體設置爲Popup和Modal以及BorderStyle Resizable有一個主要限制 - 代碼現在啓動彈出框的表單不會等待表單返回。如何處理Popup,Modal,Resizable表格

那麼,如何讓一個表單等待隱形?我嘗試使用sleep和doevents循環,但這會使彈出窗體不能很快響應,並且會嚼碎CPU週期。我已經嘗試設置啓動窗體的form.gotfocus事件,但不會觸發,這意味着我必須將打開彈出窗體的代碼與彈出窗體關閉後執行的代碼分開。

什麼是最佳解決方案?

感謝

回答

0

您可以打開acDialog選項的形式:

DoCmd.OpenForm "MyFormName", WindowMode:=acDialog 

它會等到形成封閉或隱藏。

+0

但是,這將使形式的非調整大小。 – Andre

0

這裏的問題是彈出窗口和模態窗體不會停止調用代碼。

但更糟的是你需要停止調用代碼。這需要一個對話框。

更糟糕的是對話框形式不允許重新調整大小。

你不想在這裏混淆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也會被認爲是取消或退出。所以你的「保存」或「確定」或「選擇」按鈕將具有上述代碼。

+0

感謝您的詳細解釋 - 您提供了一個可行的解決方案和一些提示,以更好的編碼 - 我將嘗試解決方案,縮短睡眠時間,看看它是否有效,因爲程序方法可以提供更清晰的代碼,但如果響應時間或CPU週期過高,我會實施您的解決方案 - 謝謝 – Charlie

0

我從來沒有與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 
+0

我不同意。它工作得很好。分割代碼是更加醜陋的。如果你例如希望等待查詢(數據表視圖)關閉,這是唯一的選擇。 @Enigmativity – Andre

+0

我看到你有這些樣板。 :)但是你知道這個問題是關於MS-Access和VBA的?不是C#。沒有https://stackoverflow.com/questions/5721564/multi-threading-in-vba – Andre

+0

啊,好點。我確實想念那個。然後,我可能會刪除這些評論,因爲它們具有誤導性。 – Enigmativity