Back to Devexpress

How to: Create a Custom Shapes Panel

windowsforms-401746-controls-and-libraries-diagrams-examples-how-to-create-a-custom-shapes-panel.md

latest6.7 KB
Original Source

How to: Create a Custom Shapes Panel

  • Mar 26, 2023
  • 3 minutes to read

The DiagramControl provides the DrawDetachedItem method that you can use to draw diagram items outside the Canvas/Shapes Panel. You can use this method to implement a custom shapes panel. This example illustrates how to create a custom toolbox based on the GridControl.

To drag an item when a user clicks a grid row, call the StartDragTool command. To draw a diagram item at a specific position, use the TranslateTransform method.

View Example

csharp
public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        var toolboxItems = new ObservableCollection<DiagramShape>();
        foreach (var shape in BasicShapes.Stencil.Shapes) {
            toolboxItems.Add(new DiagramShape() { Shape = shape });
        }
        gridControl1.DataSource = toolboxItems;
    }
    int shapeTextOffset = 60;
    Point mouseDownLocation;
    GridHitInfo gridHitInfo;
    private void GridView1_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e) {
        DiagramShape shapeItem = gridView1.GetRow(e.RowHandle) as DiagramShape;
        if (shapeItem == null)
            return;
        GraphicsState transState = e.Graphics.Save();
        try {
            e.Appearance.DrawString(e.Cache, e.DisplayText, new Rectangle(e.Bounds.X + shapeTextOffset, e.Bounds.Y, e.Bounds.Width - shapeTextOffset, e.Bounds.Height));
            e.Cache.TranslateTransform(e.Bounds.X, e.Bounds.Y);
            shapeItem.Width = 40;
            shapeItem.Height = e.Bounds.Height;
            diagramControl1.DrawDetachedItem(shapeItem, e.Cache);
            e.Handled = true;
        }
        finally {
            e.Graphics.Restore(transState);
        }
    }
    private void gridControl1_MouseDown(object sender, MouseEventArgs e) {
        gridHitInfo = gridView1.CalcHitInfo(e.Location);
        mouseDownLocation = e.Location;
    }
    private void gridControl1_MouseMove(object sender, MouseEventArgs e) {
        if (e.Button == MouseButtons.Left && CanStartDragDrop(e.Location)) {
            StartDragDrop();
        }
    }
    private void gridControl1_MouseLeave(object sender, EventArgs e) {
        if (gridHitInfo != null)
            gridHitInfo.View.ResetCursor();
        gridHitInfo = null;
    }
    private bool CanStartDragDrop(Point location) {
        return gridHitInfo.InDataRow && (Math.Abs(location.X - mouseDownLocation.X) > 2 || Math.Abs(location.Y - mouseDownLocation.Y) > 2);
    }
    public void StartDragDrop() {
        var draggedItem = (DiagramShape)gridHitInfo.View.GetRow(gridHitInfo.RowHandle);
        var tool = new FactoryItemTool("", () => "", diagram => new DiagramShape(draggedItem.Shape), new System.Windows.Size(150, 100));
        diagramControl1.Commands.Execute(DiagramCommandsBase.StartDragToolCommand, tool, null);
    }
}
vb
Partial Public Class Form1
        Inherits Form

        Public Sub New()
            InitializeComponent()
            Dim toolboxItems = New ObservableCollection(Of DiagramShape)()
            For Each shape In BasicShapes.Stencil.Shapes
                toolboxItems.Add(New DiagramShape() With {.Shape = shape})
            Next shape
            gridControl1.DataSource = toolboxItems
        End Sub
        Private shapeTextOffset As Integer = 60
        Private mouseDownLocation As Point
        Private gridHitInfo As GridHitInfo
        Private Sub GridView1_CustomDrawCell(ByVal sender As Object, ByVal e As DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs) Handles gridView1.CustomDrawCell
            Dim shapeItem As DiagramShape = TryCast(gridView1.GetRow(e.RowHandle), DiagramShape)
            If shapeItem Is Nothing Then
                Return
            End If
            Dim transState As GraphicsState = e.Graphics.Save()
            Try
                e.Appearance.DrawString(e.Cache, e.DisplayText, New Rectangle(e.Bounds.X + shapeTextOffset, e.Bounds.Y, e.Bounds.Width - shapeTextOffset, e.Bounds.Height))
                e.Cache.TranslateTransform(e.Bounds.X, e.Bounds.Y)
                shapeItem.Width = 40
                shapeItem.Height = e.Bounds.Height
                diagramControl1.DrawDetachedItem(shapeItem, e.Cache)
                e.Handled = True
            Finally
                e.Graphics.Restore(transState)
            End Try
        End Sub
        Private Sub gridControl1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles gridControl1.MouseDown
            gridHitInfo = gridView1.CalcHitInfo(e.Location)
            mouseDownLocation = e.Location
        End Sub
        Private Sub gridControl1_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles gridControl1.MouseMove
            If e.Button = MouseButtons.Left AndAlso CanStartDragDrop(e.Location) Then
                StartDragDrop()
            End If
        End Sub
        Private Sub gridControl1_MouseLeave(ByVal sender As Object, ByVal e As EventArgs) Handles gridControl1.MouseLeave
            If gridHitInfo IsNot Nothing Then
                gridHitInfo.View.ResetCursor()
            End If
            gridHitInfo = Nothing
        End Sub
'INSTANT VB NOTE: The variable location was renamed since Visual Basic does not handle local variables named the same as class members well:
        Private Function CanStartDragDrop(ByVal location_Conflict As Point) As Boolean
            Return gridHitInfo.InDataRow AndAlso (Math.Abs(location_Conflict.X - mouseDownLocation.X) > 2 OrElse Math.Abs(location_Conflict.Y - mouseDownLocation.Y) > 2)
        End Function
        Public Sub StartDragDrop()
            Dim draggedItem = CType(gridHitInfo.View.GetRow(gridHitInfo.RowHandle), DiagramShape)
            Dim tool = New FactoryItemTool("", Function() "", Function(diagram) New DiagramShape(draggedItem.Shape), New System.Windows.Size(150, 100))
            diagramControl1.Commands.Execute(DiagramCommandsBase.StartDragToolCommand, tool, Nothing)
        End Sub
    End Class