People have posted code to drag a borderless form using a Windows Message, both on this forum and in the CodeBank. This method has a drawback: you can't drag the form higher than the top of the screen -- or rather you can, but it immediately flips back again when you release the mouse button. I would like to change that behaviour.

After some time poring over the stream of windows messages, I found that the flip-back occurs whenever there is a WM_CAPTURECHANGED message immediately followed by a WM_WINDOWPOSCHANGING. The latter message contains a pointer to a WINDOWPOS Structure in its LParam field. Apparently it is possible to annul the impending change of position by setting the NOMOVE flag of that WINDOWPOS.

Here's how I've defined WINDOWPOS:
vb.net Code:
  1. <System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)> _
  2.     Public Structure WindowPos
  3.         Public hWnd As IntPtr
  4.         Public hWndInsertAfter As IntPtr
  5.         Public x As Integer
  6.         Public y As Integer
  7.         Public w As Integer
  8.         Public h As Integer
  9.         Public flags As UInt32
  10.     End Structure

Here's my WndProc Sub:
vb.net Code:
  1. Private DontMove As Boolean
  2.    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
  3.         If Me.Top < 0 Then
  4.             If m.Msg = WM_CAPTURECHANGED Then
  5.                 DontMove = True
  6.             ElseIf m.Msg = WM_WINDOWPOSCHANGING AndAlso DontMove = True Then
  7.                 Dim wPos As WindowPos = DirectCast(m.GetLParam((New WindowPos).GetType), WindowPos)
  8.                 wPos.flags = wPos.flags Or CUInt(SWP_NOMOVE)
  9.                 m.LParam = New IntPtr(AddressOf wPos)
  10.                 DontMove = False
  11.             Else
  12.                 DontMove = False
  13.             End If
  14.         End If  
  15.         MyBase.WndProc(m)
  16. End Sub
I have two syntax problems here. Line 7 gets past the syntax checker but it seems a rather elaborate way to get the WINDOWPOS. I'm not even sure if it works yet. Is there a more direct way to get the structure through the LParam pointer? Line 9 gives a syntax error because AddressOf apparently requires a method as its argument. Is there another way to set m.LParam to point at my modified WINDOWPOS structure?

Advice and any comments gratefully received. BB