Public Class ControlSizer
Private Const SizeGripSize = 8I
'These hold the protected methods 'OnPaint' and 'OnBackgroundPaint' of _Control
Private _PaintMethod As System.Reflection.MethodInfo
Private _PaintBackgroundMethod As System.Reflection.MethodInfo
'This is where the protected methods 'OnPaint' and 'OnBackgroundPaint' of _Control are called
Protected Overrides Sub OnPaint(ByVal pe As System.Windows.Forms.PaintEventArgs)
'everything is doublebuffered for speed now
Dim MyRect = New Rectangle(Point.Empty, Me.Size)
'Paint _Control into a buffer
Dim ControlBuffer As New Bitmap(Me.Width - (SizeGripSize * 2), Me.Height - (SizeGripSize * 2), Imaging.PixelFormat.Format32bppArgb)
If _Control IsNot Nothing Then
Using ControlBufferGraphics As Graphics = Graphics.FromImage(ControlBuffer)
Dim args As Object() = {New PaintEventArgs(ControlBufferGraphics, New Rectangle(Point.Empty, _Control.Size))}
_PaintBackgroundMethod.Invoke(_Control, args)
_PaintMethod.Invoke(_Control, args)
End Using 'ControlGraphics
End If
'Paint the size grips, selection, and border into a buffer
Dim SizeGripBuffer As New Bitmap(Me.Width, Me.Height, Imaging.PixelFormat.Format32bppArgb)
Using SizeGripBufferGraphics As Graphics = Graphics.FromImage(SizeGripBuffer)
'todo: draw size grips
'right now, we'll just draw a transparent selection box
Using SelectionBrush As New SolidBrush(Color.FromArgb(128, SystemColors.Highlight))
SizeGripBufferGraphics.FillRectangle(SelectionBrush, MyRect)
End Using
ControlPaint.DrawSelectionFrame(SizeGripBufferGraphics, True, MyRect, Rectangle.Inflate(MyRect, -2, -2), SystemColors.Highlight)
End Using
'Paint any owner draw stuff into a buffer
Dim OwnerDrawBuffer As New Bitmap(Me.Width, Me.Height, Imaging.PixelFormat.Format32bppArgb)
Using OwnerDrawBufferGraphics As Graphics = Graphics.FromImage(OwnerDrawBuffer)
MyBase.OnPaint(New PaintEventArgs(OwnerDrawBufferGraphics, MyRect))
End Using
'Paint all the buffers to the control
pe.Graphics.DrawImage(ControlBuffer, New Point(SizeGripSize, SizeGripSize))
pe.Graphics.DrawImage(SizeGripBuffer, Point.Empty)
pe.Graphics.DrawImage(OwnerDrawBuffer, Point.Empty)
'Dispose all the buffers
ControlBuffer.Dispose()
SizeGripBuffer.Dispose()
OwnerDrawBuffer.Dispose()
End Sub
'This is where _PaintMethod and _PaintBackgroundMethod are set
Public Property Control() As Control
Get
Return _Control
End Get
Set(ByVal value As Control)
If value Is Me Then
Throw New CircularReferenceException
Else
_Control = value
RefreshSize(True)
If _Control IsNot Nothing Then
_PaintBackgroundMethod = _Control.GetType.GetMethod("OnPaintBackground", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.FlattenHierarchy)
_PaintMethod = _Control.GetType.GetMethod("OnPaint", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.FlattenHierarchy)
End If
End If
End Set
End Property
Private _Control As Control
'Adjusts the size of this control or _Control as needed. Also forces redraw
Public Sub RefreshSize(ByVal SizeToControl As Boolean)
If _Control IsNot Nothing Then
If SizeToControl Then
Me.Bounds = Rectangle.Inflate(_Control.Bounds, SizeGripSize, SizeGripSize)
Me.BringToFront()
Else
_Control.Bounds = Rectangle.Inflate(Me.Bounds, -(SizeGripSize), -(SizeGripSize))
End If
Me.Invalidate()
End If
End Sub
Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
MyBase.OnSizeChanged(e)
RefreshSize(False)
End Sub
Protected Overrides Sub OnLocationChanged(ByVal e As System.EventArgs)
MyBase.OnLocationChanged(e)
RefreshSize(False)
End Sub
End Class
Public NotInheritable Class CircularReferenceException
Inherits ApplicationException
Sub New()
MyBase.New("An attempt has been made to create a reference that is circular (for example, attaching a Resizer control to itself).")
End Sub
End Class