Is There a Way To Simulate the Form Activate from Modal/Pop Up Form - vba

I have a form that opens a modal pop up helper form to collect some data. When this modal pop up form closes, focus returns to the main form. I would like to trigger some activity when focus comes back to my main form.
The event model for the form does not trigger the Form_Activate or Form_GotFocus events when returning from a model popup as per Microsoft documentation.
These forms and all controls are completely unbound.
Is there a trick to knowing in code when focus returns to my form?
If both forms are placed in normal mode, Form_Activate does fire in the primary form when the helper form closes, but this does not meet my needs. I have not been able to find a similar event to trap this. I'm hoping someone has a workaround.

For clarity, the issue I ran into was I had the design time properties in the helper form set to act as a dialog - (pop up and modal as true). When I opened the form responding to the button click event on the main form, I did NOT include the acDialog option.
If you omit the WindowMode=acDialog setting the code operates asynchronously completing the code in the click event handler in full, NOT halting and waiting.
The acDialog option apparently forces the DoCmd.OpenForm command to run synchronously, halting code execution, then returning once the modal form has been closed.
Private Sub btnHelper_Click()
DoCmd.OpenForm "frmHelper", WindowMode:=acDialog
'Do stuff after frmHelper closes
End Sub

Related

'Undo' in unload event of a subform

I wanted the user to confirm the changes he made on a record, so I added 'Save' and 'Discard' buttons to my form. Discard button runs DoCmd.RunCommand(acCmdUndo) which works fine. I also added this line to Form_Unload event of my form to undo unsaved changes before quit, which also works fine.
The problem is when I use this form (let's say form1) as a subform in another (main) form. When I hit the close (X) button of the main form, vba gives this error under Form_Unload event of form1:
Run time error '2046': The command or action 'Undo' isn't available now.
I also tried Me.Undo, but apparently it's not working in Unload event at all.
So my specific question is how can I discard the unsaved changes of a record in a subform, on the unload or exit event of the main form.
It seems that when X button is pressed everything gets saved; and no Undo will be available. Form_Unload is too late to intercept the saving action. Form_BeforeUpdate can be used instead.

How to prevent button clicks in a MS Access Form_A when Form_B is correctly displayed modal over Form_A

I realized while I was typing up this question what the problem might be and was then able to solve it. So, I have posted the question and then the answer in case it helps someone else.
I am using MS Access 2016. I have a Form_A that displays a menu of buttons--each button takes the user to a distinct form to perform whatever functions the user needs to perform. For example, one Form_A menu button could be [Add Clients] while another button could be [Add Staff], etc.
When the user first logs into the system, I use VBA code to do a number of "housecleaning" functions. Form_A and the buttons are visible, but I have made a Form_B that is a small dialog that shows the word "Working" with animated "..." while the VBA in Form_A does the housecleaning.
The problem that I cannot solve is that even though I have set Form_B's "Pop Up" property to "Yes" and its "Modal" property to "Yes", the user can still click buttons on the Form_A menu which then execute while Form_B is still doing its housecleaning.
I thought setting Form_B to modal should prevent button clicks on Form_A from getting registered.
More details:
In the Form_Load event, Form_A calls "housekeeping" code that resides in a Module. That module has a Public Sub called "RemakeTables." The RemakeTables code uses DoCmd.OpenForm "Form_B" to display the "Working" dialog.
The RemakeTables code calls several other Public subs. Between each call to the other Public subs, a DoEvents is called which allows for the "Working" dialog to animate the "..." (i.e., cycle between "Working", "Working.", "Working..", and "Working...").
My hunch is that the DoEvents is what is allowing clicks to get registered in Form_A.
How should I be doing this so that clicks cannot be registered while the Form_B "Working" dialog is showing but can still be animated?
As I was typing up the question, it occurred to me that the main problem was that the subs and functions I was calling during "housekeeping" used the DoEvents action to allow the Form_B "Working" dialog to update/animate. However, DoEvents also allows mouse clicks to register.
So, how to prevent the problem?
Include the "housekeeping" calls in the Form_Open event rather than the Form_Load event because the Form_Open event occurs first, before the Form_Load and before the form is displayed, so, there will not be any buttons visible to click if the "housekeeping" code is called in Form_Open.
Hope this helps someone else who might have had a similar problem.

Calling a form's load event when form is already loaded but has gained focus

I am creating a bike booking system in VB using winforms. I have two forms: frmBikeHire and frmBikeBookingsEdit.
On each form is a button with a click event to show and give focus to the other form.
frmBikeBookingsEdit.MdiParent = frmMDI_Main
frmBikeBookingsEdit.Show()
frmBikeBookingsEdit.Focus()
And
frmBikeHire.MdiParent = frmMDI_Main
frmBikeHire.Show()
frmBikeHire.Focus()
When a single form is open, the show command opens the other form and the load events from that form are run (refreshing the form). When the second form is already open, then the focus command brings the second form to the front. I also want the load events to run after the focus command so that the form is refreshed. Is there a simple way to re-run the load command?
I have worked this one out myself...
I have made the refresh form commands that are called on the load event, by changing them to Public Subs and then calling the refresh commands before bringing the form back into focus:
frmBikeBookingsEdit.MdiParent = frmMDI_Main
frmBikeBookingsEdit.refreshBookingDetailsGrid()
frmBikeBookingsEdit.refreshBookingsListGrid()
frmBikeBookingsEdit.Show()
frmBikeBookingsEdit.Focus()

Keep form on top of another form in modal fashion, but continue execution

I have a form in a vb.net windows form application called PolicyRefreshStatus.vb that has a ProgressBar control on it. From the main form called EditPolicy.vb I need to show PolicyRefreshStatus.vb over top of EditPolicy.vb - but the way things are wired I'm controlling the the ProgressBar and it's steps from logic inside EditPolicy.vb.
If I display the PolicyRefreshStatus.vb bar using the .show() method things work fine. The problem is if the user clicks back on the main form then PolicyRefreshStatus.vb losses focus. If I show PolicyRefreshStatus.vb as a modal form using .ShowDialog() then execution halts in EditPolicy.vb after the .ShowDialog() statement.
so for example in the code:
mPolicyRefreshStatus = New PolicyRefreshStatus
mPolicyRefreshStatus.pbMax = mPolicy.ClaimsUpdateMax
mPolicyRefreshStatus.ShowDialog()
mPolicy.UpdateFromFIS()
The line mPolicy.UpdateFromFIS() never executes because it's waiting for the PolicyRefreshStatus form to close.
How can I show PolicyRefreshStatus in a modal form but let execution continue in EditPolicy.vb?
You've got a couple of related options.
This first is to pass the unit of work to the progress bar in the form of a delegate or a class implementing an Interface. Something like this (not checked for correctness, just a rough example):
mPolicyRefreshStatus = New PolicyRefreshStatus
mPolicyRefreshStatus.pbMax = mPolicy.ClaimsUpdateMax
mPolicyRefreshStatus.UnitOfWork = AddressOf(mPolicy.UpdateFromFIS())
mPolicyRefreshStatus.ShowDialog()
Then within the progress form you can call back to the routine that actually does the work.
Another approach is to define events on your ProgressForm and then the owning/launching object can handle those events to do the work in. With this option you can create a fairly detailed set of events to be able to handle incremental work or cancels, but the concept is the same, youu are calling back from the progress form into launcher to perform the actual business logic.
You cannot show the form modally and let your routine continue. You must show the form Non-modally and then do your other stuff, closing the form when you've finished. Maybe a loop until the task has finished?
Using Show() with a parent form parameter will give you better usability. More like a tool window.

Closing forms in VB.NET

I have a small requirement and that is as follows:
I have a login form and after a successful login, i open another MDI form, but i want to close the login form. I have given the code as:
MDIForm1.show
Me.Close
This does not seem to work.
Can anyone help on this.
Similarly, is is possible to open the login form on an inactive MDI form [MDI and Login for to be seen] and when th user login details are correct, it must close the login form and return to the MDI Form.
Please help on this.
Regards,
George
Firstly, I'm guessing you've set your login form as the application's startup form? If so then VB has put something like this together for you behind the scenes:
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(New LoginForm)
The magic happens there in that Application.Run call, which basically creates a message loop for your GUI and terminates when it detects that your form has been closed.
There are a couple of ways that I know of to deal with this.
First: don't make the login form your startup form at all. Create your main form, but cause it to hide itself and ShowDialog on an instance of your login form before appearing.
Make your login form your startup object, but instead of closing it when you open your main form, simply hide it (this is actually pretty horrendous to me personally, but it's a possibility).
As for the MDI form question: this seems completely possible to me, if I understand you correctly. You want to show both the login form and the MDI form at once, but you want the MDI form to be disabled until the login form is closed, right?
So just make the MDI form your application's startup form, have it call ShowDialog on your login form in its Load event, and bingo: the MDI form will effectively be "locked" until the login form is dealt with (this is how modal dialogs in general such as MessageBox work). This is actually the same as option #1 above except that the main form (your MDI form) is never hidden, only blocked.
Other ways:
Dim <form name> As New <form name>
<form name>.Show()
Me.Hide()