There is an internal FireFly function called
FF_CloseForm(); I am trying to get my hands around this function. Is this supposed to be used in leiu of the standard way to close a window:
SENDMESSAGE hWndForm, %WM_SYSCOMMAND, %SC_CLOSE, 0 Or, is this an internal command called instead of
DestoryWindow and we should still close forms using the SENDMESSAGE method. The documentation states:
QuoteThis subroutine must be called whenever you want to close an existing Form.
But, there is no discussion on how clicking the "X" on the caption bar is handled and how to prevent an app from closing.
What I've done, and I want to make sure this is correct, is created the following custom message for my form:
FUNCTION FRMMAIN_CUSTOM( hWndForm AS DWORD, wMsg AS LONG, wParam AS DWORD, lParam AS LONG ) AS LONG
SELECT CASE wMsg
CASE %WM_SYSCOMMAND
IF ( wParam AND %SC_CLOSE ) = %SC_CLOSE THEN
IF MESSAGEBOX( _
hWndForm, _
"Are you sure you wish to exit?", _
"My Program Name", _
%MB_YESNO OR %MB_DEFBUTTON2 OR %MB_ICONQUESTION OR %MB_APPLMODAL ) = %IDNO THEN FUNCTION = 1
END IF
END SELECT
END FUNCTION
My assumtion is the that if "0" is return in that message
FF_CloseForm() will be called internally and a non-0 will prevent any exiting (the latter was tested to work).
Is this correct?
Hi George,
You are on the right track. FF_CloseForm should be used in situations where you would normally use DestroyWindow. If you simply use DestroyWindow then some important internal steps will be missed when trying to reset focus back to the parent Form (in cases where the popup Form was created modally).
The route that you have taken appears correct and you should have no problems with it.
QuoteYou are on the right track. FF_CloseForm should be used in situations where you would normally use DestroyWindow. If you simply use DestroyWindow then some important internal steps will be missed when trying to reset focus back to the parent Form (in cases where the popup Form was created modally).
What about passing a result back to the procedure which created the form in the first place. I notice that the DialogBoxParam API allows a parameter to be passed to the new dialog as the LPARAM of the create method. It is also possible to return a result back to the calling program using the EndDialog. This makes it very easy to create dialogs which are called by functions etc. Do the create and close FF functions make any allowance for this, or is there another way? :?
I am guessing from the above that the open and close FF functions make no allowance for Modal Dialogs in this regard. My questions is really how would I go about makeing a dialog that asks for some information (severl text items and other stuff) and wrap all this in a single function call. Using API you would create a structure with all the elements to hold the stuff, call the DialogBoxParam passing the VARPTR to this structure and then the Dialog would close and return a True/False to the function indicating whether the user click OK or cancel. The dialog would then simply update the stucture using a simple pointer. this way, NO GLOBALS are required. If the only answer is to use a global variable then threading and multi-instance becomes a real pain!
Do you see what I'm after here? Sorry to be so long winded about it. :lol:
Hi Chris,
I understand what you're asking. FireFly uses SDK methods to create modal windows rather than relying on the Dialog Engine (DialogBoxParam ). I see how not having a return value could be a problem.
How about this:
In the main Form, use SetProp to attach a property to the Form.
(e.g. SetProp HWND_FORM1, "MODAL_RESULT").
When the modal Form is open, it will be able to set the "MODAL_RESULT" property prior to you calling FF_CloseForm.
You will also need to remove the property in the WM_DESTROY message of the main form.
Maybe this is no better than a global variable??? Not sure.
Hmmm. I don't like the idea of using one form to carry messages or return values for another. Here's what I did in the end! - Promise you won't laugh!!! :D
Function GetConfigFile(hWnd As Long) As String
' Open the form modal and wait for the buttons to be clicked, whereupon the form gets hidden and
' my code then continues!! We hope!
Local hDlg As Long
hDlg = FRMSETCONFIG_SHOW(hWnd,0)
' We need to disable the parent window so we are pretending to be a modal dialog box!
EnableWindow hWnd, %FALSE
' At this point, I could send a message (WM_USER+xxx) to pass any parameters as needed
' to the form. I could also send the address of a variable which the dialog could maintain
' during its use. I do not need this here, as this dialog is very simple.
Do While IsWindowVisible(hDlg)
' Simple loop to emulate a message pump which terminates when the dialog becomes hidden
' which it does when either the OK or CANCEL button is clicked. I also have a hidden text
' box which holds OK or Cancel depending upon which button was clicked.
FF_DoEvents
Sleep 100
Loop
' Dialog is now no longer visible
' So we can re-enable the main form
' and then sort out what the user did!
If FF_Control_GetText(HWND_FRMSETCONFIG_TXTTAG) = "OK" Then
' The user clicked the OK button, so we can return the contents of the text box
Function = FF_Control_GetText(HWND_FRMSETCONFIG_TXTSOURCEFILE)
Else
Function = ""
End If
' Now kill the dialog the FF way!
FF_CloseForm(hDlg)
EnableWindow hWnd, %TRUE
SetActiveWindow hWnd
End Function
This way, I can still get to all the controls and the form, and that way, any number of bits of informaiton can be handled. It does also allow the function to be completely self contained. I can also use the timie before my 'message pump' to send messages to configure the dialog box or set initial values etc (which I use in another similar function). So far, this works. The only problem is that the at the time the buttons hide the dialog and allow my process to continue, the form that I want to return to is disabled!!! That is what all the enablewindow,setactivewindow is about and makes the app a bit flicky! I could alway set a parent window in the dialog which it would enable before the dialog hides, but thats for when I have the time! I could also use setprop rather than a hidden text box, but the text was the first thing I though of!!
Thanks for your help though. :)