none
[VB.NET] Moving the window using an image box?

    Question

  • I'm trying to make a custom GUI and I made the title bar on MS paint and have it all setup all i need it the code snippit to make the window move when the image is draged to different places. Help please!
    Sunday, August 15, 2010 12:07 AM

Answers

  • In VB6 I mostly used the Sendmessage API to move a form with the mouse as it is a simple call, the only real difference is the mouse up is detected after the sendmessage call.

    In VB.net the API declares are different so I had to search for an example myself to even try it in VB10. So here is using a picture box to move the form, which seems to work just fine like it did for me in VB6.

    If anyone has a better pure .net way to do this I am all ears. Going from VB6 to VB10 is a whole different world!

    Public Class Form1
      Private Declare Function SendMessageW Lib "User32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
      Private Declare Sub ReleaseCapture Lib "User32.dll" () 'Releases the mouse capture from a window in the current thread and restores normal mouse input processing. 
      Private Const WM_NCLBUTTONDOWN As Integer = &HA1 ' the window message [look it up ;) ]
      Private Const HT_CAPTION As Integer = 2 ' Hit_Test: title bar (Caption)
    
      Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then ' ignore if not left mouse button
          ReleaseCapture() 'Release mouse capture/restore normal mouse input processing
          SendMessageW(Me.Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0) ' move this form (Me.hWnd)
    
          ' [ Detect "MouseUp" here, not in PictureBox1_MouseUp ;) ]
        End If
      End Sub
    End Class

    Sunday, August 15, 2010 9:02 AM

All replies

  • In VB6 I mostly used the Sendmessage API to move a form with the mouse as it is a simple call, the only real difference is the mouse up is detected after the sendmessage call.

    In VB.net the API declares are different so I had to search for an example myself to even try it in VB10. So here is using a picture box to move the form, which seems to work just fine like it did for me in VB6.

    If anyone has a better pure .net way to do this I am all ears. Going from VB6 to VB10 is a whole different world!

    Public Class Form1
      Private Declare Function SendMessageW Lib "User32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
      Private Declare Sub ReleaseCapture Lib "User32.dll" () 'Releases the mouse capture from a window in the current thread and restores normal mouse input processing. 
      Private Const WM_NCLBUTTONDOWN As Integer = &HA1 ' the window message [look it up ;) ]
      Private Const HT_CAPTION As Integer = 2 ' Hit_Test: title bar (Caption)
    
      Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then ' ignore if not left mouse button
          ReleaseCapture() 'Release mouse capture/restore normal mouse input processing
          SendMessageW(Me.Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0) ' move this form (Me.hWnd)
    
          ' [ Detect "MouseUp" here, not in PictureBox1_MouseUp ;) ]
        End If
      End Sub
    End Class

    Sunday, August 15, 2010 9:02 AM
  • You cannot do it while you see the code for that custom Gui before your nose.

    How would you think we could do it. 

    As soon as you make something custom then you are mostly at your own, these forums handle problems which arise with general programming.

    But you can try it by explaining better how you made that custom Gui, made the title bar with MS Paint and how you did the setup.

     


    Success
    Cor
    Sunday, August 15, 2010 9:07 AM
  • You could do it by checking where the mouse is in the mouseDown event, and changing the Forms location in the mouse Move event - but it's a bit complicated.

    You can do it by messing with the windows messages that the form receives. You can intercept windows messages by overriding WndProc. Messages are the low-level way that windows tells a form what the user has been doing, or to ask the form to do something. In .Net the messages are often turned into Form events. So you get a low level message saying "the left mouse button just went down", and .Net converts it to the MouseDown event.

    We want to intercept the WM_NCHITTEST message - non-client hit test. This message sends to the form the location of the mouse, and the form sends back a value telling windows what sort of bit of the form that point is over. It's like "Hey form, here's a point, what do you have at that point?". So if the point is over the title bar, the form should send back HT_CAPTION to say "that point is on my caption".

    By overriding WndProc you can filter the messages and change the result. So - we can intercept the WM_NCHITTEST message, see what the form is currently going to send back, and if it is HT_CLIENT which means "the mouse is over the client area of the form", AND the point is actually over the custom title bar, then you change the result to HT_CAPTION:

    Public Class Form1
    
      Private awfulTitleBarBounds As Rectangle
    
      Sub New()
    
        ' This call is required by the designer.
        InitializeComponent()
    
        ' Add any initialization after the InitializeComponent() call.
        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
      End Sub
    
      Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
        awfulTitleBarBounds = New Rectangle(10, 10, Me.ClientSize.Width - 20, 30)
        MyBase.OnResize(e)
      End Sub
    
      Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        e.Graphics.FillRectangle(Brushes.SeaGreen, awfulTitleBarBounds)
        TextRenderer.DrawText(e.Graphics, "Awful Title Bar", New Font("Comic Sans MS", 12), awfulTitleBarBounds, Color.Magenta, Color.Transparent, TextFormatFlags.Left)
      End Sub
    
      Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        MyBase.WndProc(m)
        If m.Msg = &H84 AndAlso m.Result = New IntPtr(1) Then      
          Dim loc As Point = Me.PointToClient(New Point(m.LParam.ToInt32 And &HFFFF, m.LParam.ToInt32 >> 16))
          If awfulTitleBarBounds.Contains(loc) Then m.Result = New IntPtr(2)
        End If
      End Sub
    
      Private Sub Form1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.DoubleClick
        ' have some way to close it
        Me.Close()
      End Sub
    End Class
    
    

    All you need is the WndProc bit, the rest is just for the demo. Instead of using awfulTitleBarBounds you need to use a rectangle that defines the bounds of your title bar.

    The magic values I used are:
    WM_NCHITTEST = &H84
    HT_CAPTION = 2
    HT_CLIENT = 1

    LParam contains the point in screen co-ordinates - the lo word contains X, the hi word contains Y.

    Sunday, August 15, 2010 1:19 PM