How can I drag a bordeless window from any object in VB.NET? - vb.net

My form is set to bordeless, and I found code that allows me to drag the form around by simply clicking someone on the form and dragging the window about.
Dim IsDraggingForm As Boolean = False
Private MousePos As New System.Drawing.Point(0, 0)
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseDown
If e.Button = MouseButtons.Left Then
IsDraggingForm = True
MousePos = e.Location
End If
End Sub
Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseUp
If e.Button = MouseButtons.Left Then IsDraggingForm = False
End Sub
Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseMove
If IsDraggingForm Then
Dim temp As Point = New Point(Me.Location + (e.Location - MousePos))
Me.Location = temp
temp = Nothing
End If
End Sub
The problem is that my form is mostly full of control objects such as Labels, and a ListBox that have no visible borders. Attempting to drag the window clicked on these control objects does not allow this.

A solution could be to enable KeyPreview and set a keyboard short-cut to enable moving the Form (you can use Control.MousePosition to follow the mouse) on the KeyDown event and release on KeyUp.
If you're definitely after moving everything with a Click, you can set a callback from using PInvoke ( Global mouse event handler ) checking the location of the mouse is within your Form area and the Form is in focus and then do the same job with Form.Location and Control.MousePosition.

Use the following code:- (After removing your code for dragging)
<DllImportAttribute("user32.dll")> _
Public Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As Integer, lParam As Integer) As Integer
End Function
<DllImportAttribute("user32.dll")> _
Public Shared Function ReleaseCapture() As Boolean
End Function
Private Sub Object_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles <Object>.MouseDown
If e.Button = MouseButtons.Left Then
ReleaseCapture()
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0)
End If
End Sub
Replace <Object> (8th Line, after 'Handles') with the name of the object you want as the handle for dragging.

Related

VB.NET optimizing drag & drop code

I'm currently struggling with drag & drop code. I have 3 images that are at the top, and I want to add them in a random order in a flow-layout-panel.
I have this code for adding the square image into the flow-layout-panel, but I have got the feeling that this is not 100% correct. Is it possible to add these with 1 sub instead of 3?
And how do you write a sub that detects what object in being dragged? Now my sub just adds a square with each dragdrop event. But I need it to drop a Square only when a Square is being dragged and drop a Trapezium or round when it's being dragged.
Public Class Form2
Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
' Initiate dragging.
PictureBox1.DoDragDrop(PictureBox1, DragDropEffects.Copy)
End Sub
Private Sub PictureBox2_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox2.MouseMove
' Initiate dragging.
PictureBox2.DoDragDrop(PictureBox2, DragDropEffects.Copy)
End Sub
Private Sub PictureBox3_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox3.MouseMove
' Initiate dragging.
PictureBox3.DoDragDrop(PictureBox2, DragDropEffects.Copy)
End Sub
Private Sub FlowLayoutPanel1_DragEnter(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DragEventArgs) Handles FlowLayoutPanel1.DragEnter
' Check the format of the data being dropped.
If (e.Data.GetDataPresent(GetType(PictureBox))) Then
' Display the copy cursor.
e.Effect = DragDropEffects.Copy
Else
' Display the no-drop cursor.
e.Effect = DragDropEffects.None
End If
End Sub
Private Sub FlowLayoutPanel1_DragDrop(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DragEventArgs) Handles FlowLayoutPanel1.DragDrop
Dim oPB As New PictureBox()
oPB.Image = Image.FromFile("C:\Users\Jef\Desktop\square.jpg")
oPB.Visible = True
oPB.Width = 100
oPB.Height = 100
oPB.SizeMode = PictureBoxSizeMode.CenterImage
FlowLayoutPanel1.Controls.Add(oPB)
End Sub
You already got the answer in your previous question:
Private Sub FlowLayoutPanel1_DragDrop(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DragEventArgs) Handles FlowLayoutPanel1.DragDrop
Dim oPB As New PictureBox()
Dim pb = CType(e.Data.GetData(GetType(PictureBox)))
oPB.Image = pb.Image
pb.Image = Nothing '' Optional
'' etc...
End Sub
You do have a bug, the probable reason why you did not use the answer:
Private Sub PictureBox3_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox3.MouseMove
' Initiate dragging.
PictureBox3.DoDragDrop(PictureBox2, DragDropEffects.Copy)
End Sub
Note how it drags the wrong control, PictureBox2 instead of PictureBox3. You avoid bugs like this by writing DRY code, Do not Repeat Yourself. The sender argument of a MouseMove event already gives you a reference to the control. So you just need one event handler for all three controls:
Private Sub PictureBox_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove, PictureBox2.MouseMove, PictureBox3.MouseMove
' Initiate dragging.
Me.DoDragDrop(sender, DragDropEffects.Copy)
End Sub
With the detail that we now let the Form support DoDragDrop(). Which only matters if you implement the GiveFeedback or QueryContinueDrag events.

How Do I Force An Action When A Dialog Box Closes In VB.Net?

I am wondering how to force my main gui to update when a dialog box such as a SaveFileDialog box closes. I have tried Main.LostFocus, Main.GotFocus, Main.Enter, Main.MouseEnter, Main.MouseLeave, and Main.MouseMove, but no matter what function I try I can never get the result I am looking for.
The dialog box is opened when a picture is clicked. The picture changes when it is clicked and again when the icon_new.MouseUp is called. The problem is that it acts correctly until the dialog is closed. At this point the picture changes back to the image it had when the mouse was over it.
Here is what the picture does regularly:
Private Sub icon_new_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles icon_new.MouseDown
icon_new.Image = My.Resources.NewMapClick
End Sub
Private Sub icon_new_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles icon_new.MouseUp
icon_new.Image = My.Resources.NewMapHover
End Sub
Private Sub icon_new_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles icon_new.MouseEnter
icon_new.Image = My.Resources.NewMapHover
End Sub
Private Sub icon_new_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles icon_new.MouseLeave
icon_new.Image = My.Resources.NewMapDefault
End Sub
This works until the dialog box is closed, at which point it the image becomes NewMapHover when it should be NewMapDefault, because the mouse is no longer within the bounds of the picture. In the calls such as Main.LostFocus, Main.GotFocus, or Main.Whatever I have icon_new.image = My.Resources.NewMapDefault, but even if this call triggers, the image ends up as NewMapHover. I'm not sure why this is happening or how to fix it. Any help is greatly appreciated.
EDIT: This is the click event that calls the dialog_box
Private Sub icon_new_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles icon_new.Click
If file_created = True Then
save()
Else 'file_created = false'
SaveWindow.FileName = txt_name.Text
If SaveWindow.ShowDialog() = DialogResult.OK Then
file_path = SaveWindow.FileName
End If
file_created = True
End If
save()
new_file()
End Sub
If the file hasn't been saved, then a dialog box opens, prompting the user to save the file. I've also toyed with a MsgBox() that has Yes, No, and Cancel, prompts, but for simplicity I took it out because the results were the same and one third of the time the SaveFile dialog will come up anyway.
Try doubleclicking your SaveFileDialog, which will open up the SaveFileDialog_FileOk event code, and then put the same code there as in the MouseLeave event.
This event will fire when the SaveFileDialog is about to close after you've pressed the "Save" button.
EDIT:
You can try doing this in your click event:
Dim DResult As DialogResult
DResult = SaveFileDialog1.ShowDialog()
If DResult = System.Windows.Forms.DialogResult.OK Then
'Code for when you press the save button, and when the image should change
ElseIf DResult = System.Windows.Forms.DialogResult.Cancel Then
'Code for image change...
End If
Try
Private Sub icon_new_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles icon_new.MouseUp
Dim pnt As Point
Dim rect As Rectangle
rect.X = icon_new.Location.X
rect.Y = icon_new.Location.Y
rect.Width = icon_new.Width
rect.Height = icon_new.Height
pnt = PointToClient(Cursor.Position)
If Not rect.Contains(pnt) Then
Return
End If
icon_new.Image = My.Resources.NewMapHover
End Sub
Valter
This is the code I originally had.
Private Sub icon_new_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles icon_new.MouseUp
icon_new.Image = My.Resources.NewMapHover
End Sub
I added the variable dialog_open as a boolean and set it to true whenever I called SaveFile.ShowDialog(). I then changed my MouseUp event to this:
Private Sub icon_new_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles icon_new.MouseUp
icon_new.Image = My.Resources.NewMapHover
If dialog_open = True Then
icon_new.Image = My.Resources.NewMapDefault
dialog_open = False
End If
End Sub
Thanks to #valter and #Kevin Hogg for suggesting I edit the MouseUp event.

Cancelling of Drag/Drop on DataGridView

I am using basic Drag/Drop functionality in single DataGridView.
Like this:
Private Sub DataGridView1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView1.DragDrop
Dim p As Point = Me.PointToClient(New Point(e.X, e.Y))
dropindex = DataGridView1.HitTest(p.X, p.Y).RowIndex
If (e.Effect = DragDropEffects.Move) Then
Dim dragRow As DataGridViewRow = CType(e.Data.GetData(GetType(DataGridViewRow)), DataGridViewRow)
'' SOME PROCEDURE HERE FOR DROPPING ---
End If
End Sub
Private Sub DataGridView1_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView1.DragOver
e.Effect = DragDropEffects.Move
End Sub
Private Sub DataGridView1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DataGridView1.MouseDown
dragindex = DataGridView1.HitTest(e.X, e.Y).RowIndex
If dragindex > -1 Then
Dim dragSize As Size = SystemInformation.DragSize
dragrect = New Rectangle(New Point(CInt(e.X - (dragSize.Width / 2)), CInt(e.Y - (dragSize.Height / 2))), dragSize)
Else
dragrect = Rectangle.Empty
End If
End Sub
Private Sub DataGridView1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DataGridView1.MouseMove
If (e.Button And MouseButtons.Left) = MouseButtons.Left Then
If (dragrect <> Rectangle.Empty AndAlso Not dragrect.Contains(e.X, e.Y)) Then
Me.DoDragDrop(DataGridView1.Rows(dragindex), DragDropEffects.Move)
End If
End If
End Sub
When I push left mouse button and start to drag some square appears under a cursor and dragging begins.
If I release button on certain row dropping occurs (normally:)
But, if during dragging I change a mind and press ESC key those square under cursor dissappears but dropping occurs anyway when I release button.
What to do to cancel dropping when dragging already begins (say with ESC key)?
Me.DoDragDrop(DataGridView1.Rows(dragindex), DragDropEffects.Move)
You made a mistake there. The QueryContinueDrag event is raised on the control that called DoDragDrop(). You used Me, making the form the source of the data. But you implemented the QueryContinueDrag for DataGridView1, not the form. So your event handler never runs. Fix:
DataGridView1.DoDragDrop(DataGridView1.Rows(dragindex), DragDropEffects.Move)
You cannot track ESC by relying on the Key Event methods of the DataGridView, because are not triggered while you are drag-dropping. But there is an easy way to account for this situation (drag-drop process interrupted): DragLeave Event. You can make the condition for dropping depend upon a global flag set in this method. Sample code:
Dim cancelDrop As Boolean
Private Sub DataGridView1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles DataGridView1.DragDrop
Dim p As Point = Me.PointToClient(New Point(e.X, e.Y))
dropindex = DataGridView1.HitTest(p.X, p.Y).RowIndex
If (e.Effect = DragDropEffects.Move AndAlso Not cancelDrop) Then
Dim dragRow As DataGridViewRow = CType(e.Data.GetData(GetType(DataGridViewRow)), DataGridViewRow)
'' SOME PROCEDURE HERE FOR DROPPING ---
End If
cancelDrop = False
End Sub
Private Sub DataGridView1_DragLeave(sender As Object, e As System.EventArgs) Handles DataGridView1.DragLeave
cancelDrop = True
End Sub

Allow a user to move a borderless window

I have a form without borders that I would like the user to be able to move. I have not been able to find anything that would allow me to do so.
Is it possible to move a window with the border set to None?
Introduce a Boolean variable which holds the state if the form is currently dragged and variables which hold the starting point of the drag. Then OnMove move the form accordingly. As this has already been answered elsewhere, I just copy&paste it here.
Class Form1
Private IsFormBeingDragged As Boolean = False
Private MouseDownX As Integer
Private MouseDownY As Integer
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseDown
If e.Button = MouseButtons.Left Then
IsFormBeingDragged = True
MouseDownX = e.X
MouseDownY = e.Y
End If
End Sub
Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseUp
If e.Button = MouseButtons.Left Then
IsFormBeingDragged = False
End If
End Sub
Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseMove
If IsFormBeingDragged Then
Dim temp As Point = New Point()
temp.X = Me.Location.X + (e.X - MouseDownX)
temp.Y = Me.Location.Y + (e.Y - MouseDownY)
Me.Location = temp
temp = Nothing
End If
End Sub
End Class
stolen from http://www.dreamincode.net/forums/topic/59643-moving-form-with-formborderstyle-none/
All 'simple' VB answers made my form jump all over the place with multiple screens. So i derived this from same answer in C# and it works like a charm :
Public Const WM_NCLBUTTONDOWN As Integer = 161
Public Const HT_CAPTION As Integer = 2
then
<DllImport("User32")> Private Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As Integer, lParam As Integer) As Integer
End Function
<DllImport("User32")> Private Shared Function ReleaseCapture() As Boolean
End Function
and finally
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
If (e.Button = MouseButtons.Left) Then
ReleaseCapture()
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0)
End If
End Sub
Dim offSetX As Integer
Dim offSetY As Integer
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.Location = New Point(Cursor.Position.X - offSetX, Cursor.Position.Y - offSetY)
End Sub
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
offSetX = PointToClient(Cursor.Position).X
offSetY = PointToClient(Cursor.Position).Y
Timer1.Enabled = True
End Sub
Private Sub Form1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
Timer1.Enabled = False
End Sub
This is slightly scruffy way of doing it xD
Hope it helps though =]
Another way of doing this is to handle the WM_NCHITTEST message . This allows you to have parts of your form respond to mouse events as the title bar, borders, etc. would for a window with borders. For example, if you have a label on your form and you return HTCAPTION in the WM_NCHITTEST handler, you will be able to move the form by dragging this label just as you can move a regular window by dragging on its title bar. See this Stack Overflow question for example code.

Drag drop a usercontrol in vb.net

I have, what should be , a very simple problem, but now I have used 5 hours without results.
I have a usercontrol, UserControl1, which I want to drag and drop on my form, Form1.
That’s it. It should be simple, but I have googled for hours without results. Does anybody have a sample code to fix this?
I dont know what a user control is (I'm still learning) but I found something that might help.
In this code, add two TextBox controls to a form and set the AllowDrop property of the second TextBox control to True.
Then use this code to enable drag and drop
Private MouseIsDown As Boolean = False
Private Sub TextBox1_MouseDown(ByVal sender As Object, ByVal e As _
System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseDown
' Set a flag to show that the mouse is down.
MouseIsDown = True
End Sub
Private Sub TextBox1_MouseMove(ByVal sender As Object, ByVal e As _
System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseMove
If MouseIsDown Then
' Initiate dragging.
TextBox1.DoDragDrop(TextBox1.Text, DragDropEffects.Copy)
End If
MouseIsDown = False
End Sub
Private Sub TextBox2_DragEnter(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DragEventArgs) Handles TextBox2.DragEnter
' Check the format of the data being dropped.
If (e.Data.GetDataPresent(DataFormats.Text)) Then
' Display the copy cursor.
e.Effect = DragDropEffects.Copy
Else
' Display the no-drop cursor.
e.Effect = DragDropEffects.None
End If
End Sub
Private Sub TextBox2_DragDrop(ByVal sender As Object, ByVal e As _
System.Windows.Forms.DragEventArgs) Handles TextBox2.DragDrop
' Paste the text.
TextBox2.Text = e.Data.GetData(DataFormats.Text)
End Sub
I hope that you can use this for a usercontrol. Good luck and comment!
Here is the code, I have used, to get it work.
Now I have a form, Form1, and a usercontrol, Usercontrol1. To drag the usercontrol, I inserted a panel in the top of the usercontrol, and only if the user pressed the panel (panel1), the control should to move - like normal windows forms.
Public Class UserControl1
Shared mypositionX As Integer
Shared mypositionY As Integer
Shared mBlnFormDragging As Boolean
Shared drawBeginX As Integer
Shared drawBeginY As Integer
Shared drawing As Boolean
Private Sub Panel1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseMove
If mBlnFormDragging = True Then
Dim position As Point = Form1.PointToClient(MousePosition)
Me.Location = New Point(position)
End If
End Sub
Private Sub Panel1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseUp
' Dim dd1 As DragDropEffects = DoDragDrop(ParentForm, DragDropEffects.Move)
mBlnFormDragging = False
Dim position As Point = Form1.PointToClient(MousePosition)
Location = New Point(position)
End Sub
Public Sub Panel1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseDown
'Dim dd1 As DragDropEffects = DoDragDrop(ParentForm, DragDropEffects.Move)
mBlnFormDragging = True
End Sub