本帖最后由 pmq 于 2025-11-2 20:39 编辑
  1. [hide]Imports Autodesk.AutoCAD.Runtime
  2. Imports Autodesk.AutoCAD.ApplicationServices
  3. Imports Autodesk.AutoCAD.EditorInput

  4. Imports Autodesk.AutoCAD.Geometry
  5. Imports System.Drawing
  6. Imports System.Windows.Forms
  7. Imports System.Threading
  8. Imports System.Drawing.Drawing2D
  9. Imports Font = System.Drawing.Font

  10. Public Class RadialMenuDemo
  11.     Implements IExtensionApplication

  12.     Private Shared pendingAction As Action = Nothing
  13.     Private Shared targetCadPoint As Point3d = Point3d.Origin
  14.     Private Shared radialForm As RadialSectorMenuForm = Nothing

  15.     Public Sub Initialize() Implements IExtensionApplication.Initialize
  16.     End Sub

  17.     Public Sub Terminate() Implements IExtensionApplication.Terminate
  18.         If radialForm IsNot Nothing AndAlso Not radialForm.IsDisposed Then
  19.             If radialForm.InvokeRequired Then
  20.                 radialForm.Invoke(New Action(Sub() radialForm.Close()))
  21.             Else
  22.                 radialForm.Close()
  23.             End If
  24.             radialForm = Nothing
  25.         End If
  26.     End Sub

  27.     <CommandMethod("RadialMenu")>
  28.     Public Sub ShowRadialMenuCommand()
  29.         Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
  30.         Dim ed As Editor = doc.Editor

  31.         If radialForm IsNot Nothing AndAlso Not radialForm.IsDisposed Then
  32.             If radialForm.InvokeRequired Then
  33.                 radialForm.Invoke(New Action(Sub() radialForm.Close()))
  34.             Else
  35.                 radialForm.Close()
  36.             End If
  37.             radialForm = Nothing
  38.         End If

  39.         Dim ppr As PromptPointResult = ed.GetPoint(vbLf & "点击弹出可拖动轮盘菜单:" & vbCrLf & " - 拖动内圆移动菜单" & vbCrLf & " - 点击功能扇区执行命令" & vbCrLf & " - 点击内圆/外圆外关闭菜单")
  40.         If ppr.Status <> PromptStatus.OK Then
  41.             ed.WriteMessage(vbLf & "命令已取消。")
  42.             Return
  43.         End If
  44.         targetCadPoint = ppr.Value
  45.         Dim screenPoint As System.Drawing.Point = Cursor.Position

  46.         Dim sectors As New List(Of RadialSector) From {
  47.         New RadialSector("展点", Color.FromArgb(255, 80, 160, 220), AddressOf DrawZD),
  48.         New RadialSector("绘制图框", Color.FromArgb(255, 60, 140, 200), AddressOf DrawTK),
  49.         New RadialSector("绘剖面线", Color.FromArgb(255, 40, 120, 180), AddressOf DrawPMX),
  50.         New RadialSector("剖面计算", Color.FromArgb(255, 160, 120, 220), AddressOf DrawPMJS),
  51.         New RadialSector("剖面绘制", Color.FromArgb(255, 140, 100, 200), AddressOf DrawPMHZ),
  52.         New RadialSector("坐标标注", Color.FromArgb(255, 80, 200, 140), AddressOf ZBBZ),
  53.         New RadialSector("自动编号", Color.FromArgb(255, 150, 180, 120), AddressOf AutoBH),
  54.         New RadialSector("高程点内插", Color.FromArgb(255, 240, 140, 80), AddressOf CalcElevationByPoints),
  55.         New RadialSector("文本求和", Color.FromArgb(255, 223, 127, 60), AddressOf TextSummation),
  56.         New RadialSector("范围线", Color.FromArgb(255, 80, 220, 200), AddressOf AutoAlphaBoundary),
  57.         New RadialSector("生成坐标", Color.FromArgb(255, 60, 200, 180), AddressOf ZDfile),
  58.         New RadialSector("范围缩放", Color.FromArgb(255, 240, 200, 80), AddressOf OpenAll),
  59.         New RadialSector("打开所有", Color.FromArgb(255, 230, 191, 127), AddressOf DQtc),
  60.         New RadialSector("显示当前", Color.FromArgb(255, 220, 180, 40), AddressOf ZooE),
  61.         New RadialSector("关闭菜单", Color.FromArgb(255, 160, 160, 160), AddressOf CloseMenu)
  62.     }

  63.         Dim thread As New Thread(Sub() ShowNonModalDraggableForm(sectors, screenPoint)) With {.IsBackground = True}
  64.         thread.SetApartmentState(ApartmentState.STA)
  65.         thread.Start()
  66.     End Sub

  67.     Private Sub CloseMenu()
  68.         Dim docLock As DocumentLock = Core.Application.DocumentManager.MdiActiveDocument.LockDocument
  69.         If radialForm IsNot Nothing AndAlso Not radialForm.IsDisposed Then
  70.             If radialForm.InvokeRequired Then
  71.                 radialForm.Invoke(New Action(Sub() radialForm.Close()))
  72.             Else
  73.                 radialForm.Close()
  74.             End If
  75.         End If
  76.         docLock.Dispose()
  77.     End Sub


  78.     Private Sub DrawZD()
  79.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus()

  80.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  81.         acDoc.SendStringToExecute("_ZD ", True, False, False)

  82.     End Sub

  83.     Private Sub DrawTK()
  84.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus()

  85.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  86.         acDoc.SendStringToExecute("_Rec ", True, False, False)

  87.     End Sub

  88.     Private Sub DrawPMX()
  89.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus()

  90.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  91.         acDoc.SendStringToExecute("_point ", True, False, False)

  92.     End Sub

  93.     Private Sub DrawPMJS()
  94.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus()

  95.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  96.         acDoc.SendStringToExecute("_point ", True, False, False)

  97.     End Sub

  98.     Private Sub DrawPMHZ()
  99.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus()

  100.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  101.         acDoc.SendStringToExecute("_point ", True, False, False)

  102.     End Sub

  103.     '坐标标注
  104.     Private Sub ZBBZ()
  105.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus()

  106.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  107.         acDoc.SendStringToExecute("_ZBBZ ", True, False, False)

  108.     End Sub

  109.     '自动编号
  110.     Private Sub AutoBH()
  111.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus()

  112.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  113.         acDoc.SendStringToExecute("_AutoBH ", True, False, False)

  114.     End Sub

  115.     '高程点内插
  116.     Private Sub CalcElevationByPoints()
  117.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus() ' CAD获得焦点

  118.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  119.         acDoc.SendStringToExecute("_CalcElevationByPoints ", True, False, False)

  120.     End Sub

  121.     '范围线
  122.     Private Sub AutoAlphaBoundary()
  123.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus() ' CAD获得焦点

  124.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  125.         acDoc.SendStringToExecute("_AutoAlphaBoundary ", True, False, False)

  126.     End Sub

  127.     '文本求和 求平均值
  128.     Private Sub TextSummation()
  129.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus() ' CAD获得焦点

  130.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  131.         acDoc.SendStringToExecute("_TextSummation ", True, False, False)

  132.     End Sub

  133.     '生成三维坐标文件
  134.     Private Sub ZDfile()
  135.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  136.         Dim ffName As New Zd_XyhFiles
  137.         ffName.Show()
  138.     End Sub

  139.     '打开所有
  140.     Private Sub OpenAll()

  141.     End Sub

  142.     '只显示当前层
  143.     Private Sub DQtc()
  144.         DQtc()

  145.     End Sub

  146.     ' 范围缩放
  147.     Private Sub ZooE()
  148.         Core.Application.DocumentManager.MdiActiveDocument.Window.Focus() ' CAD获得焦点
  149.         Dim acDoc As Document = Core.Application.DocumentManager.MdiActiveDocument
  150.         acDoc.SendStringToExecute("_Zoom E ", True, False, False)
  151.     End Sub



  152.     '===============================================================================================

  153.     Private Sub ShowNonModalDraggableForm(sectors As List(Of RadialSector), screenPos As System.Drawing.Point)
  154.         Try
  155.             System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(False)
  156.             radialForm = New RadialSectorMenuForm(sectors) With {
  157.                 .StartPosition = FormStartPosition.Manual
  158.             }
  159.             radialForm.Location = New System.Drawing.Point(
  160.                 screenPos.X - radialForm.Width \ 2,
  161.                 screenPos.Y - radialForm.Height \ 2
  162.             )

  163.             ' 绑定窗体事件(仅保留ActionTriggered,简化事件机制)
  164.             AddHandler radialForm.FormClosed, AddressOf RadialForm_Closed
  165.             AddHandler radialForm.ActionTriggered, AddressOf OnActionTriggered

  166.             radialForm.Show()
  167.             System.Windows.Forms.Application.Run()
  168.         Catch ex As Exception
  169.             System.Windows.Forms.MessageBox.Show(
  170.                 $"菜单加载错误:{ex.Message}", "错误提示",
  171.                 System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error
  172.             )
  173.         End Try
  174.     End Sub

  175.     Private Sub RadialForm_Closed(sender As Object, e As FormClosedEventArgs)
  176.         radialForm = Nothing
  177.         System.Windows.Forms.Application.ExitThread()
  178.     End Sub

  179.     Private Sub OnActionTriggered(action As Action)
  180.         If action Is Nothing Then Return
  181.         pendingAction = action
  182.         AddHandler Autodesk.AutoCAD.ApplicationServices.Application.Idle, AddressOf ExecuteActionOnCADMainThread
  183.     End Sub

  184.     Private Sub ExecuteActionOnCADMainThread(sender As Object, e As EventArgs)
  185.         RemoveHandler Autodesk.AutoCAD.ApplicationServices.Application.Idle, AddressOf ExecuteActionOnCADMainThread

  186.         If pendingAction IsNot Nothing Then
  187.             pendingAction.Invoke()
  188.             pendingAction = Nothing
  189.         End If
  190.     End Sub

  191.     ' ----------------------  ----------------------
  192.     Friend Class RadialSector
  193.         Public Property Text As String
  194.         Public Property FillColor As Color
  195.         Public Property Action As Action
  196.         Public Sub New(text As String, fillColor As Color, action As Action)
  197.             Me.Text = text
  198.             Me.FillColor = fillColor
  199.             Me.Action = action
  200.         End Sub
  201.     End Class

  202.     ' ----------------------  ----------------------
  203.     Friend Class RadialSectorMenuForm
  204.         Inherits Form

  205.         Public Event ActionTriggered(action As Action)

  206.         Private isDragging As Boolean = False
  207.         Private dragStartMousePos As Point
  208.         Private dragStartFormPos As Point

  209.         Private ReadOnly sectors As List(Of RadialSector)
  210.         Private ReadOnly radiusOuter As Integer = 140
  211.         Private ReadOnly radiusInner As Integer = 40
  212.         Private ReadOnly menuFont As Font

  213.         Public Sub New(sectors As List(Of RadialSector))
  214.             Me.sectors = sectors
  215.             FormBorderStyle = FormBorderStyle.None
  216.             ShowInTaskbar = False
  217.             TopMost = True
  218.             BackColor = Color.Magenta
  219.             TransparencyKey = Color.Magenta
  220.             DoubleBuffered = True
  221.             Size = New Size(radiusOuter * 2, radiusOuter * 2)
  222.             menuFont = New Font("宋体", 10, FontStyle.Bold)


  223.             AddHandler MouseDown, AddressOf Form_MouseDown
  224.             AddHandler MouseMove, AddressOf Form_MouseMove
  225.             AddHandler MouseUp, AddressOf Form_MouseUp
  226.             AddHandler MouseClick, AddressOf Form_MouseClick
  227.             AddHandler Paint, AddressOf Form_Paint
  228.         End Sub


  229.         Private Sub Form_MouseDown(sender As Object, e As MouseEventArgs)
  230.             If e.Button <> MouseButtons.Left Then Return

  231.             Dim formCenter As New System.Drawing.Point(Width \ 2, Height \ 2)
  232.             Dim mouseOffsetX As Integer = e.X - formCenter.X
  233.             Dim mouseOffsetY As Integer = e.Y - formCenter.Y
  234.             Dim distanceToCenter As Double = Math.Sqrt(mouseOffsetX ^ 2 + mouseOffsetY ^ 2)

  235.             If distanceToCenter <= radiusInner Then
  236.                 isDragging = True
  237.                 dragStartMousePos = Cursor.Position
  238.                 dragStartFormPos = Me.Location
  239.                 Cursor = Cursors.Hand
  240.             End If
  241.         End Sub


  242.         Private Sub Form_MouseMove(sender As Object, e As MouseEventArgs)
  243.             If Not isDragging Then Return

  244.             Dim offsetX As Integer = Cursor.Position.X - dragStartMousePos.X
  245.             Dim offsetY As Integer = Cursor.Position.Y - dragStartMousePos.Y

  246.             Dim newFormX As Integer = dragStartFormPos.X + offsetX
  247.             Dim newFormY As Integer = dragStartFormPos.Y + offsetY


  248.             newFormX = Math.Max(0, Math.Min(newFormX, Screen.PrimaryScreen.WorkingArea.Width - Me.Width))
  249.             newFormY = Math.Max(0, Math.Min(newFormY, Screen.PrimaryScreen.WorkingArea.Height - Me.Height))

  250.             Me.Location = New System.Drawing.Point(newFormX, newFormY)
  251.         End Sub


  252.         Private Sub Form_MouseUp(sender As Object, e As MouseEventArgs)
  253.             If e.Button = MouseButtons.Left Then
  254.                 isDragging = False
  255.                 Cursor = Cursors.Default
  256.             End If
  257.         End Sub

  258.         Private Sub Form_MouseClick(sender As Object, e As MouseEventArgs)
  259.             If isDragging Then Return

  260.             Dim formCenter As New System.Drawing.Point(Width \ 2, Height \ 2)
  261.             Dim mouseOffsetX As Integer = e.X - formCenter.X
  262.             Dim mouseOffsetY As Integer = e.Y - formCenter.Y
  263.             Dim distanceToCenter As Double = Math.Sqrt(mouseOffsetX ^ 2 + mouseOffsetY ^ 2)


  264.             Dim clickAngle As Double = Math.Atan2(mouseOffsetY, mouseOffsetX)
  265.             clickAngle += Math.PI / 2
  266.             If clickAngle < 0 Then clickAngle += 2 * Math.PI

  267.             Dim sectorCount As Integer = sectors.Count
  268.             Dim sectorAngleStep As Double = 2 * Math.PI / sectorCount
  269.             Dim targetSectorIndex As Integer = CInt(Math.Floor(clickAngle / sectorAngleStep)) Mod sectorCount
  270.             Dim targetSector As RadialSector = sectors(targetSectorIndex)


  271.             RaiseEvent ActionTriggered(targetSector.Action)
  272.         End Sub


  273.         Private Sub Form_Paint(sender As Object, e As PaintEventArgs)
  274.             Dim g As Graphics = e.Graphics
  275.             g.SmoothingMode = SmoothingMode.AntiAlias
  276.             Dim formCenter As New System.Drawing.Point(Width \ 2, Height \ 2)
  277.             Dim sectorCount As Integer = sectors.Count
  278.             Dim sectorAngleDeg As Single = 360.0F / sectorCount


  279.             For i As Integer = 0 To sectorCount - 1
  280.                 Dim sector As RadialSector = sectors(i)

  281.                 Using fillBrush As New SolidBrush(sector.FillColor)
  282.                     Using sectorPath As New GraphicsPath()

  283.                         sectorPath.AddPie(
  284.                     formCenter.X - radiusOuter, formCenter.Y - radiusOuter,
  285.                     radiusOuter * 2, radiusOuter * 2,
  286.                     sectorAngleDeg * i,
  287.                     sectorAngleDeg
  288.                 )

  289.                         sectorPath.AddPie(
  290.                     formCenter.X - radiusInner, formCenter.Y - radiusInner,
  291.                     radiusInner * 2, radiusInner * 2,
  292.                     sectorAngleDeg * i,
  293.                     sectorAngleDeg
  294.                 )
  295.                         sectorPath.FillMode = FillMode.Alternate
  296.                         g.FillPath(fillBrush, sectorPath)
  297.                     End Using
  298.                 End Using


  299.                 Dim sectorRadialAngleDeg As Single = sectorAngleDeg * i + sectorAngleDeg / 2
  300.                 Dim sectorRadialAngleRad As Double = sectorRadialAngleDeg * Math.PI / 180.0
  301.                 Dim textDistanceFromCenter As Integer = radiusInner + (radiusOuter - radiusInner) / 2
  302.                 Dim textSize As SizeF = g.MeasureString(sector.Text, menuFont)

  303.                 Dim textCenterX As Integer = CInt(formCenter.X + textDistanceFromCenter * Math.Cos(sectorRadialAngleRad))
  304.                 Dim textCenterY As Integer = CInt(formCenter.Y + textDistanceFromCenter * Math.Sin(sectorRadialAngleRad))

  305.                 Dim textRotateAngle As Single = If(textCenterX < formCenter.X,
  306.                                           sectorRadialAngleDeg + 180.0F,
  307.                                           sectorRadialAngleDeg)

  308.                 Using textBrush As New SolidBrush(Color.Black)
  309.                     Dim gState As GraphicsState = g.Save()

  310.                     g.TranslateTransform(textCenterX, textCenterY)
  311.                     g.RotateTransform(textRotateAngle)
  312.                     g.DrawString(
  313.                 sector.Text,
  314.                 menuFont,
  315.                 textBrush,
  316.                 -textSize.Width \ 2,
  317.                 -textSize.Height \ 2
  318.             )

  319.                     g.Restore(gState)
  320.                 End Using
  321.             Next

  322.             Using innerCircleWhiteBrush As New SolidBrush(Color.White)
  323.                 g.FillEllipse(
  324.             innerCircleWhiteBrush,
  325.             formCenter.X - radiusInner, formCenter.Y - radiusInner,
  326.             radiusInner * 2, radiusInner * 2
  327.         )
  328.             End Using

  329.             Using innerCirclePen As New Pen(Color.Red, 2) With {.DashStyle = DashStyle.Dash}
  330.                 g.DrawEllipse(
  331.             innerCirclePen,
  332.             formCenter.X - radiusInner, formCenter.Y - radiusInner,
  333.             radiusInner * 2, radiusInner * 2
  334.         )
  335.                 Dim dragTextSize As SizeF = g.MeasureString("拖动", menuFont)
  336.                 g.DrawString(
  337.             "拖动",
  338.             menuFont,
  339.             Brushes.Black,
  340.             formCenter.X - dragTextSize.Width \ 2,
  341.             formCenter.Y - dragTextSize.Height \ 2
  342.         )
  343.             End Using

  344.             Using outerCirclePen As New Pen(Color.Black, 2)
  345.                 g.DrawEllipse(
  346.             outerCirclePen,
  347.             formCenter.X - radiusOuter, formCenter.Y - radiusOuter,
  348.             radiusOuter * 2, radiusOuter * 2
  349.         )
  350.             End Using
  351.         End Sub

  352.         Protected Overrides Sub Dispose(disposing As Boolean)
  353.             If disposing Then
  354.                 If menuFont IsNot Nothing Then menuFont.Dispose()
  355.                 RemoveHandler MouseDown, AddressOf Form_MouseDown
  356.                 RemoveHandler MouseMove, AddressOf Form_MouseMove
  357.                 RemoveHandler MouseUp, AddressOf Form_MouseUp
  358.                 RemoveHandler MouseClick, AddressOf Form_MouseClick
  359.                 RemoveHandler Paint, AddressOf Form_Paint
  360.             End If
  361.             MyBase.Dispose(disposing)
  362.         End Sub

  363.         Private Sub CloseMenu()
  364.             Me.Close()
  365.         End Sub
  366.     End Class
  367. End Class[/hide]




网友答:
qifeifei 发表于 2025-11-2 13:33
太强大了 直接发布源码

测试过了没有?看下兼容哪些版本?   


网友答:
pengbin 发表于 2025-11-2 13:47
测试过了没有?看下兼容哪些版本?

没有啊 不打算弄这个 我用不上.

网友答: 太强大了 直接发布源码

网友答: 必须顶一下,这个好。

网友答: 强呀。如何使用呀?


网友答: 功能很强大,先收藏

网友答: 提供源码的,必需顶上

网友答: 营销没有别人厉害呀
  • 上一篇:變更圖元的屬性
  • 下一篇:没有了