November 1, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Create a Shaped 3D Control with GDI+

  • September 29, 2004
  • By Paul Kimmel
  • Send Email »
  • More Articles »

Adding the Control to the Toolbar

After you have compiled the class library containing the control, add it to the Toolbar in VS.NET. You can optionally add a new toolbar tab by selecting the Toolbox (View|Toolbox) and selecting Add Tab from the context menu (right-click over the Toolbox to display the context menu). I added a tab named Controls. To add the custom control, select the new (or an existing) tab, again displaying the toolbox context menu. This time, select Add/Remove Items from the context menu, displaying the Customize Toolbox dialog. On the .NET Framework Components tab, click Browse and navigate to the class library assembly containing the 3D Cube control.

Figure 4 shows the design-time view of the cube with the background color changed to blue.



Click here for a larger image.

Figure 4: The control shown in the toolbox and painted on a form at design time

Testing the Control

The final step is to drag and drop the control from the toolbox onto a form or user control. To test that the bounding region is limited to the cube shape, add a Click event handler. The event should fire only when you click within the boundaries of the control, as opposed to the rectangular boundary shown when the control is selected at design time.

Before you send me some e-mail about errors in the code, albeit minor ones, I'm warning you now: The control code contains errors. The cube bound and control boundary should be synonymous. This implies that setting the bounds of the cube and the control are identical. Additionally, adjusting the center of the cube should reposition the control. Currently, changing properties such as the CubeCenter makes the cube appear offset from the control, and the control does not resize or snap-to-fit automatically at design time. Another flaw is that the depth value is zero by default, so the cube looks like a rectangle when it is first dropped on a form. If you play with the RotateX and RotateY properties of the underlying cube, you will also notice that the cube does not render correctly in some configurations. These tweaks were intentionally left in place for you to play with if you'd like.

Hint: A minimalist approach to improving design flaws would lead one to remove all of the cube properties and accomplish everything through the outer control, specifically the resize event. A maximalist approach would include adding a Z or depth property, surfacing rotation properties, and incorporating the Z or Depth property into a three-dimensional size property. The latter would require a custom property editor for a three-dimensional size and the ScaleCube method would need to be modified to encompass the rotation factors.

The two remaining sections contain the complete code listing for the 3D Cube control and the 3D Cube structure, respectively. While I encourage you to review the previous VB Today column, I know you're busy so I included the complete listing here.

Control Code Listing

Listing 7 is the complete listing for the 3D Cube control.

Listing 7: The complete Listing for the 3D Cube Control

Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Data
Imports System.Windows.Forms

<ToolboxBitmap("Cube3d.bmp")> _
Public Class Cube3d
   Inherits System.Windows.Forms.Control

#Region " Component Designer generated code "

   Public Sub New(ByVal Container _
                  As System.ComponentModel.IContainer)
      MyClass.New()

      'Required for Windows.Forms Class Composition Designer
      'support
      Container.Add(Me)
   End Sub

   Public Sub New()
      MyBase.New()

      SetStyle(ControlStyles.SupportsTransparentBackColor Or _
               ControlStyles.ResizeRedraw, True)

      InitializeComponent()

      FCube = New Cube(CubeX, CubeY, CubeHeight, CubeWidth, 
      CubeDepth)

   End Sub

   'Component overrides dispose to clean up the component list.
   Protected Overloads Overrides Sub Dispose( _
   ByVal disposing As Boolean)
      If disposing Then
         If Not (components Is Nothing) Then
            components.Dispose()
         End If
      End If
      MyBase.Dispose(disposing)
   End Sub

   'Required by the Component Designer
   Private components As System.ComponentModel.IContainer

   'NOTE: The following procedure is required by the
   'Component Designer
   'It can be modified using the Component Designer.
   'Do not modify it using the code editor.
   <System.Diagnostics.DebuggerStepThrough()> _
   Private Sub InitializeComponent()
        components = New System.ComponentModel.Container
   End Sub

#End Region

   Private FPen As Pen = New Pen(Color.Black)
   Private FCube As Cube

   Protected Overrides Sub OnPaint( _
   ByVal e As System.Windows.Forms.PaintEventArgs)
      MyBase.OnPaint(e)
      Dim path As GraphicsPath = FCube.GetCube()
      e.Graphics.DrawPath(FPen, path)
      Me.Region = EnclosingRegion()
   End Sub

   Public Function EnclosingRegion() As Region
      Dim copy As Cube3D = Clone()
      copy.ScaleCube(1, 1, 1)
      Dim path As GraphicsPath = copy.Cube.GetCube()
      path.FillMode = FillMode.Winding
      Return New Region(path)
   End Function

   Public Function Clone() As Cube3d
      Dim copy As Cube3D = New Cube3d
      copy.SetCubeBounds(CubeX, CubeY, CubeWidth, CubeHeight, 
      CubeDepth)
      Return copy
   End Function

   Public Sub ScaleCube(ByVal x As Integer, ByVal y As Integer, 
   ByVal z As Integer)
      CubeLocation = New Point(CubeX - x, CubeY - y)
      CubeWidth += 2 * x
      CubeHeight += 2 * y
      CubeDepth += 2 * z
   End Sub

   Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
      MyBase.OnResize(e)
      ResizeCubeStructure()
   End Sub

   Public Sub SetCubeBounds(ByVal x As Integer, _
      ByVal y As Integer, _
      ByVal width As Integer, ByVal height As Integer, _
      ByVal depth As Integer)
      FCube.Location = New Point(x, y)
      FCube.Width = width
      FCube.Height = height
      FCube.Depth = depth
      Invalidate()
   End Sub

   Private Sub ResizeCubeStructure()
      FCube.FillRectangle(Bounds)
      Invalidate()
   End Sub


   Public Property CubeWidth() As Integer
      Get
         Return FCube.Width
      End Get
      Set(ByVal Value As Integer)
         FCube.Width = Value
         Invalidate()
      End Set
   End Property
   Public Property CubeHeight() As Integer
      Get
         Return FCube.Height
      End Get
      Set(ByVal Value As Integer)
         FCube.Height = Value
         Invalidate()
      End Set
   End Property
   Public Property CubeDepth() As Integer
      Get
         Return FCube.Depth
      End Get
      Set(ByVal Value As Integer)
         FCube.Depth = Value
         Invalidate()
      End Set
   End Property
   Public Property CubeCenter() As Point
      Get
         Return FCube.Center
      End Get
      Set(ByVal Value As Point)
         FCube.Center = Value
         Invalidate()
      End Set
   End Property
   Public Property CubeLocation() As Point
      Get
         Return FCube.Location
      End Get
      Set(ByVal Value As Point)
         FCube.Location = Value
         Invalidate()
      End Set
   End Property

   <Browsable(False)> _
   Public Property CubeSize() As CubeSize
      Get
         Return FCube.Size
      End Get
      Set(ByVal Value As CubeSize)
         FCube.Size = Value
         Invalidate()
      End Set
   End Property
   <Browsable(False)> _
   Public ReadOnly Property CubeX() As Integer
      Get
         Return FCube.X
      End Get
   End Property
   <Browsable(False)> _
   Public ReadOnly Property CubeY() As Integer
      Get
         Return FCube.Y
      End Get
   End Property
   <Browsable(False)> _
      Public Property CubePen() As Pen
      Get
         Return FPen
      End Get
      Set(ByVal Value As Pen)
         FPen = Value
      End Set
   End Property
   <Browsable(False)> _
   Public ReadOnly Property Cube() As Cube
      Get
         Return FCube
      End Get
   End Property

End Class




Page 4 of 6



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel