Stop MDI child form flickering when moves on MDI parent borderless form edges - vb.net

I am working on a project which contains MDI child forms. I have make my MDI child forms stop moving when user is trying to drag them out of MDI parent borderless form's edges. But, if user insists, MDI child form flickering like crazy!!!
Note that I have already set my forms to DoubleBuffered = True and I have also add me.Refresh() and me.parentform.Refresh() at the end of event.
Any idea what else can I do?
Here is an edited example of my code...
First we have the custom title bar control and this is the needed part of it's code:
Imports System.Windows.Forms
Imports System.ComponentModel
Public Class cmosTitleBar
Region "Custom events."
Public Event FormTitleBar_DoubleClick_Plus(sender As Object, e As EventArgs)
Public Event FormTitleBar_MouseDown_Plus(sender As Object, e As EventArgs)
Public Event FormTitleBar_MouseMove_Plus(sender As Object, e As EventArgs)
Public Event FormTitleBar_MouseEnter_Plus(sender As Object, e As EventArgs)
Public Event FormTitleBar_MouseLeave_Plus(sender As Object, e As EventArgs)
End Region
Region "Form Code."
Dim NewPoint As New System.Drawing.Point
Dim X, Y As Integer
Region "FormTitleBar Events."
Private Sub FormTitleBar_DoubleClick(sender As Object, e As EventArgs) Handles FormTitleBar.DoubleClick
RaiseEvent FormTitleBar_DoubleClick_Plus(sender, e)
Call PreventFlickering()
End Sub
Private Sub FormTitleBar_MouseDown(sender As Object, e As MouseEventArgs) Handles FormTitleBar.MouseDown, FormIcon.MouseDown, MyBase.MouseDown
If Not ParentForm.WindowState = FormWindowState.Maximized Then
X = Control.MousePosition.X - ParentForm.Location.X
Y = Control.MousePosition.Y - ParentForm.Location.Y
End If
RaiseEvent FormTitleBar_MouseDown_Plus(sender, e)
End Sub
Private Sub FormTitleBar_MouseMove(sender As Object, e As MouseEventArgs) Handles FormTitleBar.MouseMove, FormIcon.MouseMove, MyBase.MouseMove
If Not ParentForm.WindowState = FormWindowState.Maximized Then
If e.Button = Windows.Forms.MouseButtons.Left Then
NewPoint = Control.MousePosition
NewPoint.X -= (X)
NewPoint.Y -= (Y)
ParentForm.Location = NewPoint
End If
End If
Call PreventChildMoveOut()
RaiseEvent FormTitleBar_MouseMove_Plus(sender, e)
RaiseEvent FormIcon_MouseMove_Plus(sender, e)
Call PreventFlickering()
End Sub
Private Sub FormTitleBar_MouseEnter(sender As Object, e As EventArgs) Handles FormTitleBar.MouseEnter, FormIcon.MouseEnter
If ParentForm.WindowState = FormWindowState.Normal Then
FormTitleBar.Cursor = Cursors.NoMove2D
FormIcon.Cursor = Cursors.NoMove2D
Else
FormTitleBar.Cursor = Cursors.Default
FormIcon.Cursor = Cursors.Default
End If
RaiseEvent FormTitleBar_MouseEnter_Plus(sender, e)
End Sub
Private Sub FormTitleBar_MouseLeave(sender As Object, e As EventArgs) Handles FormTitleBar.MouseLeave
RaiseEvent FormTitleBar_MouseLeave_Plus(sender, e)
End Sub
End Region
End Region
Region "Custom subs."
Private Sub PreventFlickering()
If Me.ParentForm.IsMdiChild = True Then
Me.ParentForm.Refresh()
Me.ParentForm.ParentForm.Refresh()
Else
Me.ParentForm.Refresh()
End If
End Sub
Private Sub PreventChildMoveOut()
If ParentForm.IsMdiChild = True Then
If ParentForm.Left < ParentForm.MdiParent.ClientRectangle.Left Then
ParentForm.Left = ParentForm.MdiParent.ClientRectangle.Left
If ParentForm.Top < ParentForm.MdiParent.ClientRectangle.Top Then
ParentForm.Top = ParentForm.MdiParent.ClientRectangle.Top
ElseIf ParentForm.Bottom > ParentForm.MdiParent.ClientRectangle.Height - 98 Then
ParentForm.Top = ParentForm.MdiParent.ClientRectangle.Bottom - ParentForm.Height - 98
End If
ElseIf ParentForm.Right > ParentForm.MdiParent.ClientRectangle.Width Then
ParentForm.Left = ParentForm.MdiParent.ClientRectangle.Right - ParentForm.Width
If ParentForm.Top < ParentForm.MdiParent.ClientRectangle.Top Then
ParentForm.Top = ParentForm.MdiParent.ClientRectangle.Top
ElseIf ParentForm.Bottom > ParentForm.MdiParent.ClientRectangle.Height - 98 Then
ParentForm.Top = ParentForm.MdiParent.ClientRectangle.Bottom - ParentForm.Height - 98
End If
ElseIf ParentForm.Top < ParentForm.MdiParent.ClientRectangle.Top Then
ParentForm.Top = ParentForm.MdiParent.ClientRectangle.Top
ElseIf ParentForm.Bottom > ParentForm.MdiParent.ClientRectangle.Height - 98 Then
ParentForm.Top = ParentForm.MdiParent.ClientRectangle.Bottom - ParentForm.Height - 98
End If
End If
End Sub
End Region
End Class
Here is the needed code of my borderless MDI parent form which contains my custom title bar control:
Public Class MainForm
Region "Form Code."
Private Sub SettingsToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SettingsToolStripMenuItem.Click
SettingsForm.MdiParent = Me
SettingsForm.Show()
End Sub
End Region
End Class
Into my borderless MDI child forms which also contains my custom title bar control there is no code for this action cause everything (until now) happens into custom title bar control's code.

It is flickering because you are trying to restrict location to >= 0, and location moves to -1 then 0. Then as you try to coerce the form past your boundary, the location is really -1, 0, -1, 0, etc. You don't want to allow it to get to -1 in the first place. So instead restrict the cursor area when moving the mdi child.
To test, make a project with two forms.
MdiParentForm with IsMdiContainer = true
MdiChildForm
MdiParentForm code:
Public Class MdiParentForm
Private child As Form
Private Sub MdiParentForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
child = New MdiChildForm()
child.MdiParent = Me
child.Show()
End Sub
End Class
MdiChildForm code:
Public Class MdiChildForm
Private mouseIsDown As Boolean = False
Private myParent As Form
Private myRectangle As System.Drawing.Rectangle
Private myCursorLocation As System.Drawing.Point
Private myBorderWidth As Integer
Private myTitlebarHeight As Integer
Private Sub MdiChildForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
myParent = Me.MdiParent
End Sub
Private Sub MdiChildForm_MouseCaptureChanged(sender As Object, e As EventArgs) Handles Me.MouseCaptureChanged
If mouseIsDown Then
myRectangle = myParent.Bounds
myCursorLocation = Me.PointToClient(Cursor.Position)
myBorderWidth = (Me.Width - Me.ClientSize.Width) / 2
myTitlebarHeight = Me.Height - Me.ClientSize.Height - 2 * myBorderWidth
End If
End Sub
Private Sub MdiChildForm_Move(sender As Object, e As EventArgs) Handles Me.Move
If mouseIsDown Then
Cursor.Clip = New Rectangle(myRectangle.Left + myCursorLocation.X + myBorderWidth,
myRectangle.Top + myCursorLocation.Y + myTitlebarHeight,
myRectangle.Width - Me.Width - myBorderWidth,
myRectangle.Height - Me.Height)
Else
Cursor.Clip = Nothing
End If
End Sub
' there is no event for title bar click, so use WndProc
Protected Overrides Sub WndProc(ByRef m As Message)
MyBase.WndProc(m)
Select Case m.Msg
Case &H21
mouseIsDown = True
Case &H22
mouseIsDown = False
End Select
End Sub
End Class
Since you are using custom controls, you may need to tweak the Cursor.Clip rectangle dimensions and coordinates inside MdiChildForm_Move.

Related

How to save location of movable button in visual basic winform?

I have a movable button. the new location is save in my setting once it is mouse up event. when I move the button, sometimes the button disappear, after I re run it, it completely disappear.
How to save the button location before I close the app?
Public Class Form1
Dim x, y As Integer
Dim newpoint As New Point
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If My.Settings.button1_x70123454440211bghff > 0 Or My.Settings.button1_y70123454440211bghff > 0 Then
Me.Button1.Location = New Point(My.Settings.button1_x70123454440211bghff, My.Settings.button1_y70123454440211bghff)
End If
End Sub
Private Sub Button1_MouseMove(sender As Object, e As MouseEventArgs) Handles Button1.MouseMove
If e.Button = Windows.Forms.MouseButtons.Left Then
newpoint = Control.MousePosition
newpoint = Control.MousePosition
newpoint.X -= x
newpoint.Y -= y
Button1.Location = newpoint
End If
End Sub
Private Sub Button1_MouseDown(sender As Object, e As MouseEventArgs) Handles Button1.MouseDown
x = Control.MousePosition.X - Button1.Location.X
y = Control.MousePosition.Y - Button1.Location.Y
End Sub
Private Sub Button1_MouseUp(sender As Object, e As MouseEventArgs) Handles Button1.MouseUp
My.Settings.button1_x70123454440211bghff = x
My.Settings.button1_y70123454440211bghff = y
My.Settings.Save()
End Sub
Private Sub Form1_Closed(sender As Object, e As EventArgs) Handles Me.Closed
My.Settings.richtextbox1 = RichTextBox1.Text
End Sub
End Class
Follow this answer for button movement, and add some checks to keep the control within its parent container. For the setting, I like to keep things simple, and will take advantage of the ability of Visual Studio to store a struct in the settings, so instead I will use a System.Drawing.Point
Now you ask "How to save the button location before I close the app?" Well you can do it in Form_Close, or do it in the MouseUp event. Since you do it in the MouseUp, I will do the same. And I will load the last position in Form_Load
Public Class Form1
Private initialCursorPosition As System.Drawing.Point
Private intialButtonPosition As System.Drawing.Point
Private buttonIsMoving As Boolean = False
Private Sub Button1_MouseDown(sender As Object, e As MouseEventArgs) Handles Button1.MouseDown
Dim b = DirectCast(sender, Button)
initialCursorPosition = System.Windows.Forms.Cursor.Position
intialButtonPosition = b.Location
buttonIsMoving = True
End Sub
Private Sub Button1_MouseUp(sender As Object, e As MouseEventArgs) Handles Button1.MouseUp
buttonIsMoving = False
My.Settings.Button1Location = DirectCast(sender, Button).Location
End Sub
Private Sub Button1_MouseMove(sender As Object, e As MouseEventArgs) Handles Button1.MouseMove
If buttonIsMoving Then
Dim b = DirectCast(sender, Button)
Dim newX = intialButtonPosition.X - (initialCursorPosition.X - Cursor.Position.X)
Dim newY = intialButtonPosition.Y - (initialCursorPosition.Y - Cursor.Position.Y)
newX = Math.Max(Math.Min(newX, b.Parent.ClientSize.Width - b.Width), 0)
newY = Math.Max(Math.Min(newY, b.Parent.ClientSize.Height - b.Height), 0)
b.Location = New Point(newX, newY)
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Button1.Location = My.Settings.Button1Location
End Sub
End Class

Managing Dynamically created User Controls events

I have a User Control that is Dynamically created. It has to raise a Mouse_Move event & Mouse_Down event.
How to manage events for Multiple User Control that are created dynamically. I was considering using a list of user controls to track the controls. But I do not know how to setup the events properly.
Public Class UserControl1
Public Structure Porportions
Dim width_Percent As Double
Dim Height_percent As Double
Dim X_Location_Percent As Double
Dim Y_Location_Percent As Double
End Structure
Dim Pipe As Porportions
Dim guage1 As Porportions
Dim guage2 As Porportions
Public start_pos As Point
Public move_offset As Point
Public Client_Point As Point
Public Pipe_Source As Excel
Public Pipe_Data As DataSet
Public Pipe_Properties As Pipe
Private Pipe_ID As String
' Public Event Pipe_MouseMove(ByVal sender As Object, ByVal e As System.EventArgs)
Public Event Pipe_MouseMove1(ByVal sender As Object, ByVal e As System.EventArgs)
Public Event Pipe_MouseDown1(ByVal sender As Object, ByVal e As System.EventArgs)
Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
RaiseEvent Pipe_MouseMove1(sender, e)
End Sub
Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
RaiseEvent Pipe_MouseDown1(sender, e)
End Sub
Public Class Form1
Private pipe_cnt As Integer = 0
Private start_position As Point
Private MoveOffset As Point
Private Mouse_Position As Point
Private WithEvents pp As UserControl1
Private Sub Pipe_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles pp.Pipe_MouseMove1
Dim dx As Integer
Dim dy As Integer
Dim m_loc As Point
Dim scrn As Point
m_loc = New Point(e.Location)
Mouse_Position = New Point(e.X, e.Y)
scrn = PointToScreen(Mouse_Position)
Mouse_Position = PointToClient(Mouse_Position)
dx = start_position.X - Mouse_Position.X
dy = start_position.Y - Mouse_Position.Y
MoveOffset = New Point(dx, dy)
If e.Button = MouseButtons.Left Then
Try
pp.Location = New Point(pp.Left + e.X, pp.Top + e.Y)
pp.Location = New Point(pp.Left + e.X, pp.Top + e.Y)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End If
End Sub
Private Sub Pipe_MouseDown1(ByVal sender As Object, ByVal e As System.EventArgs) Handles pp.Pipe_MouseDown1
start_position = New Point(pp.Location)
End Sub
What I understand that you want to use an same event for multiple user controls. There are many methods to achieve this.
Method 1 (Easiest):
Just put handler events after Handles clause and separate them by commas ,. See example:
Private Sub MouseMove_Event(sender As Object, e As MouseEventArgs) Handles Pipe.MouseMove, PictureBox1.MouseMove
MsgBox("MouseMove")
End Sub
Private Sub Click_Event(sender As Object, e As MouseEventArgs) Handles Pipe.Click, PictureBox1.Click
MsgBox("Click")
End Sub
Private Sub MouseDown_Event(sender As Object, e As MouseEventArgs) Handles Pipe.MouseDown, PictureBox1.MouseDown
MsgBox("MouseDown")
End Sub
Method 2 (burden):
Create and collect all controls in a array of controls and then create events in a foreach loop.
Create Sub that gets array of controls and add handlers using foreach loop.
Private Sub CreateHandlers(Controls() As Control)
For Each control As Control In Controls
Me.Controls.Add(control)
AddHandler control.Click, AddressOf Click_Event
AddHandler control.MouseMove, AddressOf MouseMove_Event
AddHandler control.MouseDown, AddressOf MouseDown_Event
Next
End Sub
Your events
Private Sub Click_Event(sender As Object, e As EventArgs)
'Handle Click events here
End Sub
Private Sub MouseMove_Event(sender As Object, e As EventArgs)
'Handle MouseMove events here
End Sub
Private Sub MouseDown_Event(sender As Object, e As EventArgs)
'Handle MouseDown events here
End Sub
Create controls dynamically and just call CreateHandlers(controls) at end
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim pictureBox1 As PictureBox = New PictureBox _
With {
.Size = New Size(100, 100),
.Location = New Point(0, 0),
.BackColor = Color.Black
}
Dim panel1 As Panel = New Panel _
With {
.Size = New Size(100, 100),
.Location = New Point(100, 0),
.BackColor = Color.Red
}
Dim tableLayoutPanel1 As TableLayoutPanel = New TableLayoutPanel _
With {
.Size = New Size(100, 100),
.Location = New Point(200, 0),
.BackColor = Color.Green
}
Dim controls() As Control = {pictureBox1, panel1, tableLayoutPanel1}
CreateHandlers(controls)
End Sub
End Class

Change the color of a button(s) for a duration of time

I have a small VB.net app that has a LOT of buttons. I need to change the back color of the buttons when they are clicked and then set it back to its original color after a duration of 10 seconds. I am struggling with either using a timer or the time process both of which have their own issues.
Any ideas to make this work and work efficiently?
Code:
Private Sub MyButtons_Click(sender As Object, e As EventArgs) _
Handles Button1.Click,
Button2.Click
Dim myButton = DirectCast(sender, Button)
MakeCall()
myButton.BackColor = Color.Green
'TurnOnActiveCallCOLOR.Enabled = True
For i As Integer = 0 To 10000 - 1
Threading.Thread.Sleep(10000)
Next
myButton.BackColor = Color.FromArgb(64, 64, 64)
End Sub
Here is an example of using a Windows Forms Timer to accomplish what you need:
Private MyButton As Button
Private Sub MyButtons_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click
MyButton = DirectCast(sender, Button)
MyButton.BackColor = Color.Green
Timer1.Enabled = True
MakeCall()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
MyButton.BackColor = Color.FromArgb(64, 64, 64)
Timer1.Enabled = False
End Sub
To handle an arbitrary number of buttons, you could have something like this:
Public Class Form1
Dim buttonTimers As New Dictionary(Of Control, ButtonTimer)
Class ButtonTimer
Property Timeout As Integer = 2000
Property Target As Control
Property ActiveColor As Color = Color.Green
Property DefaultColor As Color = Color.FromArgb(64, 64, 64)
Private tim As Timer
Sub TimTick(sender As Object, e As EventArgs)
tim.Stop()
Target.BackColor = DefaultColor
End Sub
Sub New()
' empty constructor
End Sub
Sub New(target As Control)
Me.Target = target
Me.Target.BackColor = Me.ActiveColor
tim = New Timer With {.Interval = Timeout}
AddHandler tim.Tick, AddressOf TimTick
tim.Start()
End Sub
Sub Restart()
Target.BackColor = Me.ActiveColor
If tim IsNot Nothing Then
tim.Stop()
tim.Start()
End If
End Sub
Public Sub DisposeOfTimer()
If tim IsNot Nothing Then
tim.Stop()
RemoveHandler tim.Tick, AddressOf TimTick
tim.Dispose()
End If
End Sub
End Class
Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click
Dim myButton = DirectCast(sender, Button)
'MakeCall()
If buttonTimers.ContainsKey(myButton) Then
buttonTimers(myButton).Restart()
Else
buttonTimers.Add(myButton, New ButtonTimer(myButton))
End If
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
For Each x In buttonTimers
x.Value.DisposeOfTimer()
Next
End Sub
End Class
If a button is clicked again before the timeout, the time is restarted.
You can add other constructors if you want to have a different timeout/colours for different buttons.
The MyBase.FormClosing code should be included in your form closing handler (if there is one) so that the timers are cleaned up properly.
I expect it would be tidier overall to make your own custom button class which inherits from Button, so you might want to investigate doing that. (How to: Inherit from Existing Windows Forms Controls.)
asynh and await if you don't want use timer. Simple method using task.delay
Private Async Sub ButtonClick(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click, Button3.Click, Button4.Click
DirectCast(sender, Button).BackColor = Color.Red 'after click setcolor to red
Await setColorAfterDelay(sender) 'Add this comand on button click and don't forget add asynh before sub in this method
End Sub
Public Async Function setColorAfterDelay(sender As Object) As Task
Await Task.Delay(1000) ''Milisecound how long you wana dealey
DirectCast(sender, Button).BackColor = Color.White 'and set colorto white
End Function
With the use of lambda expressions (and a lookup table if you want to interact with it further) you can do this pretty easily:
'Lookup table for if you want to be able to interact with the timers even more.
Dim ButtonTimers As New Dictionary(Of Button, Timer)
Private Sub MyButtons_Click(sender As Object, e As EventArgs) _
Handles Button1.Click, Button2.Click
MakeCall()
Dim myButton = DirectCast(sender, Button)
myButton.BackColor = Color.Green
'If a timer already exists for the button, restart it.
Dim existingTimer As Timer = Nothing
If ButtonTimers.TryGetValue(myButton, existingTimer) Then
existingTimer.Stop()
existingTimer.Start()
Return 'Do not execute the rest of the code.
End If
'Create the timer and set its Interval to 10000 ms (10 seconds).
Dim buttonTimer As New Timer() With {.Interval = 10000}
'Add a handler to its Tick event.
AddHandler buttonTimer.Tick, _
Sub(tsender As Object, te As EventArgs)
myButton.BackColor = Color.FromArgb(64, 64, 64)
'Dispose timer and remove from lookup table.
ButtonTimers.Remove(myButton)
buttonTimer.Stop()
buttonTimer.Dispose()
End Sub
ButtonTimers.Add(myButton, buttonTimer)
buttonTimer.Start()
End Sub
If you want to interact with a button's timer (if one exists) you can do:
Dim buttonTimer As Timer = Nothing
If ButtonTimers.TryGetValue(yourButtonHere) Then
'Do something with buttonTimer...
End If
This could probably be done better by dynamically creating timer controls so each button has it's own timer but here is what I came up with.
Oh, an set your timer to 1000 interval and enabled to 'False'.
Public Class Form1
Dim T1 As Integer = 0
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
T1 = T1 + 1
If T1 = 10 Then
For Each button In Controls
button.backcolor = Color.FromArgb(225, 225, 225)
Next
Timer1.Stop()
T1 = 0
End If
Me.Text = T1
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Button1.BackColor = Color.Red
Timer1.Start()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Button2.BackColor = Color.Orange
Timer1.Start()
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Button3.BackColor = Color.Yellow
Timer1.Start()
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Button4.BackColor = Color.Green
Timer1.Start()
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Button5.BackColor = Color.Blue
Timer1.Start()
End Sub
End Class

Click and drag implementation on a rectangle VB.NET

So my problem is that I want to have multiple rectangles on a form at a time. However I also want these rectangles to be able to be clicked and dragged across the form.
This is my current code for clicking and dragging a rectangle that was drawn onto the form using the toolbox.
Public Class DragRectangle
Dim Go As Boolean
Dim LeftSet As Boolean
Dim TopSet As Boolean
Dim HoldLeft As Integer
Dim HoldTop As Integer
Dim OffLeft As Integer
Dim OffTop As Integer
Private Sub obj1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles RectangleShape1.MouseUp
Go = False
LeftSet = False
TopSet = False
End Sub
Private Sub obj1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles RectangleShape1.MouseDown
Go = True
End Sub
Private Sub obj1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles RectangleShape1.MouseMove
If Go = True Then
HoldLeft = (Control.MousePosition.X - Me.Left)
HoldTop = (Control.MousePosition.Y - Me.Top)
If TopSet = False Then
OffTop = HoldTop - sender.Top
TopSet = True
End If
If LeftSet = False Then
OffLeft = HoldLeft - sender.Left
LeftSet = True
End If
sender.Left = HoldLeft - OffLeft
sender.Top = HoldTop - OffTop
End If
End Sub
End Class
This works fine for one rectangle, although this requires the rectangles to be pre-drawn onto the form using the toolbox.
What I would like is a rectangle gets drawn by clicking a button on the form, and the newly drawn rectangle can also be clicked and dragged into a new location.
Is this possible?
Thanks for any help
Working example:
Public Class Form1
Private Property Rectangles As New List(Of DrgRectangle)
Private Property curRect As DrgRectangle
Private _x As Integer
Private _y As Integer
Private Sub loadme() Handles Me.Load
'load the rectangle in list
Rectangles.Add(New DrgRectangle With {.Rect = New Rectangle(20, 20, 20, 20)})
End Sub
Private Sub FormMouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
_x = e.X
_y = e.Y
For Each rect In Rectangles
If rect.Rect.Contains(e.X, e.Y) Then
curRect = rect
Exit For
End If
Next
End Sub
Private Sub FormMouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
If e.Button = Windows.Forms.MouseButtons.Left Then
If curRect IsNot Nothing Then
curRect.Rect = New Rectangle(New Point(curRect.Rect.Location.X + (e.X - _x), curRect.Rect.Location.Y + (e.Y - _y)), curRect.Rect.Size)
Me.Refresh()
End If
End If
_x = e.X
_y = e.Y
End Sub
Private Sub FormPaint(sender As Object, e As PaintEventArgs) Handles me.Paint
For Each rect In Rectangles
e.Graphics.DrawRectangle(Pens.Black, rect.Rect)
Next
End Sub
End Class
Public Class DrgRectangle
Public Rect As New Rectangle
'add more properties as needed
End Class

PictureBox - Opacity paint inside given coordinates

I have a Picturebox and inside that I want to paint (with opacity to don't full hide the painted region) a determinated region of the picture with the coordniates given.
So far I've the 'IF' statement to when user click the picturebox it checks if is the region with the correct coordinates:
If LocalMousePosition.X >= 87 And LocalMousePosition.X <= 131 And LocalMousePosition.Y >= 5 And LocalMousePosition.Y <= 55 Then
Label1.Text = "coordinate correct"
Else
Label1.Text = ""
End If
Now I've no idea how to paint the clicked region.
Thanks in advance.
Try something like...
Public Class Form1
Private InTarget As Boolean = False
Private Target As New Rectangle(New Point(87, 5), New Size(45, 51))
Private Sub PictureBox1_Click(sender As System.Object, e As System.EventArgs) Handles PictureBox1.Click
Dim clientCoords As Point = PictureBox1.PointToClient(Cursor.Position)
InTarget = Target.Contains(clientCoords)
Label1.Text = IIf(InTarget, "coordinate correct", "")
PictureBox1.Refresh()
End Sub
Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
If InTarget Then
Using highlight As New SolidBrush(Color.FromArgb(128, Color.Yellow)) ' 0 to 255
e.Graphics.FillRectangle(highlight, Target)
End Using
End If
End Sub
End Class