Screen.ActiveForm returning wrong form (1 Viewer)

Futures_Bright

Registered User.
Local time
Today, 10:46
Joined
Feb 4, 2013
Messages
69
Hi all,

I have a problem that has taken me quite a while to try and understand and how to resolve it... I think I understand what the problem is and have an idea of how to fix it - but since I'm not confident about it and the solution will be a ballache I want to get a second opinion:

The problem:

I have a global function called "Permissions" that runs through the form ensuring the right ones are locked/disabled/invisible depending on the user's level on load for all forms (this function uses Screen.ActiveForm to work out which form it should run the code on and I have .setfocus for each of the forms before calling the function). This has worked really well except I've just noticed it doesn't work on two particular forms. In my database I try and limit the possibility of multiple forms being open except when it is necessary - these two forms are examples where multiple forms can be open.

I have a 'Clauses In Review' form to show any clause that needs to be reviewed and (if one exists) the previous version it has updated. Two buttons to open the 'Review Clause' or 'Previous Review' forms. Unfortunately I've now found out that it runs the 'Permissions' function on the 'Clauses In Review' form in the background even after setting focus to the newly open forms.

My understanding of the problem:

So after a day of trying to fix the code (I tried moving it to 'before update' but this won't work on it's own) and frantic googling, I think the problem is that the 'Clauses In Review' form is still active because it all starts with the docmd.OpenForm command for the buttons. I'm not convinced this is the problem because it works on other forms where I have a button to open another form and then close the current one though (i.e. the only difference is these buttons don't close the current form down, but this should happen after the 'on load' event for the new form opened anyway).

If this sounds likely to be the problem, the only solution I can think is to not use Screen.ActiveForm and instead have it a variable given by every form that calls it up - which will mean changing this on Every form I have!


So does this sound likely to be the cause of the problem or are there other things I should check first? Does anyone have any more 'elegant' solutions for me to try that don't involve a lot of man-hours updating code?


Thanks in advance.
 

theDBguy

I’m here to help
Staff member
Local time
Today, 03:46
Joined
Oct 29, 2018
Messages
21,358
Hi. Are you opening the other forms in Dialog mode? If not, are you able to?
 

vba_php

Forum Troll
Local time
Today, 05:46
Joined
Oct 6, 2019
Messages
2,884
sounds like uve got a pretty damn complex thing going on here. A couple of things to mention here after reading your stuff:

1) be aware of the difference between popup forms and modal forms and running code on them. if any of these open forms of yours are popups or modals and you're trying to "setfocus" on them or something like that, it's possible the action is being ignored or will error out cuz popup and modals (i can't remember which) stays on top of all other open forms. this would also explain why "screen.activeform" would not work on the form you want.

2) there's nothing wrong with having multiple forms open at once. as a matter of fact, most of the stuff i've built in access uses a system where by i bring up form on top of form, sometimes many all open at once as a means to tell the user they're "stupid" and can't possibly make a mistake in terms of knowing what to do! they're not stupid of course, but it's a way of guiding them in case they're ignorant. but if you do stuff like that, using the popup and modal properties are key because it prevents users from clicking around aimlessly and causing the app to error out due to unintentional operations.

I seriously doubt you will need much code to do what you want, but ur description is a little vague. I didn't follow all of it, and I'm not sure any other expert here would either. can you be any more clear about it? maybe a sample file upload for people to look at?
 

moke123

AWF VIP
Local time
Today, 06:46
Joined
Jan 11, 2013
Messages
3,852
My first thought, without seeing your code, would be to pass the form object as an arguement to your "Permissions" function instead of using screen.activeform.

Code:
public function Permissions(frm as form)

'replace all Screen.ActiveForm with frm
'do whatever the function does

End function

in the onload event
Code:
Permissions(Me)
 

Futures_Bright

Registered User.
Local time
Today, 10:46
Joined
Feb 4, 2013
Messages
69
@DBguy/vba_php: I had to give myself a refresher on the difference between dialog, modal and pop up. This could help others (as it looks like dialog should pause the code until the window is closed, and modal should force the focus) but unfortunately for my situation there are occasions the user will need all 3 of these screens to be open (i.e. having both 'pop up' Review and Previous Review windows open).

@Moke: I think that's the 'better' solution, but before I proceed with this I want to find out if there is either: a more 'elegant' solution (i.e. a solution that doesn't need me to change the code on every form I have in the database!); or confirm that what I think is the problem is correct - I think you've done this with your suggestion.

@vba_php: I appreciate it's hard to understand the problem from a description alone; the databse is pretty large so I've done my best to explain the purpose and the logic behind the sections in question. I'll give an extract of the relevent bits of codes and hope that gives a bit more helpful insight.

Starting with the simpler button to open the 'Previous Review' (commented out DoEvents since that didn't help) - this is just the macro to open the form converted to vba:

Code:
Private Sub OpenPrevReviewButton_Click()
On Error GoTo OpenPrevReviewButton_Click_Err
    ' _AXL:<?xml version="1.0" encoding="UTF-16" standalone="no"?>
    ' <UserInterfaceMacro For="SaveAndCloseButton" Event="OnClick" xmlns="[URL]http://schemas.microsoft.com/office/accessservices/2009/11/application[/URL]" xmlns:a="[URL]http://schemas.microsoft.com/office/access[/URL]
    ' _AXL:services/2009/11/forms"><Statements><Action Name="CloseWindow"><Argument Name="ObjectType">Form</Argument><Argument Name="ObjectName">ClausesInReview</Argument><Argument Name="Save">Yes</Argument></Action><Action Name="OpenForm"><Argument Name="For
    ' _AXL:mName">Main Menu</Argument></Action></Statements></UserInterfaceMacro>
    DoCmd.OpenForm "Previous Review", acNormal, "", "[Clause ID]=" & Me.PreviousClause
'    DoEvents

OpenPrevReviewButton_Click_Exit:
    Exit Sub
OpenPrevReviewButton_Click_Err:
    MsgBox Error$
    Resume OpenPrevReviewButton_Click_Exit
End Sub
This opens the On Load event for the Previous Review:

Code:
Private Sub Form_Load()
On Error GoTo err_Form_Load
'''set control to jump to in the event of Error 2165
''ctlErr2165 = Me.Compliant_

'ensure current form is active
Forms![Previous Review].[Clause ID].SetFocus

Call Permissions  'Located in Module "User Permissions"
'Exceptions
Me.Reviewer.Locked = True
Me.Review_Date_Time.Locked = True
Me.VerifiedBy.Locked = True
Me.Verify_Date_Time.Locked = True
ExitSub:
Exit Sub
err_Form_Load:
    Select Case Err.Number
        Case Is = 2475
            'occurs when going to normal view from design view - resume once form opened
            Resume
        Case Else
            Call LogError(Err.Number, Err.Description, "Form_Load - " & Me.Name & "", , booInformUser)
    End Select
    Resume ExitSub

End Sub
And the start of the Permissions function (to the point where the form is defined and I've found it looks at 'Clauses In Review'):

Code:
Public Sub Permissions()
Dim ctl As Control
Dim frmCurrentForm As Form
Dim frmName As String
...

On Error GoTo err_Permissions

Set frmCurrentForm = Screen.ActiveForm
frmName = frmCurrentForm.Name
...
Clauses In Review is set up as No for both Pop up and Modal; both 'Review' and 'Previous Review' screens have yes for Pop up and no for Modal.

If no one else can spot anything else that I've missed and that could help, then I'll try passing the form name as an argument instead later when I have a chance to test it and let you know how it goes.
 

vba_php

Forum Troll
Local time
Today, 05:46
Joined
Oct 6, 2019
Messages
2,884
(it looks like dialog should pause the code until the window is closed, and modal should force the focus)
form objects have nothing to do with breaks or pauses in code execution ,as far as I know, unless you hard code such vba statements behind the event the runs the code. code runs behind form events and it runs immediately. there are no 2 code processes that can run at the same time, again as far as I know, which is why form events and control events have different names.

why do you have XML code behind one of your processes?

I'm not really following what you're doing here, so to get help from me you would have to reduce the size of ur file and upload a zipped version here. but there are so many other people looking at this, I'm sure one of them will get it done for you.
 

Micron

AWF VIP
Local time
Today, 06:46
Joined
Oct 20, 2018
Messages
3,476
Passing the form (or at least the form name) is exactly what I was thinking as I read through. I don't see the modification being so much of a problem. You alter the function to take either the form or the name. Then Ctrl+H, enter the function name call as what to find, set the search to the project level and enter the new function call text as the replacement value. I would use Find Next then Replace and review the change one by one rather than just hoping I got it right and changing every instance en masse and get it wrong.

A form that opens modal causes code in the calling form (or procedure) to suspend until the modal form is closed. IIRC, it doesn't matter if it is opened modal by way of window mode argument or using the property of the form itself. I guess it depends on whether or not that has anything to do with 'form objects having nothing to do with breaks or pauses in code execution' or not but it seems that it does.
 

Futures_Bright

Registered User.
Local time
Today, 10:46
Joined
Feb 4, 2013
Messages
69
form objects have nothing to do with breaks or pauses in code execution ,as far as I know, unless you hard code such vba statements behind the event the runs the code. code runs behind form events and it runs immediately. there are no 2 code processes that can run at the same time, again as far as I know, which is why form events and control events have different names.

why do you have XML code behind one of your processes?

I'm not really following what you're doing here, so to get help from me you would have to reduce the size of ur file and upload a zipped version here. but there are so many other people looking at this, I'm sure one of them will get it done for you.

Sorry the 'pause the code' bit came from reading something that suggested the code after opening the form would stop until the user closed the Dialog window before continuing - this I interpreted as 'pausing' but haven't fully tested myself because the Dialog windows aren't practical for this application.

The XML code is because it was originally a macro in access, and I used the 'convert Form's macros to Visual Basic' tool when I found it wasn't working so I could try and work out what was going wrong and how to fix it. That section is commented out but I've left it in tbh.
 

vba_php

Forum Troll
Local time
Today, 05:46
Joined
Oct 6, 2019
Messages
2,884
so does your last response mean ur aren't willing to upload a file?
 

theDBguy

I’m here to help
Staff member
Local time
Today, 03:46
Joined
Oct 29, 2018
Messages
21,358
@DBguy/vba_php: I had to give myself a refresher on the difference between dialog, modal and pop up. This could help others (as it looks like dialog should pause the code until the window is closed, and modal should force the focus) but unfortunately for my situation there are occasions the user will need all 3 of these screens to be open (i.e. having both 'pop up' Review and Previous Review windows open).
Just in case it helps someone else in the future, I should have posted this link earlier.
 

gemma-the-husky

Super Moderator
Staff member
Local time
Today, 10:46
Joined
Sep 12, 2006
Messages
15,614
Do the permissions remain static during the life of each form? In which case, surely you only need to set the permissions when each form first opens?

(ie in each forms open event)
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 05:46
Joined
Feb 28, 2001
Messages
27,001
One factor that is incredibly important here is Focus.

https://docs.microsoft.com/en-us/office/vba/api/access.screen.activeform

The description of "Screen.ActiveForm" clearly states that the form returned this way is the form that currently has focus. But if you have multiple forms open, only one of them CAN have focus.

If you clicked something to launch a form, dollars to donuts says that the active form is the one that contains whatever control you just clicked for that form launch - unless your code does an explicit SetFocus to that new form after it opens. Which COULD be problematic because event routines cannot interrupt each other except when the event is caused by a machine hardware event. Therefore, the location of the code doing the test of Screen.ActiveForm should probably NOT be in the same event-code flow as the thing that launched the miscreant form.

Stated another way, the launch code can SAY it does a .SetFocus -but if the form being opened hasn't yet had the chance to run its own Form_Load event, there are no controls to which one CAN set focus.

Therefore, your problem might not be that the Screen.ActiveForm code doesn't work, but that it is susceptible to timing issues. In essence, it sounds like you have a "race" condition and either sometimes or always lose the race.
 

Users who are viewing this thread

Top Bottom