Drag and drop for groupbox/picturebox vs textbox vb.net



是只有我,还是groupbox/picturebox与textbox的拖放方式不同?我有这个拖放代码,允许我调整大小和拖放控件。然而,每当我尝试使用groupbox/picturebox时,控件都会反复闪烁且不移动,并且我的鼠标光标会卡在父控件中。动态创建的文本框不会发生这种情况。我需要为groupbox/picturebox启用什么吗?

拖放dll

#Region "     class library"
#Region "     imports"
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Runtime.InteropServices
#End Region
Public Class controlHandler
#Region "     global variables"
Private horizontalMidPoint As Integer
Private verticalMidPoint As Integer
Private locations() As Point
Private width As Control
Private height As Control
Private dpiX As Integer
Private dpiY As Integer
Private myControl As Control
Private controlType As String
Public Structure boundControl
Public mControl As Control
Public mParent As Control
Public Sub New(ByVal parent As Control, ByVal control As Control)
mParent = parent
mControl = control
End Sub
End Structure
Private activeControl As Control = Nothing
Private activeControlParent As Control = Nothing
#End Region
#Region "     properties"
Private _boundControls As New List(Of boundControl)
Public ReadOnly Property boundControls As List(Of boundControl)
Get
Return _boundControls
End Get
End Property
Public Property boundingRectangle As Rectangle
Private _canDeselect As Boolean = True
Public Property canDeselect As Boolean
Get
Return _canDeselect
End Get
Set(ByVal value As Boolean)
_canDeselect = value
End Set
End Property
#End Region
#Region "    WidthHeightSetter"
Public Sub setWidthHeightBoxes(w As Control, h As Control, x As Integer, y As Integer, bound As boundControl)
width = w
height = h
myControl = bound.mControl
dpiX = x
dpiY = y
AddHandler myControl.SizeChanged, AddressOf myControl_ResizeHandler
End Sub
#End Region
#Region "    Resize Handler"
Private Sub myControl_ResizeHandler(ByVal sender As Object, ByVal e As EventArgs)
Dim w As Double
Dim h As Double
w = (Convert.ToDouble(myControl.Size.Width()) / dpiX) / 2
h = (Convert.ToDouble(myControl.Size.Height()) / dpiY) / 2

width.Text = FormatNumber(CDbl(Convert.ToString(w)), 2)
height.Text = FormatNumber(CDbl(Convert.ToString(h)), 2)
'Debug.Print(FormatNumber(CDbl(Convert.ToString(w)), 2))
'Debug.Print(FormatNumber(CDbl(Convert.ToString(h)), 2))
End Sub
#End Region
#Region "    controlType getter/setter"
Public Sub setControlType(s As String)
controlType = s
End Sub
Public Function getControlType() As String
Return controlType
End Function
#End Region
#Region "     initialize"
Public Sub bindControls()
For x As Integer = 0 To _boundControls.Count - 1
Dim ctrl As Control = _boundControls(x).mControl
AddHandler ctrl.MouseDown, AddressOf mControl_mousedown
AddHandler ctrl.Paint, AddressOf mControl_Paint
AddHandler ctrl.Resize, AddressOf mControl_Resize
AddHandler ctrl.Move, AddressOf mControl_Move
Dim parent As Control = _boundControls(x).mParent
Next
End Sub
#End Region
#Region "     drag handles"
Public Sub deselectAll()
If activeControl IsNot Nothing And canDeselect Then
activeControl = Nothing
boundingRectangle = Nothing
For x As Integer = 0 To 8
pb(x).Dispose()
Next
activeControlParent.Invalidate()
End If
End Sub
Private pb(8) As PictureBox
Private Sub addDragHandles()
Dim sizeCursor() As Cursor = {Cursors.SizeNWSE, Cursors.SizeNS, Cursors.SizeNESW, Cursors.SizeWE, _
Cursors.SizeNWSE, Cursors.SizeNS, Cursors.SizeNESW, Cursors.SizeWE}
Dim smConstants() As Integer = {HTTOPLEFT, HTTOP, HTTOPRIGHT, HTRIGHT, HTBOTTOMRIGHT, _
HTBOTTOM, HTBOTTOMLEFT, HTLEFT}
For x As Integer = 1 To 8
pb(x - 1) = New PictureBox
With pb(x - 1)
.BackColor = Color.White
.Size = New Size(6, 6)
.BorderStyle = BorderStyle.FixedSingle
.Location = locations(x - 1)
.Cursor = sizeCursor(x - 1)
.Tag = smConstants(x - 1)
activeControlParent.Controls.Add(pb(x - 1))
.BringToFront()
AddHandler .MouseDown, AddressOf pbsMouseDown
AddHandler .MouseMove, AddressOf pbsMouseMove
End With
Next
pb(8) = New PictureBox
pb(8).Size = New Size(15, 15)
pb(8).BorderStyle = BorderStyle.None
pb(8).Location = locations(8)
pb(8).Cursor = Cursors.SizeAll
pb(8).Image = My.Resources.move
activeControlParent.Controls.Add(pb(8))
pb(8).BringToFront()
AddHandler pb(8).MouseDown, AddressOf move_mousedown
AddHandler pb(8).MouseMove, AddressOf move_mousemove
End Sub
#End Region
#Region "     resize handles"
Private mouseOnHandle As Boolean = False
Private Sub pbsMouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
mouseOnHandle = True
End Sub
Private Sub pbsMouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If mouseOnHandle Then
ReleaseCapture()
SendMessage(activeControl.Handle, WM_NCLBUTTONDOWN, CInt(DirectCast(sender, PictureBox).Tag), 0)
If GetCapture = 0 Then mouseOnHandle = False
Application.DoEvents()
End If
End Sub
#Region "     move resize handles"
Private Sub paintresize()
If activeControl IsNot Nothing Then
horizontalMidPoint = CInt(activeControl.Left + (activeControl.Width / 2))
verticalMidPoint = CInt(activeControl.Top + (activeControl.Height / 2))
locations = New Point() _
{New Point(activeControl.Left - 3, activeControl.Top - 3), New Point(horizontalMidPoint - 3, activeControl.Top - 3),
New Point(activeControl.Right - 2, activeControl.Top - 3), New Point(activeControl.Right - 2, verticalMidPoint - 3),
New Point(activeControl.Right - 2, activeControl.Bottom - 2), New Point(horizontalMidPoint - 3, activeControl.Bottom - 2),
New Point(activeControl.Left - 3, activeControl.Bottom - 2), New Point(activeControl.Left - 3, verticalMidPoint - 3),
New Point(activeControl.Left + 9, activeControl.Top - 10)}
For x As Integer = 0 To 8
pb(x).Location = locations(x)
Next
End If
End Sub
#End Region
#End Region
#Region "     move handle"
Private mouseOnMove As Boolean = False
Private Sub move_mousedown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
mouseOnMove = True
End Sub
Private Sub move_mousemove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If mouseOnMove Then
ReleaseCapture()
SendMessage(activeControl.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0)
If GetCapture = 0 Then
mouseOnMove = False
For x As Integer = 0 To 8
pb(x).BringToFront()
Next
End If
End If
End Sub
#End Region
#Region "     control eventHandlers"
Private Sub mControl_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
Application.DoEvents()
If sender Is activeControl Then
drawBoundingRectangle()
paintresize()
End If
End Sub
Private Sub mControl_Resize(ByVal sender As Object, ByVal e As System.EventArgs)
If activeControl IsNot Nothing Then
activeControl.Invalidate()
Application.DoEvents()
drawBoundingRectangle()
paintresize()
End If

End Sub
Private Sub mControl_Move()
If activeControl IsNot Nothing Then
activeControl.Invalidate()
Application.DoEvents()
drawBoundingRectangle()
paintresize()
End If
End Sub

Private Sub mControl_mousedown(ByVal sender As Object, ByVal e As System.EventArgs)
If activeControlParent IsNot Nothing Then activeControlParent.Invalidate()
Dim newCtrl As Control = DirectCast(sender, Control)
horizontalMidPoint = CInt(newCtrl.Left + (newCtrl.Width / 2))
verticalMidPoint = CInt(newCtrl.Top + (newCtrl.Height / 2))
locations = New Point() _
{New Point(newCtrl.Left - 3, newCtrl.Top - 3), New Point(horizontalMidPoint - 3, newCtrl.Top - 3), _
New Point(newCtrl.Right - 2, newCtrl.Top - 3), New Point(newCtrl.Right - 2, verticalMidPoint - 3), _
New Point(newCtrl.Right - 2, newCtrl.Bottom - 2), New Point(horizontalMidPoint - 3, newCtrl.Bottom - 2), _
New Point(newCtrl.Left - 3, newCtrl.Bottom - 2), New Point(newCtrl.Left - 3, verticalMidPoint - 3), _
New Point(newCtrl.Left + 9, newCtrl.Top - 10)}
If activeControl IsNot Nothing Then
For x As Integer = 0 To 8
pb(x).Dispose()
Next
End If
activeControl = newCtrl
For x As Integer = 0 To _boundControls.Count - 1
If _boundControls(x).mControl Is activeControl Then
activeControlParent = _boundControls(x).mParent
Exit For
End If
Next
drawBoundingRectangle()
addDragHandles()
End Sub
#End Region
#Region "     set activeControl bounding rectangle"
Private Sub drawBoundingRectangle()
If activeControl IsNot Nothing Then
Dim r As Rectangle = activeControl.Bounds
r.Inflate(1, 1)
boundingRectangle = r
activeControlParent.Invalidate()
End If
End Sub
#End Region
#Region " Functions and Constants "
<DllImport("user32.dll")> _
Public Shared Function ReleaseCapture() As Boolean
End Function
<DllImport("user32.dll")> _
Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function
Public Declare Function GetCapture Lib "user32" Alias "GetCapture" () As Integer
Private Const WM_NCLBUTTONDOWN As Integer = &HA1
Private Const HTBORDER As Integer = 18
Private Const HTBOTTOM As Integer = 15
Private Const HTBOTTOMLEFT As Integer = 16
Private Const HTBOTTOMRIGHT As Integer = 17
Private Const HTCAPTION As Integer = 2
Private Const HTLEFT As Integer = 10
Private Const HTRIGHT As Integer = 11
Private Const HTTOP As Integer = 12
Private Const HTTOPLEFT As Integer = 13
Private Const HTTOPRIGHT As Integer = 14
#End Region
End Class
#End Region

是如何实现的

Dim worker As New controlHandler
Dim textBoxBoundControl As New controlHandler.boundControl(Panel2, DragAndDropGroupBox)
worker.setWidthHeightBoxes(nameWidth, nameHeight, dpiX, dpiY, textBoxBoundControl)
Dim TextSizeChangeHandler As New TextSizeChangeHandler(labelSizeWidth, labelSizeHeight, DragAndDropGroupBox, dpiX, dpiY)
worker.boundControls.Add(textBoxBoundControl)
worker.bindControls()

编辑:问题似乎出在分组框上。我只是试着自己放一个图片盒,它拖放得很好。然而,我仍然无法拖放组框,即使它唯一的父级是选项卡页。当picturebox是groupbox的子项时,picturebox 会出现问题

编辑2:有图像源的图片框似乎有问题。我刚试过用一个空白的画框,它成功了。

将背景颜色从透明更改为白色或其他颜色似乎可以解决此问题。这看起来更像是一个"黑客",但目前,我将使用它,直到出现更好的解决方案。

最新更新