11 Replies - 4795 Views - Last Post: 19 May 2019 - 10:45 AM Rate Topic: -----

#1 razal   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 09-October 14

Moving WinForm without Title Bar

Posted 12 October 2014 - 06:47 AM

Greetings!

How can I move a Windows Form around the screen using the mouse, if I don't want it to have any Title Bar? Can I click and drag over the background somehow? I know how to set the position of the Form like this Me.Location = New Point(100, 100) but I don't know how to update it i real time when the mouse moves. Any help will be appreciated!
Is This A Good Question/Topic? 0
  • +

Replies To: Moving WinForm without Title Bar

#2 rusoaica   User is offline

  • They're watching you, Neo!
  • member icon

Reputation: 220
  • View blog
  • Posts: 691
  • Joined: 10-March 12

Re: Moving WinForm without Title Bar

Posted 12 October 2014 - 07:03 AM

You need to declare some class-level variable that can hold your X and Y position values, as well as a boolean variable that will indicate whether the form is being dragged or not. Something like this:

Private IsFormBeingDragged As Boolean = False
Private MouseDownX As Integer
Private MouseDownY As Integer



Then, in the MouseDown event of your form, we need to keep the original position of the window, and also, indicate that we are about to drag the form:

If e.Button = MouseButtons.Left Then
     IsFormBeingDragged = True
     MouseDownX = e.X
     MouseDownY = e.Y
End If



We used e.Button = MouseButtons.Left because we want to move it around only when we drag it when we use the left mouse button. If you want to drag it with either buttons, remove the If statement.

Next thing to do, we need to update the position of the form while we drag it with the mouse. This peace of code is placed in the MouseMove event of the form:

If IsFormBeingDragged Then
     Dim temp As Point = New Point()
     temp.X = form.Location.X + (e.X - MouseDownX)
     temp.Y = form.Location.Y + (e.Y - MouseDownY)
     MyForm.Location = temp
     temp = Nothing
End If



Finally, in the MouseUp event of the form, we need to switch the boolean variable that tells if the form is being dragged or not:

If e.Button = MouseButtons.Left Then
     IsFormBeingDragged = False
End If



To make your form without a title bar, you can use

MyForm.FormBorderStyle = Windows.Forms.FormBorderStyle.None



Hope this helps!
Was This Post Helpful? 1
  • +
  • -

#3 razal   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 09-October 14

Re: Moving WinForm without Title Bar

Posted 12 October 2014 - 07:19 AM

What do you mean class-level variable?

This post has been edited by andrewsw: 12 October 2014 - 09:43 AM
Reason for edit:: Removed large quote, just press the REPLY button

Was This Post Helpful? 0
  • +
  • -

#4 rusoaica   User is offline

  • They're watching you, Neo!
  • member icon

Reputation: 220
  • View blog
  • Posts: 691
  • Joined: 10-March 12

Re: Moving WinForm without Title Bar

Posted 12 October 2014 - 07:33 AM

A class-level variable (or a "field variable") is a variable that is declared outside of any property, method, function, etc. It is declared inside the class itself, thus being visible to all the methods inside that class. Quick example of a class-level variable and a "local" variable:

Class MyClass
   Dim ClassLevelVariable As Integer

   Private Sub SomeSub
      Dim LocalVariable As Integer
   End Sub

   Private Sub SomeOtherSub
      ClassLevelVariable = 1 'this will work
      LocalVariable = 1 'this will not work
   End Sub
End Class



The reason why LocalVariable cannot be "seen" inside the second method is because it is declared inside the first Sub and it can only be used inside that Sub. ClassLevelVariable is declared outside of any Sub, so it can be seen in every Sub of that class. You can read more about variable scope.
Was This Post Helpful? 1
  • +
  • -

#5 razal   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 09-October 14

Re: Moving WinForm without Title Bar

Posted 12 October 2014 - 07:59 AM

View Postrusoaica, on 12 October 2014 - 07:33 AM, said:

A class-level variable (or a "field variable") is a variable that is declared outside of any property, method, function, etc. It is declared inside the class itself, thus being visible to all the methods inside that class. Quick example of a class-level variable and a "local" variable:

Class MyClass
   Dim ClassLevelVariable As Integer

   Private Sub SomeSub
      Dim LocalVariable As Integer
   End Sub

   Private Sub SomeOtherSub
      ClassLevelVariable = 1 'this will work
      LocalVariable = 1 'this will not work
   End Sub
End Class



The reason why LocalVariable cannot be "seen" inside the second method is because it is declared inside the first Sub and it can only be used inside that Sub. ClassLevelVariable is declared outside of any Sub, so it can be seen in every Sub of that class. You can read more about variable scope.


OK, it works! :bananaman:
One last question what means temp.X = form.Location.X + (e.X - MouseDownX)? What does it do?
Was This Post Helpful? 0
  • +
  • -

#6 rusoaica   User is offline

  • They're watching you, Neo!
  • member icon

Reputation: 220
  • View blog
  • Posts: 691
  • Joined: 10-March 12

Re: Moving WinForm without Title Bar

Posted 12 October 2014 - 08:09 AM

that piece of line is the line that updates the new X position of the form, while you move the mouse. In this code:

Dim temp As Point = New Point()
     temp.X = form.Location.X + (e.X - MouseDownX)
     temp.Y = form.Location.Y + (e.Y - MouseDownY)
     MyForm.Location = temp



we have declared a new Point and we position the form to that Point. In the calculus, we add to the actual position of the form - form.Location.X - the difference between the new X and Y position of the mouse, minus the last position of the mouse. That difference will actually give us the distance that the form was being dragged, which can be positive or negative, depending on which direction the form was being dragged.

This post has been edited by rusoaica: 12 October 2014 - 08:11 AM

Was This Post Helpful? 1
  • +
  • -

#7 razal   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 09-October 14

Re: Moving WinForm without Title Bar

Posted 12 October 2014 - 08:27 AM

View Postrusoaica, on 12 October 2014 - 08:09 AM, said:

that piece of line is the line that updates the new X position of the form, while you move the mouse. In this code:

Dim temp As Point = New Point()
     temp.X = form.Location.X + (e.X - MouseDownX)
     temp.Y = form.Location.Y + (e.Y - MouseDownY)
     MyForm.Location = temp



we have declared a new Point and we position the form to that Point. In the calculus, we add to the actual position of the form - form.Location.X - the difference between the new X and Y position of the mouse, minus the last position of the mouse. That difference will actually give us the distance that the form was being dragged, which can be positive or negative, depending on which direction the form was being dragged.


OK so e.X and e.Y is the position of the mouse?
Was This Post Helpful? 0
  • +
  • -

#8 rusoaica   User is offline

  • They're watching you, Neo!
  • member icon

Reputation: 220
  • View blog
  • Posts: 691
  • Joined: 10-March 12

Re: Moving WinForm without Title Bar

Posted 12 October 2014 - 08:37 AM

In this context, yes. Many events have one or two parameters passed to them, sender and e. Sender is the actual object that generated the event. In this case, the sender is the form itself, because when we clicked it, it generated the MouseDown event. So, sender can be used to identify who fired the event. The other parameter, e is the variable that defines any arguments for the event. Depending on the event, it can have a number of methods and properties. In our case, it has two properties: e.X and e.Y, because it is a mouse event, and mouse cursor is defined by its x and y position. For instance, in the KeyDown event of your form, you can't use e.X, because the keys don't have an X position. Instead, you can use e.KeyCode, to identify which key was pressed.

By the way, you don't have to quote me every time you make a reply. There is a "Reply" button down the page.
Was This Post Helpful? 1
  • +
  • -

#9 razal   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 09-October 14

Re: Moving WinForm without Title Bar

Posted 12 October 2014 - 08:41 AM

You helped me a lot, thank you! :rolleyes:
Was This Post Helpful? 0
  • +
  • -

#10 rusoaica   User is offline

  • They're watching you, Neo!
  • member icon

Reputation: 220
  • View blog
  • Posts: 691
  • Joined: 10-March 12

Re: Moving WinForm without Title Bar

Posted 12 October 2014 - 08:44 AM

You are welcome!
Was This Post Helpful? 0
  • +
  • -

#11 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1538
  • View blog
  • Posts: 3,869
  • Joined: 01-February 13

Re: Moving WinForm without Title Bar

Posted 12 October 2014 - 06:06 PM

Hi,
I know you have solved your problem already but, i just wanted to add another option that you or someone else may want to use for moving a borderless Form. It also has other benefits that i will get to in a minute.

You can use the WndProc Overrides Sub to filter the Window Messages that are sent to the Form. There are Window Messages for the WM_LBUTTONDOWN and WM_MOUSEMOVE that can be filtered and used to detect when the left mouse button is pressed down or when the mouse moves within the form`s bounds.

In this example i have set a few of the forms properties in the Form.Load event just to show what i have set. You can set them in the Forms Design tab instead of the Load event though. I also commented it to help understand what the code is doing. When you understand it and get rid of the comments it will look a lot shorter.

Public Class Form1
    Private Const WM_MOUSEMOVE As Integer = &H200 '  Window Message values for the MouseMove
    Private Const WM_LBUTTONDOWN As Integer = &H201 ' and the LeftButtonDown messages
    Private Const MK_LBUTTON As Integer = &H1 'This one is used with the MouseMove message to detect if the left button is down
    Private OffSet As Point = Point.Empty

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.DoubleBuffered = True
        Me.FormBorderStyle = FormBorderStyle.None
        Me.Width = 300
        Me.Height = 180
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        '   check if the Window Message being sent to this window is equal to the WM_LBUTTONDOWN constant value
        If m.Msg = WM_LBUTTONDOWN Then
            OffSet.X = MousePosition.X - Me.Location.X 'get the width between the mouse`s X location and the form`s X location
            OffSet.Y = MousePosition.Y - Me.Location.Y 'get the height between the mouse`s Y location and the form`s Y location

            'check if the Window Message being sent to this window is equal to the WM_MOUSEMOVE constant value. Also,
            'using the integer value of the WParam of the window message you can make sure the left mouse button is
            'down while the mouse is moving by checking if it is equal to the MK_LBUTTON constant value
        ElseIf m.Msg = WM_MOUSEMOVE AndAlso m.WParam.ToInt32 = MK_LBUTTON Then
            Me.Left = MousePosition.X - OffSet.X 'set the Left(X) location of this window to the mouse`s X location minus the offset X value
            Me.Top = MousePosition.Y - OffSet.Y 'set the Top(Y) location of this window to the mouse`s Y location minus the offset Y value
        End If
        MyBase.WndProc(m) 'This is added by default. It is used to pass the message to the form`s base class
    End Sub
End Class



Now for the other benefits i mentioned. When you use the WndProc Sub to filter the windows messages for moving the Form it does not take to much more code to filter the WM_NCHITTEST message to make your Borderless Form sizable also. When this message is sent to your Form you can return the Result as one of the Hit Test Message Values to make it show and use the Sizing Arrows around the outside edges of the form.

To do this you can add these Constants for the Hit Test Messages.
    Private Const WM_NCHITTEST As Integer = &H84
    Private Const HTLEFT As Integer = &HA
    Private Const HTRIGHT As Integer = &HB
    Private Const HTTOP As Integer = &HC
    Private Const HTTOPLEFT As Integer = &HD
    Private Const HTTOPRIGHT As Integer = &HE
    Private Const HTBOTTOM As Integer = &HF
    Private Const HTBOTTOMLEFT As Integer = &H10
    Private Const HTBOTTOMRIGHT As Integer = &H11



Then change the WndProc Sub`s code like this to filter the Hit Test Messages. This will show and use the Sizing cursors on all sides and the corners also. You can easily pick and choose the sides and or corners you want to use if you don`t want it on all of them. For example, if you use the Transparency key of the form to make it transparent and draw the form with rounded corners using the Form`s Paint event you will not be able to use the Hit Test on the corners so, that code could be removed.
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg = WM_NCHITTEST Then

            'Get the X, Y location of the mouse
            Dim loc As New Point(m.LParam.ToInt32 And &HFFFF, m.LParam.ToInt32 >> 16)
            loc = PointToClient(loc) 'compute the mouse location to the forms client coordinantes 

            Dim bTop As Boolean = (loc.Y < ClientRectangle.Y + 4) ' (True) if the mouse is over the 4 Top pixels of the form
            Dim bLeft As Boolean = (loc.X < ClientRectangle.X + 4) '(True) if the mouse is over the 4 Left pixels of the form
            Dim bRight As Boolean = (loc.X > Width - 4) '           (True) if the mouse is over the 4 Right pixels of the form
            Dim bBottom As Boolean = (loc.Y > Height - 4) '         (True) if the mouse is over the 4 Bottom pixels of the form

            If bTop And bLeft Then
                m.Result = CType(HTTOPLEFT, IntPtr) 'return the Top Left hit test message value
            ElseIf bTop And bRight Then
                m.Result = CType(HTTOPRIGHT, IntPtr) 'return the Top Right hit test message value
                Return
            ElseIf bBottom And bLeft Then
                m.Result = CType(HTBOTTOMLEFT, IntPtr) 'return the Bottom Left hit test message value
                Return
            ElseIf bBottom And bRight Then
                m.Result = CType(HTBOTTOMRIGHT, IntPtr) 'return the Bottom Right hit test message value
                Return
            ElseIf bLeft Then
                m.Result = CType(HTLEFT, IntPtr) 'return the Left hit test message value
                Return
            ElseIf bTop Then
                m.Result = CType(HTTOP, IntPtr) 'return the Top Top hit test message value
                Return
            ElseIf bRight Then
                m.Result = CType(HTRIGHT, IntPtr) 'return the Top Right hit test message value
                Return
            ElseIf bBottom Then
                m.Result = CType(HTBOTTOM, IntPtr) 'return the Top Bottom hit test message value
                Return
            End If

        ElseIf m.Msg = WM_LBUTTONDOWN Then
            OffSet.X = MousePosition.X - Me.Location.X
            OffSet.Y = MousePosition.Y - Me.Location.Y

        ElseIf m.Msg = WM_MOUSEMOVE AndAlso m.WParam.ToInt32 = MK_LBUTTON Then
            Me.Left = MousePosition.X - OffSet.X
            Me.Top = MousePosition.Y - OffSet.Y
        End If
        MyBase.WndProc(m)
    End Sub



Hope it is useful. :)
Was This Post Helpful? 1
  • +
  • -

#12 MonkeySeeMonkeyDo   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 19-May 19

Re: Moving WinForm without Title Bar

Posted 19 May 2019 - 10:45 AM

View Postrazal, on 12 October 2014 - 07:59 AM, said:

View Postrusoaica, on 12 October 2014 - 07:33 AM, said:

A class-level variable (or a "field variable") is a variable that is declared outside of any property, method, function, etc. It is declared inside the class itself, thus being visible to all the methods inside that class. Quick example of a class-level variable and a "local" variable:

Class MyClass
   Dim ClassLevelVariable As Integer

   Private Sub SomeSub
      Dim LocalVariable As Integer
   End Sub

   Private Sub SomeOtherSub
      ClassLevelVariable = 1 'this will work
      LocalVariable = 1 'this will not work
   End Sub
End Class



The reason why LocalVariable cannot be "seen" inside the second method is because it is declared inside the first Sub and it can only be used inside that Sub. ClassLevelVariable is declared outside of any Sub, so it can be seen in every Sub of that class. You can read more about variable scope.


OK, it works! :bananaman:/>/>
One last question what means temp.X = form.Location.X + (e.X - MouseDownX)? What does it do?


Thanks to everyone involved in this post. Even after all this time your efforts are helping novice developers.

Thanks to everyone involved in this thread. Five years later your efforts are still helping novice developers. Great job!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1