Common source codes between WM_CLOSE notification message and a "Close" button

Started by Jean-pierre Leroy, January 06, 2014, 06:34:39 AM

Previous topic - Next topic

Jean-pierre Leroy

Dear all,

Usually end users can close a FORM either by ...

1. Clicking on the close button(cross icon) on the system menu
2. Using the keyboard short cut ALT-F4
=> For these both cases the WM_CLOSE notification is raised

3. Clicking on a specific "Close" button (if there is one) on the form
In this case the function FORM1_CLOSE_BN_CLICKED is used to manage the close event.

In many cases the source codes are usually the same for the WM_CLOSE function and the CLOSE_BN_CLICKED function; so to avoid duplicating the source code I simulate a click on the "Close" button inside the WM_CLOSE notification function :


'--------------------------------------------------------------------------------
Function FORM1_WM_CLOSE ( _
                        hWndForm As Dword _  ' handle of Form
                        ) As Long
                       
    ' simulate a click on the Close button
    SendMessage hWndForm, %WM_COMMAND, MakLng(IDC_FORM1_CLOSE,%BN_CLICKED), HWND_FORM1_CLOSE   
   
    ' to cancel the WM_CLOSE notification
    Function = -1                                                                                   

End Function


And then write the code to close (or not) the FORM inside the FORM1_CLOSE_BN_CLICKED function:


'--------------------------------------------------------------------------------
Function FORM1_CLOSE_BN_CLICKED ( _
                                ControlIndex     As Long,  _  ' index in Control Array
                                hWndForm         As Dword, _  ' handle of Form
                                hWndControl      As Dword, _  ' handle of Control
                                idButtonControl  As Long   _  ' identifier of button
                                ) As Long
   
    Local lResult As Long

    ' to ask for a confirmation
    lResult = MessageBox(hWndForm, "Leave the form ?" & $CrLf, "Close Form", %MB_YESNO Or %MB_DEFBUTTON2 Or %MB_ICONQUESTION Or %MB_APPLMODAL)               
       
    ' if the user decides to stay on the form
    If lResult = %IDNO Then Exit Function   
   
    ' close the current form
    FF_CloseForm (hWndForm)                               

End Function


I would like to know if it is a good practice (or not) to do that ? Is-there any other way to achieve the same thing ? I don't remember if this subject was already discussed in the past in the FF forum.

PS: In this sample project, there are not a lot of common source codes; but in a real project, we have to check fields, to update databases, etc ...

Thanks.
Jean-Pierre

Eddy Van Esch

Jean-Pierre,
I would do it the other way around because it seems simpler to me:


Function FORM1_WM_CLOSE ( _
                             hWndForm As Dword _  ' handle of Form
                             ) As Long

    Local i As Long
   
    i = MsgBox("Close this form?", %MB_YESNO Or %MB_DEFBUTTON2 Or %MB_TASKMODAL Or %MB_ICONQUESTION, "????")
    If i = %IDNO Then
            'Don't close this form
        Function = 1
    Else
            'Close this form
        Function = 0
    End If
   
End Function


A Close/Exit button must generate a WM_CLOSE message (see the below code) because FF_CloseForm()  does not send a WM_CLOSE message to the form (only a WM_DESTROY):

Function FORM1_CMDCLOSEFORM_BN_CLICKED ( _
                                            ControlIndex     As Long,  _  ' index in Control Array
                                            hWndForm         As Dword, _  ' handle of Form
                                            hWndControl      As Dword, _  ' handle of Control
                                            idButtonControl  As Long   _  ' identifier of button
                                            ) As Long


    'FF_CloseForm hWndForm, %TRUE    'But FF_CloseForm does not send a WM_CLOSE message to the form (only a WM_DESTROY),

    SendMessage hWndForm, %WM_CLOSE, 0, 0
End Function


Kind regards
Eddy
Eddy

David Kenny

Jean-pierre,

I would create a function that contains the common code and just call it from each of the two FF functions you mentioned.

But, I don't see anything wrong with the way you or Eddy are doing it. There's more than one way to skin a cat (kind of a morbid old saying).

David

Eddy Van Esch

Jean-Pierre,
An improvement to my original post:
Probably FF likes it better when FF_CloseForm is called:

Function FORM1_WM_CLOSE ( _
                             hWndForm As Dword _  ' handle of Form
                             ) As Long

    Local i As Long
   
    i = MsgBox("Close this form?", %MB_YESNO Or %MB_DEFBUTTON2 Or %MB_TASKMODAL Or %MB_ICONQUESTION, "????")

    If i = %IDYES Then
            'Close this form
        FF_CloseForm hWndForm, %TRUE   
    End If
   
    Function = 1
End Function
Eddy

Jean-pierre Leroy

Eddy, Kenny,
Thanks I appreciate your answers.

Eddy,
Yes you're right it is clearly more elegant and simpler to do it the other way around.

NB: Regarding the call to the FF_CloseForm function inside the WM_CLOSE handler function I don't know if it is mandatory, optionnal, recommanded or useless; I think that Paul can help us here on this question.

Regards,
Jean-Pierre




Eddy Van Esch

Quote from: Jean-pierre Leroy on January 06, 2014, 07:51:14 AM
Regarding the call to the FF_CloseForm function inside the WM_CLOSE handler function I don't know if it is mandatory, optionnal, recommanded or useless; I think that Paul can help us here on this question.
The use of FF_CloseForm is probably 'highly recommended' in most cases because it does some cleaning up for us.
Here's what it (currently) does:


Sub FF_CloseForm( ByVal hwndForm As Dword, _
                  Optional ByVal ReturnValue As Long )
   
    If IsWindow( hWndForm ) = %FALSE Then Exit Sub
   
    Local hWndParent As DWord

    Local ff As FLY_DATA Ptr
    ff = GetProp(hwndForm, "FLY_PTR")

    If ff Then
      If @ff.IsModal Then 
         ' Reset the focus back to the parent of the modal form.
         ' Enable Mouse and keyboard input for the Parent Form
         hWndParent = GetWindowLong( hWndForm, %GWL_HWNDPARENT )
         If IsWindow(hWndParent) then
            EnableWindow hWndParent, %TRUE
            SetActiveWindow hWndParent
         End If   
      End If               
    End If
   
    'Destroy the window. This will delete any font objects and release
    'the memory held by the type structure.
    DestroyWindow hWndForm
   
    'Set the value that will be returned to the calling program.
    App.ReturnValue = ReturnValue
End Sub 
Eddy