When you send a WM_CLOSE message to a window, it tries to close the window as if the X button were pressed. This causes the UnloadMode to set to 0. You cannot know whether the application was closed externally or by clicking the X button; by looking only at the UnloadMode parameter.
But there is an easy alternative. When you are closing the window externally using WM_CLOSE, you can initialize its 32-bit user data value using the SetWindowLong function before sending the message. In the target application (being closed) you will query this user data using GetWindowLong function and execute your code accordingly.
The user data value is set to 0 by default. You can set it to any non-zero value before sending the WM_CLOSE message.
See how it goes. Below is the code for the application trying to close the window.
___
[tt]
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Const WM_CLOSE = &H10
Const GWL_USERDATA = -21
...
'code to close the target window (CurrApp)
'
'Set the user data value of the target window to -1
'(originally 0)
SetWindowLong CurrApp, GWL_USERDATA, -1
'send closing messgae
SendMessage CurrApp, WM_CLOSE, 0, ByVal 0&[/tt]
___
In the QueryUnload event of the target window, you would check the user data value something like this...
___
[tt]
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Const GWL_USERDATA = -21
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If GetWindowLong(hwnd, GWL_USERDATA) = 0 Then
MsgBox "Closing from X."
Else '(if -1)
MsgBox "Closing externally using WM_CLOSE."
End If
End Sub[/tt]
___
Checked this method on my machine and its works fine.