open Dialogues

  • Thread starter Thread starter Gottfried Lesigang
  • Start date Start date
G

Gottfried Lesigang

Hi everybody!

Using AccessXP, all available servicepacks installed.

I have a quite simple question - should be every days work ;-) but no
(convincing) solution found yet...

What it should be: My MainForm hands an object (selfdefined class) to a
popup form and opens it as a dialogbox. The user enters some values, these
values are validated and written into the properties of my class-object. The
dialogue disappears and my MainForm handles the (changed) values within the
object.

The Online-Help gives information and examples about "Load Object" and
"Form.Show vbModal" - what should be exactly what I need. This way just
doesn't work. Neither am I aloud to "Load" my DialogueForm, nor is there any
"Show"-method within my forms :-(

Later I found out about the "DoCmd.OpenForm" but there is no chance to put
MyClassObject into the "OpenArgs" (I realy don't want to serialise this!).

Than I found out about the variables beginning with "Form_" wich represent
my forms. It is no problem to define a public property within my dialogue
and I can set it to MyClassObject with:

Set Form_MyPopUp.MyClass = MyClassObject

A MessageBox within the "Load"-Event appears at this moment...

But there is no "Show"-method... And just making it visible doesn't make my
programm wait for the users reaction! The lines behind the ".visible=true"
are executed immedeately...

If I open the form with the DoCmd and "WindowMode;=acDialog" it is loaded
once again and it shows a second instance of my PopUpForm (I tested this
with a MessageBox within the "Load"-Event...)! This second instance doesn't
know about MyClassObject and changes made by the user don't affect the
"Form_MyPopUp" at all... I even have to close it twice :-((((

What I do at the moment? I defined a public sub "AnswerDialog(Changed as
Boolean)" within my MainForm. At the very last line of the calling "Sub" I
pass "MyClassObject" to "Form_MyPopUp" and make that visible. By closing the
PopUp my public "Sub" is called by the PopUp's EventProcedure. But this way
is super-ugly and pure nightmare to OOP!

So my simple question: How is this done?

TIA
Gottfried
 
The commands you are trying to issue appear to be Visual Basic commands, not
Access. To open the form and have it pause the calling code, try

DoCmd.OpenForm "FormName",,,,,acDialog

The acDialog window mode argument will popup the form and halt the calling
code until the popup is closed or hidden.
 
Wayne, thanks for your answer!
The commands you are trying to issue appear to be Visual Basic commands, not
Access. To open the form and have it pause the calling code, try

DoCmd.OpenForm "FormName",,,,,acDialog

The acDialog window mode argument will popup the form and halt the calling
code until the popup is closed or hidden.

Yes, I know that. As I wrote already:

I got a very strange behaviour with this: It worked very fine with my first
PopUp - for a while. I than designed another (completely selfstanding) PopUp
an tried to open it the same way (within the Click-Event of another button).
But from this on BOTH Forms (I didn't change anything with the first!)
opened with empty fields! Placing MessageBoxes within the Load-Event brought
up that the Form was loaded twice: One instance (accessable with
"Form_MyForm") holds my Parameter-Object - but is invisible! The other
Instance (created during DoCmd.OpenForm) is visible - but empty. After TWO
Clicks on the Exit-Button I come back to my Code. Inputs made by the User
are gone and "Form_MyForm" stills keeps a reference to the propper object -
but unchanged offcours.

My current way works - but I dislike it :-(

Any other ideas?

TIA
Gottfried
 
I'm sorry, I was scrolling with the mouse wheel and must have moved the
mouse just enough that it quit scrolling and I didn't catch that I wasn't at
the end of your message. I have now gone back and read the entire message.

The only thing I can think of to do is to set up a Do loop that runs until
your popup is closed or hidden, whichever check you prefer. Include a
DoEvents in the loop.

Example:
Private Sub Command10_Click()
DoCmd.OpenForm "Form4"
Do While IsOpen("Form4")
Sleep 100
DoEvents
Loop
MsgBox "Form4 is closed."
End Sub

With the Sleep function, this didn't appear to send the CPU usage way up,
with just the DoEvents my CPU usage would jump up and down to 100%. The
Sleep function is an API call (declaration below) and the IsOpen (below) is
a user defined function from Ken Getz (I think). I tried 1000 first with the
Sleep function and on my P3-700 it was noticeable that the app was
"sleeping", at 100 everything still seemed to run smoothly.

Public Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)

Public Function IsOpen(strName As String, Optional varObjectType As Variant)
'Returns True if strName is open, False otherwise.
'Assume the caller wants to know about a form.
If IsMissing(varObjectType) Then varObjectType = acForm
IsOpen = (SysCmd(acSysCmdGetObjectState, varObjectType, strName) <> 0)
End Function
 
Thanks for your answer!
The only thing I can think of to do is to set up a Do loop that runs until
your popup is closed or hidden, whichever check you prefer. Include a
DoEvents in the loop.

Well, now I have to decide which kind of uglyness is prettier;-)
Public Function IsOpen(strName As String, Optional varObjectType As Variant)
'Returns True if strName is open, False otherwise.
'Assume the caller wants to know about a form.
If IsMissing(varObjectType) Then varObjectType = acForm
IsOpen = (SysCmd(acSysCmdGetObjectState, varObjectType, strName) <> 0)
End Function

I didn't know about the SysCmd. Just looked it up in the online help. It has
a quite strange look, but it could do great work (sometimes).

Still I'm not very happy with it, because it should be "every days work" to
bring up PopUp-dialogues, shouldn't it?

Why the f**** hell isn't the OpenArgs-Parameter a Variant? Otherwise I could
easily pass in my oject-reference...

Thanks!
Gottfried
 
Could you pass a name, handle, or anything that could be converted to text
that you could use to find the instance of your object once the popup
opened? Could the changing values be stored in Global Variables that would
be accessible from wherever you are? Could you use a temporary table to pass
the values in and out of so that they would be accessible from anywhere?

I know what you mean about the popups. Sometimes it would be nice to hide a
popup then make it visible again in dialog mode, but this doesn't seem to
work either. You have to close the form and reopen it as a popup, unless
someone else has an idea here. If I am remembering correctly from my VB
class, this definitely works better in VB.
 
Hi Wayne!
Could you pass a name, handle, or anything that could be converted to text
that you could use to find the instance of your object once the popup
opened?

Offcourse I could! It's just absolutely not OOP... And what use do I get
from the "Form_FormName" variables?
Could the changing values be stored in Global Variables that would
be accessible from wherever you are?
ditto

I know what you mean about the popups. Sometimes it would be nice to hide a
popup then make it visible again in dialog mode,

I didn't even want to do something "compicated" like this ;-)
but this doesn't seem to
work either. You have to close the form and reopen it as a popup, unless
someone else has an idea here. If I am remembering correctly from my VB
class, this definitely works better in VB.

As I'm usually coding with VB5 or nowadays with C# I may confirm; YES!

Thanks anyway!

The best way for me seems to be the one I use:
At the very end of the calling sub the "Form_MyPopUp" gets the reference
through a public property and a second reference to the calling
"Form_MainForm" - and then just make the PopUp visible. The PopUp itself
calls when closing a public "Answer"-method of the calling Form. By this way
I'm quite limited. Different reactions to different calling situations must
be sorted out with some kinds of flags...

How pretty can you make something ugly ;-) ?

Gottfried
 
Ok, just trying to brainstorm up some alternatives, not necessarily good
ones. If you have it working, pretty or not, I guess that's the main thing.
 
Hi Wayne!

It didn't let me sleep ;-)

So I tried a modifiaction of your suggestion - this works perfectly!

Within the click-event I use the "Form_MyForm"-Variable to pass in my
parameters (whatever type I like - yeah!). Then I make it visible and call
my "WaitForClosing"-procedure. Within the PopUp I use "DoCmd.Close":

Private Sub Button_Click()
Form_MyForm.ParamterBool = True
Set Form_MyForm.ParameterObject = MyObjectReference
Form_MyForm.Visible = True
WaitForClosing "MyForm"
MsgBox "I'm back!"
End Sub

Private Sub WaitForClosing(FormName As String)
Do
DoEvents
Sleep 100
If SysCmd(acSysCmdGetObjectState, acForm, FormName) = 0 Then Exit Do
Loop
End Sub

You were perfectly right, that the Sleep-Call avoids 100%-usage - in fact
the system behaves as usual.

This workaround is rather pretty, isn't it?

Thanks a lot!
Bye
Gottfried
 
Your welcome. I sometimes do my best thinking when trying to sleep. It's
fine if I don't have to get up and go to work in the morning.
 
Hi Wayne!

The solution mentioned doesn't work as well...

By using DoCmd.Close within the PopUp a second instance of my PopUp is
loaded by reading the properties afterwards. I didn't realise this
immediately, because the effects within an object which was passed over by
rerference are persistent offcourse. The problem occured with a boolean
"Changed"-property which was allways false.

I'm using now this code (The PopUp doesn't close any more - just going
invisible...)

Private Sub WaitForClosing(FormName As String)
Do
DoEvents
Sleep 50
Select Case FormName
Case "popfrmPersonName"
If Form_popfrmPersonName.Visible = False Then Exit Do
Case "popfrmAdresse"
If Form_popfrmAdresse.Visible = False Then Exit Do

[... "Case" for each exisiting Form ...]

End Select
Loop
End Sub

The behaviour now is exactly what I need! Do you now a way to refer to the
Forms without using the "Form_MyForm"-variables and so avoiding the
"Select"?

The "Forms"-collection is of no help: The expression "Debug.Print
Forms(1).Name" returns e.g. "popfrmMyForm", but "Debug.Print
Forms("popfrmMyForm").Name" returns an error like "The Form 'popfrmMyForm'
was not found in the collection". I think there is no way to construct the
name of the variable by combining the "Form_" and the given Name in
"FormName" by code.

Well, it works - but it could be better...

Thanks for any suggestion!
Gottfried
 
Found it! The best way sometimes is so easy...

This Sub provides roughly the behaviour of "frm.Show vbModal"

You call it using "ShowModal Form_MyForm" - and that's it.

Private Sub ShowModal(frm As Form)
frm.Visible = True
Do
DoEvents
Sleep 100
If frm.Visible = False Then Exit Do
Loop
End Sub

With this I'm rather happy now!

So long!
Gottfried
 
Back
Top