none
SC_MOVE and cursor location

    Question

  • I have borderless/titleless form. I use this code to show System Menu:

    SendMessage(Handle, WM_SYSCOMMAND, SC_MOVE, 0)

    There is a problem though. When I select "Move" from System Menu, my mouse cursor gets to position (3) and I want it to be at (2) or at  least at (1). I can move mouse cursor after it is positioned, but it resets to the same position as soon as I start dragging window.

    Questions:
    1) Where/how does this API find current window's non-client rectangle area (Title Bar)?
    2) How can I define/set this rectangle area? Can area be non-rectangular? Can area be smaller (in width) compared to its window?
    3) Can you provide any code sample where it shows how to properly center mouse cursor when "Move" is selected from System Menu?

     

    Thursday, August 15, 2013 6:03 PM

Answers

  • Yes, the problem is occuring because you turn off the default titlebar and provide your own.  Even though the title bar is hidden, Windows continues to use it's "location" for the move command.  You may be able to paint the "non client" area with your titlebar instead.  Here's a project on Codeplex that shows how to do that.  I'm uncertain if you can do the transparencies you want or not, however.

    http://customerborderform.codeplex.com/

    Good luck!

    Ray

    Friday, August 16, 2013 5:55 PM
  • Well this is all I am going to do with it. It works some but not 100%.

    This works but has some issues.

    1. Sometimes when using the System Menu Move function with the mouse or the arrow keys the cursor will mysteriously jump out of its location in direct center top - 3 points of label testing and the function quits working.

    2. Sometimes ghosting of the System Menu will occur on the screen.

    3. It's probable that the code which moves the cursor from the top left corner of the System Menu to the Move line of the System Menu will not work correctly on a different sized monitor than my monitor as the offset from the top left corner of the System Menu to the Move line will have a greater or lesser amount of points it will be required to move on a different sized monitor or a monitor set to different resolution I suppose.

    4. I suppose if the computer had other processes interfering with the Forms movement procedures this may not work too well. Don't really know.

    5. Removing the label calls from the timer may alter something unforeseen.

    6. The label Testing requires a height of at least 1.

    So anyhow in the second image below the arrows show the area on the Form that the label testing can be moved in left, right, up or down from its top center - 3 points (where the System Menu Move function places the cursor). The timer in the program moves the Form around the label based on the labels movement. The label is continually repositioned on the Form also as the Form is moved which makes everything more fluid in appearance. Wherever the Form is when the System Menu Move function is called is the bounds the label uses for it's movement even though the Form is moved to keep the label appearing in its normal location on the Form.

    If the label hits its left, right, top or bottom bounds (minus a little bit to make up for the cursor key movements of 10 points at a time) that is detected and the System Menu is called and the Move function is launched again. This gives the label a new area to move in based on the Forms location at that point and the labels location in the Form.

    So in the Form I have (700 wide and 300 high) the labels left is 400, width is 20, top is 80. That means the label thinks it can move left about 410, right about 290, up 83 and down 176 even though down should be about 217. Perhaps my code is off on the down detection but I verified down movement numerous times because it was never coming up correctly according to what I was seeing. It would never move down more than 176 points before stopping. Or up more than 83 before stopping. And 176 + 83 = 259 while the form is actually 300 height. That leaves 41 points unaccounted for. Don't know why.

    The MouseDown, MouseMove and MouseUp events for your label work fine.

    I moved the label testing onto your label and it was not in front of your label but the up movement detection calling the System Menu and initiating the Move function and then sending an up arrow key to remove the cursor size all so the move function works again can cause an issue since there is very little room between the labels top and the Forms top at that point. Therefore a loop can occur because each up arrow moves the Form ten points and if that's in the next up detection range then a loop will happen without the user doing anything. The Form will just automatically move up.

    Top image is Form showing Label1, Label3, MyIcon Button, your Label and Label Test. Form also uses a Timer and a BackgroundWorker. Bottom image is area that label is allowed to move in when System Menu is called and Move is initiated.

    Option Strict On
    
    Imports System.Runtime.InteropServices
    Imports System.Drawing.Drawing2D
    
    Public Class Form1
    
        Inherits System.Windows.Forms.Form
    
        <DllImport("user32.dll")> _
        Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll")> _
        Private Shared Function SetWindowLong(ByVal hwnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
        End Function
    
        <DllImport("user32.dll")> _
        Private Shared Function GetWindowLong(ByVal hwnd As IntPtr, ByVal nIndex As Integer) As Integer
        End Function
    
        Private Declare Auto Function FindWindow Lib "user32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
        Private Declare Auto Function FindWindowEx Lib "user32.dll" (ByVal hwndParent As IntPtr, ByVal hwndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
    
        Private Declare Function apimouse_event Lib "user32" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dX As Int32, ByVal dY As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32) As Boolean
        Const MOUSEEVENTF_LEFTDOWN As Int32 = &H2
        Const MOUSEEVENTF_LEFTUP As Int32 = &H4
    
        Public Const WM_SYSCOMMAND As Int32 = &H112
    
        Private mouseOffset As Point
        Private isMouseDown As Boolean = False
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
            Me.DoubleBuffered = True
            Me.Width = 700
            Me.Height = 300
            Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
    
            Dim MyTitle As New Label
            With MyTitle
                .Name = "MyTitle"
                .Text = "         Here will be my own title bar with many control buttons, options." & Environment.NewLine & "         Notice that it is much thicker and that its width is not the same as window's width."
                .Font = New Font("Times New Roman", 12, FontStyle.Regular)
                .Left = 100
                .Top = 0
                .Width = 600
                .Height = 40
                .BackColor = Color.PeachPuff
                AddHandler .MouseDown, AddressOf TitleBarMouseDown
                AddHandler .MouseMove, AddressOf TitleBarMouseMove
                AddHandler .MouseUp, AddressOf TitleBarMouseUp
            End With
    
            Me.Controls.Add(MyTitle)
    
            '_______________________________________________________________________________
    
            Dim Testing As New Label ' This is the childwindow that the System Menu move function is assigned to
            With Testing
                .Name = "Testing"
                .Text = "Testing"
                .Left = 400
                .Top = 80
                .Width = 20
                .Height = 10 ' must have a height of at least 1
                .BackColor = Color.Red
                .Font = New Font("Times New Roman", 1, FontStyle.Regular)
                TestingX = .Left + CInt(.Width / 2)
                TestingCenter = CInt(.Width / 2)
                TestingLeft = .Left
                TestingTop = .Top
                TestingBottom = .Bottom
                AddHandler .LocationChanged, AddressOf TestingLocationChanged
            End With
    
            Me.Controls.Add(Testing)
    
            'Testing.BringToFront()
    
            '________________________________________________________________________________
    
            Dim MyIcon As New Button
            With MyIcon
                .Text = "MyIcon"
                .Name = "MyIcon"
                .TextAlign = ContentAlignment.TopLeft
                .Font = New Font("Times New Roman", 1, FontStyle.Regular)
                .Left = 105
                .Top = 5
                .Width = 15
                .Height = 15
                .BackColor = Color.Aqua
                .FlatStyle = FlatStyle.Flat
                AddHandler .Click, AddressOf MyIconClick
            End With
    
            Me.Controls.Add(MyIcon)
            MyIcon.BringToFront()
    
            Dim Image1 As Image
            Image1 = Image.FromFile("c:\Users\John\Desktop\Picture Files\Crossbones BMP.bmp")
            Dim ImageSize As New Size(MyIcon.Width, MyIcon.Height)
            Image1 = ResizeImage(Image1, ImageSize)
            MyIcon.BackgroundImage = Image1
    
            Me.CenterToScreen()
    
            Timer1.Interval = 1
    
        End Sub
    
        Private Sub MyIconClick(sender As Object, e As EventArgs)
            BoundsLeft = Me.Left ' This establishes the Forms Left location when MyIcon is clicked in case the Move function is used
            BoundsTop = Me.Top ' This establishes the Forms Top location when MyIcon is clicked in case the Move function is used
            Dim hWnd As IntPtr '_______________________________This code to the next line___________________________________________
            Dim hwndChild As IntPtr
            hWnd = FindWindow(vbNullString, "Form1")
            Do
                hwndChild = FindWindowEx(hWnd, hwndChild, Nothing, Nothing)
            Loop While hwndChild <> IntPtr.Zero
            hwndChild = FindWindowEx(hWnd, hwndChild, Nothing, "Testing")
            Dim tmpStyle As Integer = GetWindowLong(hwndChild, -16) ' The code included with and between the lines is used to set the label Testing
            tmpStyle = tmpStyle Or &H80000 '                          as the location for the Move function to establish as its focal point.
            SetWindowLong(hwndChild, -16, tmpStyle)
            Dim MyIconCenter As Point
            With Me.Controls("MyIcon")
                MyIconCenter.Y = .Top + .Height \ 2
                MyIconCenter.X = .Left + .Width \ 2
            End With
            SendMessage(hwndChild, &H313, New IntPtr(0), New IntPtr(Control.MousePosition.X + Control.MousePosition.Y * &H10000)) '________
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            MyBase.WndProc(m)
        End Sub
    
        Private Sub TitleBarMouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) ' This code is for your Titlebars form moving
            Dim xOffset As Integer
            Dim yOffset As Integer
            If e.Button = MouseButtons.Left Then
                xOffset = -Cursor.Position.X + Me.Location.X
                yOffset = -Cursor.Position.Y + Me.Location.Y
                mouseOffset = New Point(xOffset, yOffset)
                isMouseDown = True
            End If
        End Sub
    
        Private Sub TitleBarMouseMove(sender As Object, e As MouseEventArgs) ' This code is for your Titlebars form moving
            If isMouseDown Then
                Dim mousePos As Point = Control.MousePosition
                mousePos.Offset(mouseOffset.X, mouseOffset.Y)
                Location = mousePos
            End If
        End Sub
    
        Private Sub TitleBarMouseUp(sender As Object, e As MouseEventArgs) ' This code is for your Titlebars form moving
            If e.Button = MouseButtons.Left Then
                isMouseDown = False
            End If
        End Sub
    
        Private Sub TestingLocationChanged(sender As Object, e As EventArgs) ' This code starts the timer when the
            i = 1 '                                                                        System Menu Functions cursor moves the
            Timer1.Start() '                                                               label Testing on the form. It sets i to 1                                                                
        End Sub '                                                                          so the forms location moves with the label.
    
        Dim i As Integer = 0
        Dim TestingCenter As Integer = 0
        Dim TestingLeft As Integer = 0
        Dim TestingTop As Integer = 0
        Dim TestingBottom As Integer = 0
        Dim FudgeFactor As Integer = 11 ' FudgeFactor takes into accout arrow movement which moves label ten points at a time.
        Dim TestingX As Integer = 0
        Dim BoundsLeft As Integer = 0
        Dim BoundsTop As Integer = 0
        Dim TestIt As Integer = 0
    
        Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick ' this timer is used to relocate the form when the
            Timer1.Stop() '                                                             label Testing is moved by the System Menu Move function.
            Label1.Text = Cursor.Position.X.ToString & " ... " & Cursor.Position.Y.ToString
            With Me.Controls("Testing")
                .Left = TestingLeft
                .Top = TestingTop
            End With
            If i = 1 Then
                Me.Location = New Point(Cursor.Position.X - TestingX, Cursor.Position.Y - TestingTop - 3) ' 3 is how far down the cursor is in label Testing during a System Menu move operation
            End If
            If Me.Left - BoundsLeft <= -TestingLeft + -TestingCenter + FudgeFactor Then ' Tests if left bound of labels movement met
                Label2.Text = "Left hit"
                Label3.Text = ""
                Label4.Text = ""
                Label5.Text = ""
                i = 2
                Counter = 0
                TestIt = 1
                apimouse_event(MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0) ' Places cursor on Button MyIcon
                SendKeys.Send("{Enter}") ' Sends enter key on Button MyIcon to start redisplay of System Menu
                BackgroundWorker1.RunWorkerAsync()
            ElseIf Me.Left - BoundsLeft >= Me.Width - TestingLeft - TestingCenter - FudgeFactor Then  ' Tests if right bound of labels movement met
                Label2.Text = ""
                Label3.Text = "Right hit"
                Label4.Text = ""
                Label5.Text = ""
                i = 2
                Counter = 0
                TestIt = 2
                apimouse_event(MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0)
                SendKeys.Send("{Enter}")
                BackgroundWorker1.RunWorkerAsync()
            ElseIf BoundsTop - Me.Top >= TestingTop + 3 - FudgeFactor Then ' Tests if top bound of labels movement met
                Label2.Text = ""
                Label3.Text = ""
                Label4.Text = "Top hit"
                Label5.Text = ""
                i = 2
                Counter = 0
                TestIt = 3
                apimouse_event(MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0)
                SendKeys.Send("{Enter}")
                BackgroundWorker1.RunWorkerAsync()
            ElseIf Me.Top - BoundsTop >= Me.Height - TestingTop - FudgeFactor - 3 Then  ' Tests if bottom bound of labels movement met
                Label2.Text = ""
                Label3.Text = ""
                Label4.Text = ""
                Label5.Text = "Bottom hit"
                i = 2
                Counter = 0
                TestIt = 4
                apimouse_event(MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0)
                SendKeys.Send("{Enter}")
                BackgroundWorker1.RunWorkerAsync()
            End If
            Timer1.Stop() ' The timer stops until the System Menu Move function moves the label again.
        End Sub
    
        Dim Counter As Integer = 0 ' used by a loop in the background worker giving the
        '                            System Menu time to display before the sub routine is called.
        '                            The sub routine sets the cursor to the Move function location then
        '                            sends Enter so the Move function cursor (size all) displays.
        '                            Depending on the users current movement of the form the sub routine
        '                            then sends an arrow key in that direction to get rid of the size all
        '                            cursor and continue with movement.
    
        Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Do Until Counter = 800000 ' Unfortunately this is an arbitrary number and may run faster or slower depending on the system
                Counter += 1 '          the program is on so it may not allow the System Menu Move function to display before the
            Loop '                      loop finishes. This would cause the TestIt subs to perform while no System Menu is displayed.
            If TestIt = 1 Then '        Or run too long so the System Menu is displayed too long and the user sees it.
                LeftTestIt()
            ElseIf TestIt = 2 Then
                RightTestIt()
            ElseIf TestIt = 3 Then
                UpTestIt()
            ElseIf TestIt = 4 Then
                DownTestIt()
            End If
        End Sub
    
        Private Sub LeftTestIt()
            Cursor.Position = New Point(Cursor.Position.X + 50, Cursor.Position.Y + 34) ' Offset of cursor postion at top left corner of System Menu to the Move function on my laptops screen
            SendKeys.SendWait("{Enter}") ' Sends Enter while cursor is on System Menu at Move location.
            SendKeys.SendWait("{Left}") ' Sends Arrow to remove cursor size all and allow Move function to continue working.
        End Sub
    
        Private Sub RightTestIt()
            Cursor.Position = New Point(Cursor.Position.X + 50, Cursor.Position.Y + 34)
            SendKeys.SendWait("{Enter}")
            SendKeys.SendWait("{Right}")
        End Sub
    
        Private Sub UpTestIt()
            Cursor.Position = New Point(Cursor.Position.X + 50, Cursor.Position.Y + 34)
            SendKeys.SendWait("{Enter}")
            SendKeys.SendWait("{Up}")
        End Sub
    
        Private Sub DownTestIt()
            Cursor.Position = New Point(Cursor.Position.X + 50, Cursor.Position.Y + 34)
            SendKeys.SendWait("{Enter}")
            SendKeys.SendWait("{Down}")
        End Sub
    
        Public Shared Function ResizeImage(ByVal image As Image, ByVal size As Size, Optional ByVal preserveAspectRatio As Boolean = True) As Image
            Dim newWidth As Integer
            Dim newHeight As Integer
            If preserveAspectRatio Then
                Dim originalWidth As Integer = image.Width
                Dim originalHeight As Integer = image.Height
                Dim percentWidth As Single = CSng(size.Width) / CSng(originalWidth)
                Dim percentHeight As Single = CSng(size.Height) / CSng(originalHeight)
                Dim percent As Single = If(percentHeight < percentWidth,
                        percentHeight, percentWidth)
                newWidth = CInt(originalWidth * percent)
                newHeight = CInt(originalHeight * percent)
            Else
                newWidth = size.Width
                newHeight = size.Height
            End If
            Dim newImage As Image = New Bitmap(newWidth, newHeight)
            Using graphicsHandle As Graphics = Graphics.FromImage(newImage)
                graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic
                graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight)
            End Using
            Return newImage
        End Function
    
    End Class


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


    Wednesday, August 21, 2013 7:06 AM

All replies

  • What is a system menu?

    Why do you have to select move rather than just moving the form?

    You provide no code and assume that everybody understands the terminology you are using.

    This code provides the capability to move a borderless form as well as resize it from the right side, bottom or botton right corner.

    Option Strict On
    
    Public Class Form1
    
        Private mouseOffset As Point
    
        Const WM_NCHITTEST As Integer = &H84
    
        Const HTBOTTOMRIGHT As Integer = 17
        Const HTBOTTOM As Integer = 15
        Const HTRIGHT As Integer = 11
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.BackColor = Color.DarkSlateGray
            Panel1.BackColor = Color.DarkCyan
            Button1.BackColor = Color.DarkSlateGray
            TextBox1.BackColor = Color.DarkSlateGray
            Label1.BackColor = Color.Red
            Label2.BackColor = Color.Red
        End Sub
    
        Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
            MyBase.OnMouseDown(e)
            If e.Button = MouseButtons.Left Then
                Me.Capture = False
                Me.WndProc(Message.Create(Me.Handle, &HA1, New IntPtr(2), IntPtr.Zero))
            End If
        End Sub
    
        Private Sub Label1_Click(sender As Object, e As EventArgs) Handles Label1.Click
            If Label1.Text = "X" Then
                Application.Exit()
            End If
        End Sub
    
        Private Sub Label2_Click(sender As Object, e As EventArgs) Handles Label2.Click
            If Label2.Text = "__" Then
                Me.WindowState = FormWindowState.Minimized
            End If
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As Message)
    
            Select Case m.Msg
    
                Case WM_NCHITTEST
    
                    Dim loc As New Point(m.LParam.ToInt32 And &HFFFF, m.LParam.ToInt32 >> 16)
                    loc = PointToClient(loc)
    
                    Dim blnRight As Boolean = (loc.X > Width - 9)
                    Dim blnBottom As Boolean = (loc.Y > Height - 9)
    
                    If blnRight And blnBottom Then
    
                        m.Result = CType(HTBOTTOMRIGHT, IntPtr)
                        Return
    
                    ElseIf blnRight Then
    
                        m.Result = CType(HTRIGHT, IntPtr)
                        Return
    
                    ElseIf blnBottom Then
    
                        m.Result = CType(HTBOTTOM, IntPtr)
                        Return
    
                    End If
    
            End Select
    
            MyBase.WndProc(m)
    
        End Sub
    
        Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
    
            Dim xOffset As Integer
            Dim yOffset As Integer
    
            If e.Button = Windows.Forms.MouseButtons.Left Then
                xOffset = -e.X - SystemInformation.FrameBorderSize.Width
                yOffset = -e.Y - SystemInformation.FrameBorderSize.Height
                mouseOffset = New Point(xOffset, yOffset)
            End If
    
        End Sub
    
    
    End Class


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


    Thursday, August 15, 2013 7:31 PM
  • What is a system menu?
    Here is an example:

     

    Why do you have to select move rather than just moving the form?
    Because there is such an option in that menu.


    • Edited by fifi5 Thursday, August 15, 2013 7:58 PM
    Thursday, August 15, 2013 7:58 PM
  • Unfortunately, I think it's going to just use the size of the standard titlebar.  You'rs is significantly smaller than the windows titlebar.  It's going to the "center" of the windows titlebar which puts it at #1.  I don't think it's something you can set without changing the size of the titlebar for ALL standard windows.

    @Mr. Monkey: He's using standard Windows terminology.  I'm not sure why you decided to get hostile with him.

    Ray

    Thursday, August 15, 2013 8:16 PM
  • I have just created this sample code to illustrate the issue. Create an empty form, paste this code, run program, click on title bar.

    Imports System.Runtime.InteropServices
    
    Public Class Form1
        Inherits System.Windows.Forms.Form
    
        <DllImport("user32.dll")> _
        Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll")> _
        Private Shared Function SetWindowLong(ByVal hwnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
        End Function
    
        <DllImport("user32.dll")> _
        Private Shared Function GetWindowLong(ByVal hwnd As IntPtr, ByVal nIndex As Integer) As Integer
        End Function
    
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles Me.Load
            Me.Width = 700
            Me.Height = 700
            Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
    
            Dim MyTitle As New Label
            With MyTitle
                .Text = "Here will be my own title bar with many control buttons, options." & Environment.NewLine & "Notice that it is much thicker and that its widht is not the same as window's width."
                .Font = New Font("Times New Roman", 12, FontStyle.Regular)
                .Left = 100
                .Top = 0
                .Width = 600
                .Height = 40
                .BackColor = Color.DarkGoldenrod
                AddHandler .Click, AddressOf TitleBarClick
            End With
    
            Me.Controls.Add(MyTitle)
    
            Dim tmpStyle As Integer = GetWindowLong(Handle, (-16))
            tmpStyle = tmpStyle Or &H80000
            SetWindowLong(Handle, (-16), tmpStyle)
        End Sub
    
        Private Sub TitleBarClick()
            SendMessage(Handle, &H313, New IntPtr(0), New IntPtr(Control.MousePosition.X + Control.MousePosition.Y * &H10000))
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            If m.Msg = &H112 AndAlso m.WParam.ToInt32() = 61456 Then MessageBox.Show("You have clicked ""Move"" from System Menu." & Environment.NewLine & "Notice where mouse cursor is centered.")
            MyBase.WndProc(m)
        End Sub
    End Class

    • Edited by fifi5 Thursday, August 15, 2013 10:47 PM
    Thursday, August 15, 2013 10:42 PM
  • @Mr. Monkey: He's using standard Windows terminology.  I'm not sure why you decided to get hostile with him.

    Ray


    I didn't. I asked a simple question Ray.

    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Thursday, August 15, 2013 11:03 PM

  • You provide no code and assume that everybody understands the terminology you are using.


    This is what sounded hostile to me.  Obviously you didn't intend it to be.  The problem with written text is it can be interpreted the wrong way.  I apologize.
    Friday, August 16, 2013 2:45 PM
  • Has anyone tried my sample code? Do you understand my issue?
    Friday, August 16, 2013 4:22 PM
  • Yes, the problem is occuring because you turn off the default titlebar and provide your own.  Even though the title bar is hidden, Windows continues to use it's "location" for the move command.  You may be able to paint the "non client" area with your titlebar instead.  Here's a project on Codeplex that shows how to do that.  I'm uncertain if you can do the transparencies you want or not, however.

    http://customerborderform.codeplex.com/

    Good luck!

    Ray

    Friday, August 16, 2013 5:55 PM
  • Thank you for your code. It seems I understand what you are trying to do, but it does not work for me. Mouse cursor gets exactly to the same position as where my code does (which is not the middle of title bar). I have tried playing with offsets, but it seems they have no effect, eg.:

    xOffset = -e.X + 100
    yOffset = -e.Y + 100
    
    xOffset = -e.X - 100
    yOffset = -e.Y - 100

    I suppose you could send a simulated mouse click to the label right after the mouse event handler additions (which would possibly alleviate the issue) then change the mouse cursor to the four arrows and change the mouse cursor back to normal when the mouse up event occurs. But that's a lot more code.

    I was about to rewrite the part that happens after System Menu -> Move, but it seems I don't know how to simulate right mouse click on title bar (so that window becomes dragable/movable).

    Friday, August 16, 2013 11:22 PM
  • And if you don't know already here's how you can add stuff to the System Menu

    Public Class Form1
    
        Public Const WM_SYSCOMMAND As Int32 = &H112
        Public Const MF_BYPOSITION As Int32 = &H400
        Public Const MYMENU1 As Int32 = 1000
        Public Const MYMENU2 As Int32 = 1001
    
        Dim hSysMenu As Long
    
    
        Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Integer, ByVal bRevert As Integer) As Integer
        Public Declare Function InsertMenu Lib "user32" Alias "InsertMenuA" _
            (ByVal hMenu As IntPtr, ByVal nPosition As Integer, ByVal wFlags As Integer, ByVal wIDNewItem As Integer, ByVal lpNewItem As String) As Boolean
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            MyBase.WndProc(m)
            If (m.Msg = WM_SYSCOMMAND) Then
                Select Case m.WParam.ToInt32
                    Case MYMENU1
                        MsgBox("1")
                    Case MYMENU2
                        MsgBox("2")
                End Select
            End If
        End Sub
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            hSysMenu = GetSystemMenu(Me.Handle, False)
            InsertMenu(hSysMenu, 5, MF_BYPOSITION, MYMENU1, "My Menu 1")
            InsertMenu(hSysMenu, 6, MF_BYPOSITION, MYMENU2, "My Menu 2")
    
        End Sub
    End Class
    


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Friday, August 16, 2013 11:22 PM
  • Maybe I don't know something, but my known methods do not allow me to reposition. I told about that in my first post "I can move mouse cursor after it is positioned, but it resets to the same position as soon as I start dragging window."

    Just to clarify:
    1) I can click anywhere on the Title Bar (MyTitle) with left mouse button and System Menu will appear. That's OK.
    2) If I choose "Move" from that menu, mouse cursor gets to the top of Title Bar (MyTitle) instead of the middle of Title Bar. That's not OK. I was not able to move mouse cursor to the right position (timing was the issue here), but even if I succeed, cursor will be reseted to the wrong place (after "Move" is clicked, mouse cursor is positioned and it is displayed with the four arrows, at this point you cannot drag/move window with mouse, you can use arrow keys and as soon as you do it, mouse cursor is reseted back to wrong place).


    • Edited by fifi5 Saturday, August 17, 2013 12:06 AM
    Friday, August 16, 2013 11:44 PM
  • Ah, I have just noticed that you have updated your code. It has a bit different approach.

    I believe it will possible to fix that shift to the left and center mouse cursor vertically across the title bar. I will try to do that.

    One thing I have noticed that it is no longer possible to move window with arrow keys. I will try to investigate that as well.

    Friday, August 16, 2013 11:54 PM
  • This fixes one issue (add it after Cursor = Cursors.SizeAll):

    Dim MyTitleCenter As Point
    With Me.Controls("MyTitle")
        MyTitleCenter.Y = .Top + .Height \ 2
        MyTitleCenter.X = .Left + .Width \ 2
    End With
    Windows.Forms.Cursor.Position = Me.PointToScreen(MyTitleCenter)

    So now only one issue is left, control movement/dragging with arrow keys.

    • Edited by fifi5 Saturday, August 17, 2013 12:23 AM
    Saturday, August 17, 2013 12:22 AM
  • I want to make it as close as possible to original windows behavior. When I start moving form by arrow keys, I still able to move it by mouse. I lose ability to move it by mouse or arrow keys when I do a left mouse click.

    Basically, I don't understand why moving by arrow keys is not possible at the moment, it is default windows behavior. I need to investigate.

    Saturday, August 17, 2013 1:28 AM
  • I deleted all of my other posts off of this thread except the one that shows how to add things to the System Menu.

    Well I finally got somewhere with this. The two labels I added (Label1 and Label2) on the left side of the form are for testing with to see the positions of the form and label "Testing" in the label "Testing" TestingLocationChanged event.

    As you can see in the first image I added a button (named MyIcon) onto your label to use like the Icon you click on a windows form to bring up the System Menu. I added a resized image to it (using the function in the code). As you can see in the second image that works fine when the button is clicked on.

    Then I added a label called "Testing" to the form. The label is used to locate the cursor (SizeAll style) for the move function in the system menu. The reason I did this is so you could relocate that label on form load into about the middle center of your label and set its height to zero so it will not appear (or wherever you want in your label for the cursor from the system menu to locate). I've tested it with height of zero and it works.

    Note that the FindWindow and FindWindoEx functions require that the control they search for has text to search on. They don't work by using the actual controls name for some reason. So if I changed Form1's text to something other than Form1 it would not work unless I changed the code for FindWindow to match the new text.

    Anyhow when you click the button the forms IntPtr is retrieved. Then that is used to retrieve the label "Testing" childwindow. SetWindowLong then sets the label with -16 and tmpStyle. Whatever that does.

    Then SendMessage sends a message for the label which I guess places the cursor (SizeAll style) at the center top of the label. Anyhow if the label was in the middle of your label I suppose the cursor would locate there.

    The issue is that you can move the form about 683 points left and right. Which when added to left and right border, if the form had borders, would just about equal the forms width of 700. As the left and right border are 8 each and 683 added to 16 = 699 "Dim BorderWidth As Integer = ((Me.Width - Me.ClientSize.Width) / 2)". Not 100% sure that is accurate for border width but think so.

    And you can move the form up and down about 261 points. When when added to the top and bottom border of the form, if the form had borders, would just about equal the forms height of 300. As the TitleBar (top border) is 30 and bottom border is 8 so 261 + 38 = 299 "Dim TitlebarHeight As Integer = Me.Height - Me.ClientSize.Height - 1 * BorderWidth". Not 100% sure that is accurate for Titlebar height but think so.

    So that's the sticking point right now. I tried resizing the form before and after getting its handle in the button MyIcon event hoping that would alter the allocated space for the System Menu move function. I maximized and unmaximized the form too. I tried setting the form to max size in the form load event then resizing it after the button MyIcon click event to see if that had any effect. I did everything I could imagine to try to get the handle of the Form when at max size to see if that would change anything. I tried relocating the label on the form instead of the form following the label around and relocating the cursor too (that was really ugly and caused havoc). Nothing worked.

    However if I change the form height to 700 rather than 300 in the form load event it changes up the action of the system menu move event and you can move the form around a much larger area for some reason. Same if you change the form width from 700 to 800 in the form load event.

    From testing it appears to me that since the label is actually being moved by the system menu move function and the form is just following the label around then the label can only be moved within the bounds area of whatever the forms width and height are starting at whatever location the form is when the system menu move function is clicked on.

    Maybe if there was some way to "tell" the label that it has a larger area than the forms area to move around in but I don't know how to do it.

    Here's the code and below it the images.

    Option Strict On
    
    Imports System.Runtime.InteropServices
    Imports System.Drawing.Drawing2D
    
    Public Class Form1
    
        Inherits System.Windows.Forms.Form
    
        <DllImport("user32.dll")> _
        Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll")> _
        Private Shared Function SetWindowLong(ByVal hwnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
        End Function
    
        <DllImport("user32.dll")> _
        Private Shared Function GetWindowLong(ByVal hwnd As IntPtr, ByVal nIndex As Integer) As Integer
        End Function
    
        Private Declare Auto Function FindWindow Lib "user32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
        Private Declare Auto Function FindWindowEx Lib "user32.dll" (ByVal hwndParent As IntPtr, ByVal hwndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
    
        Public Const WM_SYSCOMMAND As Int32 = &H112
    
        Private mouseOffset As Point
        Private isMouseDown As Boolean = False
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
            Me.Width = 700
            Me.Height = 300
            Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
    
            Dim MyTitle As New Label
            With MyTitle
                .Name = "MyTitle"
                .Text = "         Here will be my own title bar with many control buttons, options." & Environment.NewLine & "         Notice that it is much thicker and that its width is not the same as window's width."
                .Font = New Font("Times New Roman", 12, FontStyle.Regular)
                .Left = 100
                .Top = 0
                .Width = 600
                .Height = 40
                .BackColor = Color.PeachPuff
                AddHandler .MouseDown, AddressOf TitleBarMouseDown
                AddHandler .MouseMove, AddressOf TitleBarMouseMove
                AddHandler .MouseUp, AddressOf TitleBarMouseUp
            End With
    
            Me.Controls.Add(MyTitle)
    
            '_______________________________________________________________________________
    
            Dim Testing As New Label
            With Testing
                .Name = "Testing"
                .Text = "Testing"
                .Left = 350
                .Top = 80
                .Width = 100
                .Height = 40
                .BackColor = Color.Red
                AddHandler .LocationChanged, AddressOf TestingLocationChanged
            End With
    
            Me.Controls.Add(Testing)
    
            '________________________________________________________________________________
    
            Dim MyIcon As New Button
            With MyIcon
                .Text = "MyIcon"
                .Name = "MyIcon"
                .Font = Nothing
                .Left = 105
                .Top = 5
                .Width = 25
                .Height = 25
                .BackColor = Color.Aqua
                .FlatStyle = FlatStyle.Flat
                AddHandler .Click, AddressOf MyIconClick
            End With
    
            Me.Controls.Add(MyIcon)
            MyIcon.BringToFront()
    
            Dim Image1 As Image
            Image1 = Image.FromFile("c:\Users\John\Desktop\Picture Files\Crossbones BMP.bmp")
            Dim ImageSize As New Size(MyIcon.Width, MyIcon.Height)
            Image1 = ResizeImage(Image1, ImageSize)
            MyIcon.BackgroundImage = Image1
    
            Me.CenterToScreen()
    
        End Sub
    
        Private Sub MyIconClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
            Dim hWnd As IntPtr
            Dim hwndChild As IntPtr
            hWnd = FindWindow(vbNullString, "Form1")
            Do
                hwndChild = FindWindowEx(hWnd, hwndChild, Nothing, Nothing)
            Loop While hwndChild <> IntPtr.Zero
            hwndChild = FindWindowEx(hWnd, hwndChild, Nothing, "Testing")
            Dim tmpStyle As Integer = GetWindowLong(hwndChild, -16)
            tmpStyle = tmpStyle Or &H80000
            SetWindowLong(hwndChild, -16, tmpStyle)
            SendMessage(hwndChild, &H313, New IntPtr(0), New IntPtr(Control.MousePosition.X + Control.MousePosition.Y * &H10000))
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            MyBase.WndProc(m)
        End Sub
    
        Private Sub TitleBarMouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
            Dim xOffset As Integer
            Dim yOffset As Integer
            If e.Button = MouseButtons.Left Then
                xOffset = -Cursor.Position.X + Me.Location.X
                yOffset = -Cursor.Position.Y + Me.Location.Y
                mouseOffset = New Point(xOffset, yOffset)
                isMouseDown = True
            End If
        End Sub
    
        Private Sub TitleBarMouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
            If isMouseDown Then
                Dim mousePos As Point = Control.MousePosition
                mousePos.Offset(mouseOffset.X, mouseOffset.Y)
                Location = mousePos
            End If
        End Sub
    
        Private Sub TitleBarMouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)
            If e.Button = MouseButtons.Left Then
                isMouseDown = False
            End If
        End Sub
    
        Private Sub TestingLocationChanged(ByVal sender As Object, ByVal e As EventArgs)
            With Me.Controls("Testing")
                Me.Location = New Point(Me.Location.X + (.Location.X - 350), Me.Location.Y + (.Location.Y - 80))
                ' - 350 is Label Testings Left and - 80 is Label Testings Top in Form Load
                Label1.Text = Me.Location.X.ToString & "   " & .Location.X.ToString
                Label2.Text = Me.Location.Y.ToString & "   " & (.Location.Y - 80).ToString
            End With
        End Sub
    
        Public Shared Function ResizeImage(ByVal image As Image, ByVal size As Size, Optional ByVal preserveAspectRatio As Boolean = True) As Image
            Dim newWidth As Integer
            Dim newHeight As Integer
            If preserveAspectRatio Then
                Dim originalWidth As Integer = image.Width
                Dim originalHeight As Integer = image.Height
                Dim percentWidth As Single = CSng(size.Width) / CSng(originalWidth)
                Dim percentHeight As Single = CSng(size.Height) / CSng(originalHeight)
                Dim percent As Single = If(percentHeight < percentWidth,
                        percentHeight, percentWidth)
                newWidth = CInt(originalWidth * percent)
                newHeight = CInt(originalHeight * percent)
            Else
                newWidth = size.Width
                newHeight = size.Height
            End If
            Dim newImage As Image = New Bitmap(newWidth, newHeight)
            Using graphicsHandle As Graphics = Graphics.FromImage(newImage)
                graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic
                graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight)
            End Using
            Return newImage
        End Function
    
    End Class

     


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.



    Monday, August 19, 2013 3:52 AM
  • Well I figured out how to get around the issue I believe.

    When the MyIcon is clicked the last thing that needs to be done is get the forms size, Testing label location on Form,  Forms current location on screen and primary screen working area I think. Still figuring this part out.

    Also added to the MyIconClick event will be new code right before the SendMessage command. It will be an If Then statement that if an Integer = 1 it will call a Sub Routine.

    As an example in the TestingLocationChanged event if the label moves all the way to the left of what it believes is the Forms bounds (which will no longer allow the Form to move left) then code will detect this in the TestingLocationChanged event and the integer will be set to 1 and MyIconClick will be called.

    Now with the integer set to 1 MyIconClick will call a sub routine right before it calls SendMessage. SendMessage will cause the System Menu to display again at the MyIcon button. However the sub routine sends keys down, down, enter (to start the move function again) and up (up arrow to change the cursor from SizeAll to Arrow) and sets the integer to 0. The user will not notice any of that occured because the system menu is not displayed long enough to be seen. Now the label has a new bounds to move in.

    I used the below code to test the basic functionality of the send keys to do this and it works great.

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim hWnd As IntPtr
            Dim hwndChild As IntPtr
            hWnd = FindWindow(vbNullString, "Form1")
            Do
                hwndChild = FindWindowEx(hWnd, hwndChild, Nothing, Nothing)
            Loop While hwndChild <> IntPtr.Zero
            hwndChild = FindWindowEx(hWnd, hwndChild, Nothing, "Testing")
            Dim tmpStyle As Integer = GetWindowLong(hwndChild, -16)
            tmpStyle = tmpStyle Or &H80000
            SetWindowLong(hwndChild, -16, tmpStyle)
            Test()
            SendMessage(hwndChild, &H313, New IntPtr(0), New IntPtr(Control.MousePosition.X + Control.MousePosition.Y * &H10000))
    End Sub
    
    Private Sub Test()
            SendKeys.Send("{Down}")
            SendKeys.Send("{Down}")
            SendKeys.Send("{Enter}")
            SendKeys.Send("{Up}")
    End Sub


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


    Monday, August 19, 2013 7:04 PM
  • More snags developed trying the previous method. Had to move the cursor to the MyIcon button first. Then if someone is still moving the mouse or using the arrow keys still trying to move the form it's a bad thing. New approach being tested soon.

    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Monday, August 19, 2013 11:41 PM
  • Well this is all I am going to do with it. It works some but not 100%.

    This works but has some issues.

    1. Sometimes when using the System Menu Move function with the mouse or the arrow keys the cursor will mysteriously jump out of its location in direct center top - 3 points of label testing and the function quits working.

    2. Sometimes ghosting of the System Menu will occur on the screen.

    3. It's probable that the code which moves the cursor from the top left corner of the System Menu to the Move line of the System Menu will not work correctly on a different sized monitor than my monitor as the offset from the top left corner of the System Menu to the Move line will have a greater or lesser amount of points it will be required to move on a different sized monitor or a monitor set to different resolution I suppose.

    4. I suppose if the computer had other processes interfering with the Forms movement procedures this may not work too well. Don't really know.

    5. Removing the label calls from the timer may alter something unforeseen.

    6. The label Testing requires a height of at least 1.

    So anyhow in the second image below the arrows show the area on the Form that the label testing can be moved in left, right, up or down from its top center - 3 points (where the System Menu Move function places the cursor). The timer in the program moves the Form around the label based on the labels movement. The label is continually repositioned on the Form also as the Form is moved which makes everything more fluid in appearance. Wherever the Form is when the System Menu Move function is called is the bounds the label uses for it's movement even though the Form is moved to keep the label appearing in its normal location on the Form.

    If the label hits its left, right, top or bottom bounds (minus a little bit to make up for the cursor key movements of 10 points at a time) that is detected and the System Menu is called and the Move function is launched again. This gives the label a new area to move in based on the Forms location at that point and the labels location in the Form.

    So in the Form I have (700 wide and 300 high) the labels left is 400, width is 20, top is 80. That means the label thinks it can move left about 410, right about 290, up 83 and down 176 even though down should be about 217. Perhaps my code is off on the down detection but I verified down movement numerous times because it was never coming up correctly according to what I was seeing. It would never move down more than 176 points before stopping. Or up more than 83 before stopping. And 176 + 83 = 259 while the form is actually 300 height. That leaves 41 points unaccounted for. Don't know why.

    The MouseDown, MouseMove and MouseUp events for your label work fine.

    I moved the label testing onto your label and it was not in front of your label but the up movement detection calling the System Menu and initiating the Move function and then sending an up arrow key to remove the cursor size all so the move function works again can cause an issue since there is very little room between the labels top and the Forms top at that point. Therefore a loop can occur because each up arrow moves the Form ten points and if that's in the next up detection range then a loop will happen without the user doing anything. The Form will just automatically move up.

    Top image is Form showing Label1, Label3, MyIcon Button, your Label and Label Test. Form also uses a Timer and a BackgroundWorker. Bottom image is area that label is allowed to move in when System Menu is called and Move is initiated.

    Option Strict On
    
    Imports System.Runtime.InteropServices
    Imports System.Drawing.Drawing2D
    
    Public Class Form1
    
        Inherits System.Windows.Forms.Form
    
        <DllImport("user32.dll")> _
        Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll")> _
        Private Shared Function SetWindowLong(ByVal hwnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
        End Function
    
        <DllImport("user32.dll")> _
        Private Shared Function GetWindowLong(ByVal hwnd As IntPtr, ByVal nIndex As Integer) As Integer
        End Function
    
        Private Declare Auto Function FindWindow Lib "user32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
        Private Declare Auto Function FindWindowEx Lib "user32.dll" (ByVal hwndParent As IntPtr, ByVal hwndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
    
        Private Declare Function apimouse_event Lib "user32" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dX As Int32, ByVal dY As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32) As Boolean
        Const MOUSEEVENTF_LEFTDOWN As Int32 = &H2
        Const MOUSEEVENTF_LEFTUP As Int32 = &H4
    
        Public Const WM_SYSCOMMAND As Int32 = &H112
    
        Private mouseOffset As Point
        Private isMouseDown As Boolean = False
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
            Me.DoubleBuffered = True
            Me.Width = 700
            Me.Height = 300
            Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
    
            Dim MyTitle As New Label
            With MyTitle
                .Name = "MyTitle"
                .Text = "         Here will be my own title bar with many control buttons, options." & Environment.NewLine & "         Notice that it is much thicker and that its width is not the same as window's width."
                .Font = New Font("Times New Roman", 12, FontStyle.Regular)
                .Left = 100
                .Top = 0
                .Width = 600
                .Height = 40
                .BackColor = Color.PeachPuff
                AddHandler .MouseDown, AddressOf TitleBarMouseDown
                AddHandler .MouseMove, AddressOf TitleBarMouseMove
                AddHandler .MouseUp, AddressOf TitleBarMouseUp
            End With
    
            Me.Controls.Add(MyTitle)
    
            '_______________________________________________________________________________
    
            Dim Testing As New Label ' This is the childwindow that the System Menu move function is assigned to
            With Testing
                .Name = "Testing"
                .Text = "Testing"
                .Left = 400
                .Top = 80
                .Width = 20
                .Height = 10 ' must have a height of at least 1
                .BackColor = Color.Red
                .Font = New Font("Times New Roman", 1, FontStyle.Regular)
                TestingX = .Left + CInt(.Width / 2)
                TestingCenter = CInt(.Width / 2)
                TestingLeft = .Left
                TestingTop = .Top
                TestingBottom = .Bottom
                AddHandler .LocationChanged, AddressOf TestingLocationChanged
            End With
    
            Me.Controls.Add(Testing)
    
            'Testing.BringToFront()
    
            '________________________________________________________________________________
    
            Dim MyIcon As New Button
            With MyIcon
                .Text = "MyIcon"
                .Name = "MyIcon"
                .TextAlign = ContentAlignment.TopLeft
                .Font = New Font("Times New Roman", 1, FontStyle.Regular)
                .Left = 105
                .Top = 5
                .Width = 15
                .Height = 15
                .BackColor = Color.Aqua
                .FlatStyle = FlatStyle.Flat
                AddHandler .Click, AddressOf MyIconClick
            End With
    
            Me.Controls.Add(MyIcon)
            MyIcon.BringToFront()
    
            Dim Image1 As Image
            Image1 = Image.FromFile("c:\Users\John\Desktop\Picture Files\Crossbones BMP.bmp")
            Dim ImageSize As New Size(MyIcon.Width, MyIcon.Height)
            Image1 = ResizeImage(Image1, ImageSize)
            MyIcon.BackgroundImage = Image1
    
            Me.CenterToScreen()
    
            Timer1.Interval = 1
    
        End Sub
    
        Private Sub MyIconClick(sender As Object, e As EventArgs)
            BoundsLeft = Me.Left ' This establishes the Forms Left location when MyIcon is clicked in case the Move function is used
            BoundsTop = Me.Top ' This establishes the Forms Top location when MyIcon is clicked in case the Move function is used
            Dim hWnd As IntPtr '_______________________________This code to the next line___________________________________________
            Dim hwndChild As IntPtr
            hWnd = FindWindow(vbNullString, "Form1")
            Do
                hwndChild = FindWindowEx(hWnd, hwndChild, Nothing, Nothing)
            Loop While hwndChild <> IntPtr.Zero
            hwndChild = FindWindowEx(hWnd, hwndChild, Nothing, "Testing")
            Dim tmpStyle As Integer = GetWindowLong(hwndChild, -16) ' The code included with and between the lines is used to set the label Testing
            tmpStyle = tmpStyle Or &H80000 '                          as the location for the Move function to establish as its focal point.
            SetWindowLong(hwndChild, -16, tmpStyle)
            Dim MyIconCenter As Point
            With Me.Controls("MyIcon")
                MyIconCenter.Y = .Top + .Height \ 2
                MyIconCenter.X = .Left + .Width \ 2
            End With
            SendMessage(hwndChild, &H313, New IntPtr(0), New IntPtr(Control.MousePosition.X + Control.MousePosition.Y * &H10000)) '________
        End Sub
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            MyBase.WndProc(m)
        End Sub
    
        Private Sub TitleBarMouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) ' This code is for your Titlebars form moving
            Dim xOffset As Integer
            Dim yOffset As Integer
            If e.Button = MouseButtons.Left Then
                xOffset = -Cursor.Position.X + Me.Location.X
                yOffset = -Cursor.Position.Y + Me.Location.Y
                mouseOffset = New Point(xOffset, yOffset)
                isMouseDown = True
            End If
        End Sub
    
        Private Sub TitleBarMouseMove(sender As Object, e As MouseEventArgs) ' This code is for your Titlebars form moving
            If isMouseDown Then
                Dim mousePos As Point = Control.MousePosition
                mousePos.Offset(mouseOffset.X, mouseOffset.Y)
                Location = mousePos
            End If
        End Sub
    
        Private Sub TitleBarMouseUp(sender As Object, e As MouseEventArgs) ' This code is for your Titlebars form moving
            If e.Button = MouseButtons.Left Then
                isMouseDown = False
            End If
        End Sub
    
        Private Sub TestingLocationChanged(sender As Object, e As EventArgs) ' This code starts the timer when the
            i = 1 '                                                                        System Menu Functions cursor moves the
            Timer1.Start() '                                                               label Testing on the form. It sets i to 1                                                                
        End Sub '                                                                          so the forms location moves with the label.
    
        Dim i As Integer = 0
        Dim TestingCenter As Integer = 0
        Dim TestingLeft As Integer = 0
        Dim TestingTop As Integer = 0
        Dim TestingBottom As Integer = 0
        Dim FudgeFactor As Integer = 11 ' FudgeFactor takes into accout arrow movement which moves label ten points at a time.
        Dim TestingX As Integer = 0
        Dim BoundsLeft As Integer = 0
        Dim BoundsTop As Integer = 0
        Dim TestIt As Integer = 0
    
        Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick ' this timer is used to relocate the form when the
            Timer1.Stop() '                                                             label Testing is moved by the System Menu Move function.
            Label1.Text = Cursor.Position.X.ToString & " ... " & Cursor.Position.Y.ToString
            With Me.Controls("Testing")
                .Left = TestingLeft
                .Top = TestingTop
            End With
            If i = 1 Then
                Me.Location = New Point(Cursor.Position.X - TestingX, Cursor.Position.Y - TestingTop - 3) ' 3 is how far down the cursor is in label Testing during a System Menu move operation
            End If
            If Me.Left - BoundsLeft <= -TestingLeft + -TestingCenter + FudgeFactor Then ' Tests if left bound of labels movement met
                Label2.Text = "Left hit"
                Label3.Text = ""
                Label4.Text = ""
                Label5.Text = ""
                i = 2
                Counter = 0
                TestIt = 1
                apimouse_event(MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0) ' Places cursor on Button MyIcon
                SendKeys.Send("{Enter}") ' Sends enter key on Button MyIcon to start redisplay of System Menu
                BackgroundWorker1.RunWorkerAsync()
            ElseIf Me.Left - BoundsLeft >= Me.Width - TestingLeft - TestingCenter - FudgeFactor Then  ' Tests if right bound of labels movement met
                Label2.Text = ""
                Label3.Text = "Right hit"
                Label4.Text = ""
                Label5.Text = ""
                i = 2
                Counter = 0
                TestIt = 2
                apimouse_event(MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0)
                SendKeys.Send("{Enter}")
                BackgroundWorker1.RunWorkerAsync()
            ElseIf BoundsTop - Me.Top >= TestingTop + 3 - FudgeFactor Then ' Tests if top bound of labels movement met
                Label2.Text = ""
                Label3.Text = ""
                Label4.Text = "Top hit"
                Label5.Text = ""
                i = 2
                Counter = 0
                TestIt = 3
                apimouse_event(MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0)
                SendKeys.Send("{Enter}")
                BackgroundWorker1.RunWorkerAsync()
            ElseIf Me.Top - BoundsTop >= Me.Height - TestingTop - FudgeFactor - 3 Then  ' Tests if bottom bound of labels movement met
                Label2.Text = ""
                Label3.Text = ""
                Label4.Text = ""
                Label5.Text = "Bottom hit"
                i = 2
                Counter = 0
                TestIt = 4
                apimouse_event(MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0)
                SendKeys.Send("{Enter}")
                BackgroundWorker1.RunWorkerAsync()
            End If
            Timer1.Stop() ' The timer stops until the System Menu Move function moves the label again.
        End Sub
    
        Dim Counter As Integer = 0 ' used by a loop in the background worker giving the
        '                            System Menu time to display before the sub routine is called.
        '                            The sub routine sets the cursor to the Move function location then
        '                            sends Enter so the Move function cursor (size all) displays.
        '                            Depending on the users current movement of the form the sub routine
        '                            then sends an arrow key in that direction to get rid of the size all
        '                            cursor and continue with movement.
    
        Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Do Until Counter = 800000 ' Unfortunately this is an arbitrary number and may run faster or slower depending on the system
                Counter += 1 '          the program is on so it may not allow the System Menu Move function to display before the
            Loop '                      loop finishes. This would cause the TestIt subs to perform while no System Menu is displayed.
            If TestIt = 1 Then '        Or run too long so the System Menu is displayed too long and the user sees it.
                LeftTestIt()
            ElseIf TestIt = 2 Then
                RightTestIt()
            ElseIf TestIt = 3 Then
                UpTestIt()
            ElseIf TestIt = 4 Then
                DownTestIt()
            End If
        End Sub
    
        Private Sub LeftTestIt()
            Cursor.Position = New Point(Cursor.Position.X + 50, Cursor.Position.Y + 34) ' Offset of cursor postion at top left corner of System Menu to the Move function on my laptops screen
            SendKeys.SendWait("{Enter}") ' Sends Enter while cursor is on System Menu at Move location.
            SendKeys.SendWait("{Left}") ' Sends Arrow to remove cursor size all and allow Move function to continue working.
        End Sub
    
        Private Sub RightTestIt()
            Cursor.Position = New Point(Cursor.Position.X + 50, Cursor.Position.Y + 34)
            SendKeys.SendWait("{Enter}")
            SendKeys.SendWait("{Right}")
        End Sub
    
        Private Sub UpTestIt()
            Cursor.Position = New Point(Cursor.Position.X + 50, Cursor.Position.Y + 34)
            SendKeys.SendWait("{Enter}")
            SendKeys.SendWait("{Up}")
        End Sub
    
        Private Sub DownTestIt()
            Cursor.Position = New Point(Cursor.Position.X + 50, Cursor.Position.Y + 34)
            SendKeys.SendWait("{Enter}")
            SendKeys.SendWait("{Down}")
        End Sub
    
        Public Shared Function ResizeImage(ByVal image As Image, ByVal size As Size, Optional ByVal preserveAspectRatio As Boolean = True) As Image
            Dim newWidth As Integer
            Dim newHeight As Integer
            If preserveAspectRatio Then
                Dim originalWidth As Integer = image.Width
                Dim originalHeight As Integer = image.Height
                Dim percentWidth As Single = CSng(size.Width) / CSng(originalWidth)
                Dim percentHeight As Single = CSng(size.Height) / CSng(originalHeight)
                Dim percent As Single = If(percentHeight < percentWidth,
                        percentHeight, percentWidth)
                newWidth = CInt(originalWidth * percent)
                newHeight = CInt(originalHeight * percent)
            Else
                newWidth = size.Width
                newHeight = size.Height
            End If
            Dim newImage As Image = New Bitmap(newWidth, newHeight)
            Using graphicsHandle As Graphics = Graphics.FromImage(newImage)
                graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic
                graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight)
            End Using
            Return newImage
        End Function
    
    End Class


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


    Wednesday, August 21, 2013 7:06 AM