How to catch WM_MOVING message

Jashin_212

New member
Local time
Today, 11:34
Joined
Jan 3, 2016
Messages
2
Dear All,

I am new to this forum, so thank you in advance for your help with this thread.

I am trying to solve what I think is an age-old problem with Access Forms. I am developing a database where a pop-up main form opens several other pop-up forms that I want to remain within the border of the main form. When the main form is moved or resized I need to move and resize also the other open forms accordingly. I am basically trying to give my database a look similar to a real application where a main form has several child forms.

I am using the event Detail_Paint() to detect when the main form is changed in size to adjust the size of the other forms and it seems to work. However there is no event associated with the movement on screen of the form. MouseMove() does not seem to work because when the user moves the mouse curson on the form caption it doesn't fire. I have solved the problem using a Timer that checks every 10 ms the position of the main form and changes the position of the other forms accordingly. However, this creates an annoying flickering of the monitor and also problems when the user is entering text in the controls.

I have read that is possible to subclass the form and catch the WM_MOVING message to the window. I have developed some test code for this but when I try to run it Access stops working and I have to use the Task Manager to shut it down. I am using Access 2016 Professional 64bit on a Windows 10 64bit system.

Here is the code I have written so far.

' This code goes into a general module (mdl_subclass)
' When subclassing shows the coordinates of the window in its caption

Option Explicit

Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" _
(ByVal hWnd As LongPtr, _
ByVal nIndex As LongPtr, _
ByVal dwNewLong As LongPtr) As LongPtr

Declare PtrSafe Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As LongPtr, _
ByVal hWnd As LongPtr, _
ByVal Msg As LongPtr, _
ByVal wParam As LongPtr, _
ByVal lParam As LongPtr) As LongPtr

Public Const GWL_WNDPROC = (-4)
Private Const WM_MOVE = &H3

Dim m_PrevProc As LongPtr

Public Sub SubClass_On(ByVal hWnd As Long)
m_PrevProc = SetWindowLongPtr(hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub

Public Sub SubClass_Off(ByVal hWnd As Long)
SetWindowLongPtr hWnd, GWL_WNDPROC, m_PrevProc
End Sub

Private Function WindowProc(ByVal hWnd As LongPtr, ByVal uMsg As LongPtr, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr

WindowProc = CallWindowProc(m_PrevProc, hWnd, uMsg, wParam, lParam)

If uMsg = WM_MOVE Then

Form_frm_main.Me_OnMove lParam And CLng(&HFFFF&), lParam \ CLng(&HFFFF&)

End If

End Function


' This code instead goes into the form module, starts subclassing on form loading and stop subclassing on form unload

Private Sub Form_Load()

SubClass_On Me.hWnd

End Sub

Private Sub Form_Unload(Cancel As Integer)

SubClass_Off Me.hWnd

End Sub


Friend Sub Me_OnMove(ByVal xPos As Long, ByVal yPos As Long)

Me.Caption = "x=" & xPos & "; y=" & yPos

End Sub

...any idea on how to fix my code? Or any alternative suggestions to my problem?

Thanks
 
Thank you for your help.

I have actually find a solution to my problem. What I am trying to recreate is an MDI working environment with Access Forms. I have found a Windows API function that allows to directly set the child property of a form. The function is called SetParent() and is in the user32.dll library. If you call this function from the Form_Open() event it will open that form as a child of any other specified form. Therefore Windows will do the movement of the child form with the main form whenever is needed. The final effect is very nice.

Of course subclassing a form a way more complex than my solution. However, MS Access doesn't seem to like it and if it makes it unstable it is useless because I will not be able to distribute my database.

Thanks for your help.

Cheers
 

Users who are viewing this thread

Back
Top Bottom