PlanetSquires Forums

Support Forums => Other Software and Code => Topic started by: Chris Cullen on April 25, 2005, 12:50:40 PM

Title: A quick question about modal forms and passing information
Post by: Chris Cullen on April 25, 2005, 12:50:40 PM
Hi Paul

I have just installed version 2 and converted an old project and recompiled - sweet!   :D

I have a couple of 'small' buggets to report.  Fist, if you copy a control then the window styles are carried over, but the visual representation seems to go off a bit.  For example, if you create a text box with no border, then copy and paste it (say no to array), the new control has a 3d border put back.  Go and edit the syles (just turn one on and off) and it click back to no border.

Anyway, now to the reason of this post!! I often create funcitons that display a modal form and get some data.  As an example, I have a function called getdate, which takes a single argument and returns a double value.  Getdate takes a date in Jualian form as a double, displays a form modal with a calendar control on it, which needs to be set to the value passed to the funciton (it is the default date to display).  When the user clicks the OK button on the form, the function then returns the chosen date back as its value.

Now, I cannot see a way to do this via the form_show function or the form close function in FF.  I cannot see a way to Pass a value to a form or retrieve the value from the form (without a lot of messing around with the memory api's etc).

It is not safe to assume only one instance of the form will be displayed at any one time, and, ideally, the form should be thread safe!

Am I missing something, or is this a design limitation.  I have a work around which I have posted in the past, but this need my program to effectively do all the stuff the show function does, but gives me control over the form once it has been created and when it is to close.

Any ideas?
Title: A quick question about modal forms and passing information
Post by: TechSupport on April 25, 2005, 03:16:49 PM
Here is one approach that you can use. It uses the internal FireFly APP variable to pass the value to the Form.

In your main Form, set the value of App.ReturnValue and then call your modal Form. The App.ReturnValue must be a Long data type (so you can pass a pointer to a structure if you wish). In your modal Form, you can use the App.ReturnValue in the manner that you require. Set the optional return value for the FF_CloseForm function prior to closing the Form. Your main form will use the return value.

FORM1
--------
App.ReturnValue = 102343
nResult& = Form2_Show( hWndForm, 1)

MsgBox Str$(nResult&)   '<--- should be 999999


FORM2 (Modal)
-----------------
.... manipulate the App.ReturnValue as you require....

FF_CloseForm hWndForm, 999999
Title: A quick question about modal forms and passing information
Post by: Chris Cullen on April 26, 2005, 05:48:53 AM
Thanks for that paul.  This, of course, is not thread safe!  Still, I can use a global to do a similar job.  The alternative I came up with was to rob the code you use to make a form modal, and place some initialisation inside it.  That works, but its messy.  I would have thought that it should be fairly easy to pass a long value during the open form call which could be passed to the create function in the W or L param values.  This then would be completely thread safe and negate the need for any globals etc.

Any news on Cheetah III ?  I am still struggling to find a quick database to lookup stuff (which we do tons of here).  Visual Foxpro still kicks everything into the long grass!  If you need someone to hammer the indexing and searching side of the new development - I'm your man!  8)
Title: A quick question about modal forms and passing information
Post by: Chris Cullen on April 26, 2005, 12:01:30 PM
Just for information, this is how I do what I'm talking about.

Here is an abridged version of a function which gets a date.  It displays a FF form which has a MonthCalendar control on it.  It also has OK and Cancel buttons.  If the user click OK the date is retrieved from the control and the function returns true, othewise the function returns false.

Function popGetDate(ByRef tST As systemtime, hParentWnd As Long) As Long
   Local hWnd As Long
   Local hControl As Long
   Local nTag As Long
   
   hWnd = POPGETDATE_SHOW (hParentWnd , %FALSE)
   hControl = GetDlgItem( hWnd, IDC_POPGETDATE_ODATE)
   SendMessage hControl,%MCM_SETCURSEL, 0,ByVal VarPtr(tST)  
   FF_ModalWhileVisible(hParentWnd, hWnd)
   nTag = GetProp(hWnd,"TAG")
   RemoveProp(hWnd,"TAG")  
   If nTag = 1 Then        ' OK Clicked
       ' get the date value
       SendMessage hControl,%MCM_GETCURSEL, 0,ByVal VarPtr(tST)  
   End If
   FF_CloseForm(hWnd)
   Function = ( nTag = 1 )
   
End Function

Sub FF_ModalWhileVisible(ByVal hWndParent As Long, ByVal hwndForm As Long)
   Local msg            As TAGMSG
 
  ' Disable Mouse and keyboard input for the Parent Form
  If hWndParent <> %HWND_DESKTOP Then EnableWindow hWndParent, %FALSE

  If Not IsWindowVisible(hwndForm) Then
       ShowWindow hWndForm, %SW_SHOWNORMAL
  End If
  ' Creates the oportunity to re-enable the parent before the
  ' form is close, so that it gets focus.
  SetProp(hwndForm,"PARENT_FORM",hWndParent)
  UpdateWindow hWndForm

  ' Main message loop:
  Do While GetMessage(Msg, %Null, 0, 0)    
      'Exit the modal message loop if the Form was destroyed (important).
      If IsFalse IsWindow(hWndForm) Then Exit Do
      If IsFalse IsWindowVisible(hWndForm) Then Exit Do
     
      If msg.message = %WM_QUIT Then Exit Do

      If IsFalse(FF_PUMPHOOK(Msg)) Then
          If IsFalse IsDialogMessage(GetActiveWindow, Msg) Then
             TranslateMessage Msg
             DispatchMessage Msg                    
          End If    
     End If
  Loop  
  If hWndParent <> %HWND_DESKTOP Then EnableWindow hWndParent, %TRUE
 
End Sub


What would be nice would be the ability to have FORM_OPENNOSHOW which would create the window but not make it visible.  Then my FF_ModalWhileVisible function could do lots of stuff before the window appears.  Anyway, the reason for ModalWhileVisible is that a modal form remains modal even if it is not visible!  This function checks that the window is still visible, which allows for the form the be 'closed' but still be available to my function to get values etc.

This kind of programming is used a great deal (at least by me) as it is a simple and elegant way to get a modal form to do a lot of interaction with the user, and have all the results easily passed through into the program.

I would apreciate any comments on the above!  It does work well, but it is a work-around.  It would be great if the create event (message) could simply pass a dword value, which could then point to a structure, which would remove the need for this whole messy business!!!  The problem with using globals (like the App structure) is that it is entirely possible that two of more of these windows could be shown if some of the main app uses threads!  

Cheers

[/b]
Title: A quick question about modal forms and passing information
Post by: TechSupport on April 26, 2005, 03:47:34 PM
Hi Chris,

I have this working now. The "fix" will be in the upcoming update. I have created an optional parameter to the "_Show" function that allows the user to pass a user-defined long value. That value is sent to the WM_CREATE message via the lpParam of the CREATEWINDOWEX api call. Finally, the value is retrieved and sent to the FireFly WM_CREATE message handler.

It all works seamlessly to the user. I hope that it will solve your problem.

:)