Using PostMessage to send a WM_CLOSE message to an Access Application Window versus using DoCmd.Qui

W

Wayne Pearson

Hi,





I posted earlier regarding DoCmd.Quit, Dynamic Array, Form_Unload, Variable
Cleanup. If a form has a dynamic array member variable, which has been
dimensioned and populated, and DoCmd.Quit is called prior to unloading the
form then the dynamic array member variable will be destroyed BEFORE
Form_Unload is called.





Since this posting I've discovered that if I replace DoCmd.Quit with



PostMessage Application.hWndAccessApp, WM_CLOSE, &H0&, &H0&



then cleanup of dynamic array variables seems to occur as expected (at least
in the sense that they are not destroyed before Form_Unload).



Posting a WM_CLOSE message to the Access Application Window appears to
result in an orderly shutdown of all child windows (their form unload events
are invoked and valid member variables are still present in Form_Unload).





Are there any caveats to using



PostMessage Application.hWndAccessApp, WM_CLOSE, &H0&, &H0& versus
DoCmd.Quit?





I created a simple application to demonstrate the above behavior and its
code appears at the end.



The application has two forms frmPrimary and frmSecondary and a module
APIDefs.



frmPrimary has two buttons, a Display button and an Exit button. Clicking
the Display button invokes cmdDisplay_Click, which then displays
frmSecondary. Clicking the Exit button invokes cmdExit_Click, which then
calls DoCmd.Quit.



frmSecondary has a member variable m_Numbers, which is a dynamic array of
type Long.



When frmSecondary is displayed, its Form_Load event procedure dimensions the
dynamic array m_Numbers to be 2 elements long and populates it. When
frmSecondary is closed its Form_Unload event procedure prints the values in
m_Numbers to ensure they are present.



APIDefs provides definitions for PostMessage and WM_CLOSE.



If I open frmPrimary, press its Display button to open frmSecondary, and,
finally, press frmPrimary's Exit button to end the application then I get a
subscript out of range error in frmSecondary's Form_Unload event procedure.
It appears that m_Numbers is already destroyed before Form_Unload is called.



Changing frmPrimary's cmdExit_Click to call DoCmd.Close and then creating a
Form_Unload event procedure for frmPrimary and having it call DoCmd.Quit
does not remedy this problem.



However replacing DoCmd.quit in in frmPrimary's cmdExit_Click with



PostMessage Application.hWndAccessApp, WM_CLOSE, &H0&, &H0&



does appear to solve the problem. frmSecondary's m_ Numbers member variable
is NOT destroyed prior to calling Form_Unload and things appear to work as
expected.



Note that PostMessage is used here and NOT SendMessage. Using SendMessage
results in a subscript out of range error in frmSecondary's Form_Unload
event routine.





I would be interested in any comments on what might cause this behavior -
the application code is given in its entirety below.







'------------------------------------------------ Start of
Code --------------------------------------------------



'------------------------------------------ Start of frmPrimary
Code ------------------------------------------

Option Compare Database

Option Explicit



Private Sub cmdDisplay_Click()

DoCmd.OpenForm "frmSecondary"

End Sub



Private Sub cmdExit_Click()

' Using DoCmd.Quit results in a subscript out of range error in
frmSecondary's Form_Unload

' event routine



DoCmd.Quit



' Using PostMessage, however, allows the application to exit gracefully

' Note that PostMessage is used here and NOT SendMessage. Using
SendMessage results in a

' subscript out of range error in frmSecondary's Form_Unload event
routine.

'

' PostMessage Application.hWndAccessApp, WM_CLOSE, &H0&, &H0&

End Sub

'------------------------------------------ End of frmPrimary
Code -------------------------------------------





'---------------------------------------- Start of frmSecondary
Code -----------------------------------------

Option Compare Database

Option Explicit



'm_Numbers is a dynamic array of longs

Dim m_Numbers() As Long



Private Sub Form_Load()

Dim idx As Long





'm_Numbers dimensioned to 2 elements in Form_Load

ReDim m_Numbers(0 To 1)



'm_Numbers gets populated here

For idx = LBound(m_Numbers) To UBound(m_Numbers)

m_Numbers(idx) = idx

Next idx

End Sub



Private Sub Form_Unload(Cancel As Integer)

Dim idx As Long





'Error here - Subscript out of range - why?

For idx = LBound(m_Numbers) To UBound(m_Numbers)

Debug.Print "Form Unload " & CStr(m_Numbers(idx))

Next idx

End Sub

'---------------------------------------- End of frmSecondary
Code ------------------------------------------





'------------------------------------------ Start of Module
APIDefs --------------------------------------------

Option Compare Database

Option Explicit



Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal
hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As
Long) As Long



Public Const WM_CLOSE = &H10

'------------------------------------------ End of Module
APIDefs ---------------------------------------------



'------------------------------------------------ End of
Code ---------------------------------------------------





Thanks,



Wayne Pearson
 
T

TC

It's an interesting finding.

If WM_CLOSE is the message that it normally gets, when the user clicks the
close box in the user interface, I don't see why there should be any
problems with what you propose. However, I'm no expert on the internals of
win32 programming, so maybe there's a hidden gotcha that I don't see.

TC
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top