tags:

views:

269

answers:

4

For a Project running under Access 2003 I have a Form that is normally set modeless, but in some cases is opened as acDialog and thusly modal.

This Form now needs to check if itself is Modal or not to modify its behaviour upon button-click accordingly.

Me.Form.Modal

only returns the Property-Value specified in Design-mode, not the current state.

I have found a similar answer for VB that suggests using the GetWindowLong API-Call to "user", but this does not translate to VBA (Microsoft KnowledgeBase 77316), I am afraid: Access2003 cannot find the 'user'-file.

In short: Is there a reliable way to determine if a Form itself is modal or modeless from within this form?

TIA.

Edit: I seem to remember that Me.Form is actually equivalent to just Me. As far as I recall, The Form Property is the default one, so if you omit it it is assumed. Regardless, both Me.Modal and Me.Form.Modal deliver the value 'false' regardless of the way the Form was opened.

A: 

I'd advise you to refer to the 'screen.activeForm' object instead of the 'Me' instance of your form. To see what I mean, try the following

(1) open your form

(2) go to the VBA debugging window

type:

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

type

screen.activeForm.modal = False<Enter>

type

? screen.activeForm.modal<Enter>
<Answer>False
Philippe Grondier
Sadly, this again does not work. For once, once the Form is opened modal, I actually cannot enter anything in the Direct Window of the VBA Debugger.But even reading the Screen.activeForm.modal via a Debug.Print in both states returns False in both cases again. Perhaps I can come up with a dirty fix and try to change the Focus via the code and then use error-trapping. I'll report if that works.
p122
Does not work either. SetFocus does not trigger an Error, it just does not set the Focus to the calling Form. (And I assume it will complain bitterly if the Form is not open in the modeless case.)
p122
+1  A: 

Consider passing a value in OpenArgs to indicate whether the form was opened with acDialog.

HansUp
Duh. That is actually a quite good suggestion. Much better than any setting of global variables to track what is modal or not that I seen floating about. I'll leave the question open, however, since I really am interested if there is a more generic way to figure out if the Form is modal. I strikes me as odd that there are only quick-and-dirty workarounds to this.
p122
@p122 It **does** seem like a kludge. However, sometimes a kludge can be simple and useful!
HansUp
It's particularly kludgy if you need to pass something else via OpenArgs. Having to parse it is evidence to me that you should be using some other kind of data structure to pass in the information to your form (I have a preference for standalone class modules for that purpose).
David-W-Fenton
@HansUp It was not meant as critique. It was just a obvious work-around I just did not consider. I agree that if you have to pass other stuff as well it becomes tedious, but in this case it would have solved my problem.
p122
@p122 No worries. I didn't think you were critical. I prefer DJ's solution; I see you do, too.
HansUp
A: 

I'm not necessarily recommending this for the current problem (though it may be a solution), but it can come in handy in some situations, and that's to open a form with acDialog + acHidden, change its properties, and then set .Visible = True. This causes the form to become modal at the point it appears, rather than at the point it's opened. That is, the code runs up until the point the form is set to .Visible and than pauses, just as it would with only the acDialog argument in the OpenForm command:

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

This is something you can use when you need to open a modal form (with acDialog) from another form opened with acDialog. That is, open the new dialog with acDialog + acHidden, and in the OnOpen event of the child form set .Visible = True and the parent (i.e., calling) form's .Visible = False. To restore the calling form to dialog mode, set the calling form's .Visible = True in the child form's OnClose event.

The drawback of this approach from my point of view is that the two forms have to know too much about each other. I prefer that the dialog form be usable from multiple contexts, which means no hardwired references to any of the forms that might call it (and it might be called in a code-only context, rather than from another form). But when you need to do this kind of thing, it's a way to get it done.

David-W-Fenton
+2  A: 

Figured out the API (took a bit of hacking as Access I think does some funny stuff with forms)

Put this in a module

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

Then in your form_Load event (or wherever)

  MsgBox "Hi I'm " & IIf(IsModal(me.Hwnd), "Modal", "Not Modal")
DJ
Very cool. Works flawlessly.
p122