Browse Source

增加隐藏功能 Ctrl ALt shift 触发

hongwenjun 1 year ago
parent
commit
df10064587
11 changed files with 1376 additions and 1099 deletions
  1. 104 104
      ALGO.bas
  2. 259 259
      API.bas
  3. 39 39
      AverageDistance.bas
  4. 358 358
      Box.bas
  5. 193 0
      Form/Form/LinesForm.frm
  6. BIN
      Form/Form/LinesForm.frx
  7. 84 0
      Form/Form/ThisMacroStorage.cls
  8. 142 142
      MirrorParalleHorizon.bas
  9. 42 42
      RotateMoveDuplicate.bas
  10. 56 56
      Tools.bas
  11. 99 99
      lines.bas

+ 104 - 104
ALGO.bas

@@ -1,104 +1,104 @@
-Attribute VB_Name = "ALGO"
-'// This is free and unencumbered software released into the public domain.
-'// For more information, please refer to  https://github.com/hongwenjun
-
-'// Algorithm 模块
-#If VBA7 Then
-'// For CorelDRAW X6-2023  62bit
-'// Private Declare PtrSafe Function sort_byitem Lib "C:\TSP\lyvba.dll" (ByRef sr_Array As ShapeProperties, ByVal size As Long, _
-'//                       ByVal Sort_By As SortItem, ByRef ret_Array As Long) As Long
-#Else
-'// For CorelDRAW X4  32bit
-Declare Function sort_byitem Lib "C:\TSP\lyvba32.dll" (ByRef sr_Array As ShapeProperties, ByVal size As Long, _
-                      ByVal Sort_By As SortItem, ByRef ret_Array As Long) As Long
-#End If
-
-Type ShapeProperties
-  Item As Long                 '// ShapeRange.Item
-  StaticID As Long             '// Shape.StaticID
-  lx As Double: rx As Double   '// s.LeftX  s.RightX  s.BottomY  s.TopY
-  by As Double: ty As Double
-  cx As Double: cy As Double   '// s.CenterX  s.CenterY s.SizeWidth s.SizeHeight
-  sw As Double: sh As Double
-End Type
-
-Enum SortItem
-  stlx
-  strx
-  stby
-  stty
-  stcx
-  stcy
-  stsw
-  stsh
-  Area
-  topWt_left
-End Enum
-
-Private Sub Test_Sort_ShapeRange()
-  API.BeginOpt
-  Dim sr As ShapeRange, ssr As ShapeRange
-  Dim s As Shape
-  Set sr = ActiveSelectionRange
-  Set ssr = ShapeRange_To_Sort_Array(sr, topWt_left)
-
-  '// s 调整次序
-  For Each s In ssr
-    s.OrderToFront
-  Next s
-
-  MsgBox "ShapeRange_SortItem:" & " " & topWt_left & "  枚举值"
-  API.EndOpt
-End Sub
-
-
-Public Function X4_Sort_ShapeRange(ByRef sr As ShapeRange, ByRef Sort_By As SortItem) As ShapeRange
-  Set X4_Sort_ShapeRange = ShapeRange_To_Sort_Array(sr, Sort_By)
-End Function
-
-'// 映射 ShapeRange 到 Array 然后调用 DLL库排序
-Private Function ShapeRange_To_Sort_Array(ByRef sr As ShapeRange, ByRef Sort_By As SortItem) As ShapeRange
-'  On Error GoTo ErrorHandler
-  Dim sp As ShapeProperties
-  Dim size As Long, ret As Long
-  Dim s As Shape
-  size = sr.Count
-  
-  Dim sr_Array() As ShapeProperties
-  Dim ret_Array() As Long
-  ReDim ret_Array(1 To size)
-  ReDim sr_Array(1 To size)
-  
-  For Each s In sr
-    sp.Item = sr.IndexOf(s)
-    sp.StaticID = s.StaticID
-    sp.lx = s.LeftX: sp.rx = s.RightX
-    sp.by = s.BottomY: sp.ty = s.topY
-    sp.cx = s.CenterX: sp.cy = s.CenterY
-    sp.sw = s.SizeWidth: sp.sh = s.SizeHeight
-    sr_Array(sp.Item) = sp
-  Next s
-
-  '// 在VBA中数组的索引从1开始, 将数组的地址传递给函数需要Arr(1)方式
-  '// C/C++ 函数定义 int __stdcall SortByItem(ShapeProperties* sr_Array, int size, SortItem Sort_By, int* ret_Array)
-  '// sr_Array首地址,size 长度, Sort_By 排序方式, 返回数组 ret_Array
-  ret = sort_byitem(sr_Array(1), size, Sort_By, ret_Array(1))
-  
-  Debug.Print ret, size
-  If ret = size Then
-    Dim srcp As New ShapeRange, i As Integer
-    For i = 1 To size
-      srcp.Add sr(ret_Array(i))
-'     Debug.Print i
-    Next i
-    
-    Set ShapeRange_To_Sort_Array = srcp
-  End If
-  
-ErrorHandler:
-
-End Function
-
-
-
-
+Attribute VB_Name = "ALGO"
+'// This is free and unencumbered software released into the public domain.
+'// For more information, please refer to  https://github.com/hongwenjun
+
+'// Algorithm 模块
+#If VBA7 Then
+'// For CorelDRAW X6-2023  62bit
+'// Private Declare PtrSafe Function sort_byitem Lib "C:\TSP\lyvba.dll" (ByRef sr_Array As ShapeProperties, ByVal size As Long, _
+'//                       ByVal Sort_By As SortItem, ByRef ret_Array As Long) As Long
+#Else
+'// For CorelDRAW X4  32bit
+Declare Function sort_byitem Lib "C:\TSP\lyvba32.dll" (ByRef sr_Array As ShapeProperties, ByVal size As Long, _
+                      ByVal Sort_By As SortItem, ByRef ret_Array As Long) As Long
+#End If
+
+Type ShapeProperties
+  Item As Long                 '// ShapeRange.Item
+  StaticID As Long             '// Shape.StaticID
+  lx As Double: rx As Double   '// s.LeftX  s.RightX  s.BottomY  s.TopY
+  by As Double: ty As Double
+  cx As Double: cy As Double   '// s.CenterX  s.CenterY s.SizeWidth s.SizeHeight
+  sw As Double: sh As Double
+End Type
+
+Enum SortItem
+  stlx
+  strx
+  stby
+  stty
+  stcx
+  stcy
+  stsw
+  stsh
+  Area
+  topWt_left
+End Enum
+
+Private Sub Test_Sort_ShapeRange()
+  API.BeginOpt
+  Dim sr As ShapeRange, ssr As ShapeRange
+  Dim s As Shape
+  Set sr = ActiveSelectionRange
+  Set ssr = ShapeRange_To_Sort_Array(sr, topWt_left)
+
+  '// s 调整次序
+  For Each s In ssr
+    s.OrderToFront
+  Next s
+
+  MsgBox "ShapeRange_SortItem:" & " " & topWt_left & "  枚举值"
+  API.EndOpt
+End Sub
+
+
+Public Function X4_Sort_ShapeRange(ByRef sr As ShapeRange, ByRef Sort_By As SortItem) As ShapeRange
+  Set X4_Sort_ShapeRange = ShapeRange_To_Sort_Array(sr, Sort_By)
+End Function
+
+'// 映射 ShapeRange 到 Array 然后调用 DLL库排序
+Private Function ShapeRange_To_Sort_Array(ByRef sr As ShapeRange, ByRef Sort_By As SortItem) As ShapeRange
+'  On Error GoTo ErrorHandler
+  Dim sp As ShapeProperties
+  Dim size As Long, ret As Long
+  Dim s As Shape
+  size = sr.Count
+  
+  Dim sr_Array() As ShapeProperties
+  Dim ret_Array() As Long
+  ReDim ret_Array(1 To size)
+  ReDim sr_Array(1 To size)
+  
+  For Each s In sr
+    sp.Item = sr.IndexOf(s)
+    sp.StaticID = s.StaticID
+    sp.lx = s.LeftX: sp.rx = s.RightX
+    sp.by = s.BottomY: sp.ty = s.topY
+    sp.cx = s.CenterX: sp.cy = s.CenterY
+    sp.sw = s.SizeWidth: sp.sh = s.SizeHeight
+    sr_Array(sp.Item) = sp
+  Next s
+
+  '// 在VBA中数组的索引从1开始, 将数组的地址传递给函数需要Arr(1)方式
+  '// C/C++ 函数定义 int __stdcall SortByItem(ShapeProperties* sr_Array, int size, SortItem Sort_By, int* ret_Array)
+  '// sr_Array首地址,size 长度, Sort_By 排序方式, 返回数组 ret_Array
+  ret = sort_byitem(sr_Array(1), size, Sort_By, ret_Array(1))
+  
+  Debug.Print ret, size
+  If ret = size Then
+    Dim srcp As New ShapeRange, i As Integer
+    For i = 1 To size
+      srcp.Add sr(ret_Array(i))
+'     Debug.Print i
+    Next i
+    
+    Set ShapeRange_To_Sort_Array = srcp
+  End If
+  
+ErrorHandler:
+
+End Function
+
+
+
+

+ 259 - 259
API.bas

@@ -1,259 +1,259 @@
-Attribute VB_Name = "API"
-'// This is free and unencumbered software released into the public domain.
-'// For more information, please refer to  https://github.com/hongwenjun
-
-'// CorelDRAW 窗口刷新优化和关闭
-Public Function BeginOpt(Optional ByVal name As String = "Undo")
-  EventsEnabled = False
-  ActiveDocument.BeginCommandGroup name
-' ActiveDocument.SaveSettings
-  ActiveDocument.Unit = cdrMillimeter
-  Optimization = True
-' ActiveDocument.PreserveSelection = False
-End Function
-
-Public Function EndOpt()
-' ActiveDocument.PreserveSelection = True
-' ActiveDocument.RestoreSettings
-  EventsEnabled = True
-  Optimization = False
-  EventsEnabled = True
-  ActiveDocument.ReferencePoint = cdrBottomLeft
-  Application.Refresh
-  ActiveDocument.EndCommandGroup
-End Function
-
-Public Function Speak_Msg(message As String)
-  Speak_Help = Val(GetSetting("LYVBA", "Settings", "SpeakHelp", "0"))     '// 关停语音功能
-  
-  If Val(Speak_Help) = 1 Then
-    Dim sapi
-    Set sapi = CreateObject("sapi.spvoice")
-    sapi.Speak message
-  Else
-    ' 不说话
-  End If
-
-End Function
-
-Public Function GetSet(s As String)
-  Bleed = Val(GetSetting("LYVBA", "Settings", "Bleed", "2.0"))
-  Line_len = Val(GetSetting("LYVBA", "Settings", "Line_len", "3.0"))
-  Outline_Width = Val(GetSetting("LYVBA", "Settings", "Outline_Width", "0.2"))
-' Debug.Print Bleed, Line_len, Outline_Width
-
-  If s = "Bleed" Then
-    GetSet = Bleed
-  ElseIf s = "Line_len" Then
-    GetSet = Line_len
-  ElseIf s = "Outline_Width" Then
-    GetSet = Outline_Width
-  End If
-  
-End Function
-
-Public Function Create_Tolerance() As Double
-  Dim text As String
-  If GlobalUserData.Exists("Tolerance", 1) Then
-    text = GlobalUserData("Tolerance", 1)
-  End If
-  text = InputBox("请输入容差值 0.1 --> 9.9", "容差值(mm)", text)
-  If text = "" Then Exit Function
-  GlobalUserData("Tolerance", 1) = text
-  Create_Tolerance = Val(text)
-End Function
-
-Public Function Set_Space_Width(Optional ByVal OnlyRead As Boolean = False) As Double
-  Dim text As String
-  If GlobalUserData.Exists("SpaceWidth", 1) Then
-    text = GlobalUserData("SpaceWidth", 1)
-    If OnlyRead Then
-      Set_Space_Width = Val(text)
-      Exit Function
-    End If
-  End If
-  text = InputBox("请输入间隔宽度值 -99 --> 99", "设置间隔宽度(mm)", text)
-  If text = "" Then Exit Function
-  GlobalUserData("SpaceWidth", 1) = text
-  Set_Space_Width = Val(text)
-End Function
-
-'// 获得剪贴板文本字符
-Public Function GetClipBoardString() As String
-  On Error Resume Next
-  Dim MyData As New DataObject
-  GetClipBoardString = ""
-  MyData.GetFromClipboard
-  GetClipBoardString = MyData.GetText
-  Set MyData = Nothing
-End Function
-
-'// 文本字符复制到剪贴板
-Public Function WriteClipBoard(ByVal s As String)
-  On Error Resume Next
-
-' VBA_WIN10(vba7) 使用PutInClipboard乱码解决办法
-#If VBA7 Then
-  With CreateObject("Forms.TextBox.1")
-    .MultiLine = True
-    .text = s
-    .SelStart = 0
-    .SelLength = .TextLength
-    .Copy
-  End With
-#Else
-  Dim MyData As New DataObject
-  MyData.SetText s
-  MyData.PutInClipboard
-#End If
-End Function
-
-'// 换行转空格 多个空格换成一个空格
-Public Function Newline_to_Space(ByVal str As String) As String
-  str = VBA.Replace(str, Chr(13), " ")
-  str = VBA.Replace(str, Chr(9), " ")
-  Do While InStr(str, "  ")
-      str = VBA.Replace(str, "  ", " ")
-  Loop
-  Newline_to_Space = str
-End Function
-
-'// 获得数组元素个数
-Public Function arrlen(src As Variant) As Integer
-  On Error Resume Next '空意味着 0 长度
-  arrlen = (UBound(src) - LBound(src))
-End Function
-
-'// 对数组进行排序[单维]
-Public Function ArraySort(src As Variant) As Variant
-  Dim out As Long, i As Long, tmp As Variant
-  For out = LBound(src) To UBound(src) - 1
-    For i = out + 1 To UBound(src)
-      If src(out) > src(i) Then
-        tmp = src(i): src(i) = src(out): src(out) = tmp
-      End If
-    Next i
-  Next out
-  
-  ArraySort = src
-End Function
-
-'//  把一个数组倒序
-Public Function ArrayReverse(arr)
-    Dim i As Integer, n As Integer
-    n = UBound(arr)
-    Dim P(): ReDim P(n)
-    For i = 0 To n
-        P(i) = arr(n - i)
-    Next
-    ArrayReverse = P
-End Function
-
-'// 测试数组排序
-Private Function test_ArraySort()
-  Dim arr As Variant, i As Integer
-  arr = Array(5, 4, 3, 2, 1, 9, 999, 33)
-  For i = 0 To arrlen(arr) - 1
-    Debug.Print arr(i);
-  Next i
-  Debug.Print arrlen(arr)
-  ArraySort arr
-  For i = 0 To arrlen(arr) - 1
-    Debug.Print arr(i);
-  Next i
-End Function
-
-'// 两点连线的角度:返回角度(相对于X轴的角度)
-'// p为末点,O为始点
-Public Function alfaPP(P, o)
-    Dim pi As Double: pi = 4 * Atn(1)
-    Dim beta As Double
-    If P(0) = o(0) And P(1) = o(1) Then '二点重合
-        alfaPP = 0
-        Exit Function
-    ElseIf P(0) = o(0) And P(1) > o(1) Then
-        beta = pi / 2
-    ElseIf P(0) = o(0) And P(1) < o(1) Then
-        beta = -pi / 2
-    ElseIf P(1) = o(1) And P(0) < o(0) Then
-        beta = pi
-    ElseIf P(1) = o(1) And P(0) > o(0) Then
-        beta = 0
-    Else
-        beta = Atn((P(1) - o(1)) / VBA.Abs(P(0) - o(0)))
-        If P(1) > o(1) And P(0) < o(0) Then
-            beta = pi - beta
-        ElseIf P(1) < o(1) And P(0) < o(0) Then
-            beta = -(pi + beta)
-        End If
-    End If
-    alfaPP = beta * 180 / pi
-End Function
-
-'// 求过P点到线段AB上的垂足点(XY平面内的二维计算)
-Public Function pFootInXY(P, a, b)
-    If a(0) = b(0) Then
-        pFootInXY = Array(a(0), P(1), 0#): Exit Function
-    End If
-    If a(1) = b(1) Then
-        pFootInXY = Array(P(0), a(1), 0#): Exit Function
-    End If
-    Dim aa, bb, c, d, x, y
-    aa = (a(1) - b(1)) / (a(0) - b(0))
-    bb = a(1) - aa * a(0)
-    c = -(a(0) - b(0)) / (a(1) - b(1))
-    d = P(1) - c * P(0)
-    x = (d - bb) / (aa - c)
-    y = aa * x + bb
-    pFootInXY = Array(x, y, 0#)
-End Function
-
-
-Public Function FindAllShapes() As ShapeRange
-  Dim s As Shape
-  Dim srPowerClipped As New ShapeRange
-  Dim sr As ShapeRange, srAll As New ShapeRange
-  
-  If ActiveSelection.Shapes.Count > 0 Then
-    Set sr = ActiveSelection.Shapes.FindShapes()
-  Else
-    Set sr = ActivePage.Shapes.FindShapes()
-  End If
-  
-  Do
-    For Each s In sr.Shapes.FindShapes(Query:="[email protected]")
-        srPowerClipped.AddRange s.PowerClip.Shapes.FindShapes()
-    Next s
-    srAll.AddRange sr
-    sr.RemoveAll
-    sr.AddRange srPowerClipped
-    srPowerClipped.RemoveAll
-  Loop Until sr.Count = 0
-  
-  Set FindAllShapes = srAll
-End Function
-
-' ************* 函数模块 ************* '
-Public Function ExistsFile_UseFso(ByVal strPath As String) As Boolean
-     Dim fso
-     Set fso = CreateObject("Scripting.FileSystemObject")
-     ExistsFile_UseFso = fso.FileExists(strPath)
-     Set fso = Nothing
-End Function
-
-Public Function test_sapi()
-  Dim message, sapi
-  MsgBox ("Please use the headset and listen to what I have to say...")
-  message = "This is a simple voice test on your Microsoft Windows."
-  Set sapi = CreateObject("sapi.spvoice")
-  sapi.Speak message
-End Function
-
-
-' Public Function WebHelp(url As String)
-'  Dim h As Longer, r As Long
-'  h = FindWindow(vbNullString, "Toolbar")
-'  r = ShellExecute(h, "", url, "", "", 1)
-' End Function
-
-
+Attribute VB_Name = "API"
+'// This is free and unencumbered software released into the public domain.
+'// For more information, please refer to  https://github.com/hongwenjun
+
+'// CorelDRAW 窗口刷新优化和关闭
+Public Function BeginOpt(Optional ByVal name As String = "Undo")
+  EventsEnabled = False
+  ActiveDocument.BeginCommandGroup name
+' ActiveDocument.SaveSettings
+  ActiveDocument.Unit = cdrMillimeter
+  Optimization = True
+' ActiveDocument.PreserveSelection = False
+End Function
+
+Public Function EndOpt()
+' ActiveDocument.PreserveSelection = True
+' ActiveDocument.RestoreSettings
+  EventsEnabled = True
+  Optimization = False
+  EventsEnabled = True
+  ActiveDocument.ReferencePoint = cdrBottomLeft
+  Application.Refresh
+  ActiveDocument.EndCommandGroup
+End Function
+
+Public Function Speak_Msg(message As String)
+  Speak_Help = Val(GetSetting("LYVBA", "Settings", "SpeakHelp", "0"))     '// 关停语音功能
+  
+  If Val(Speak_Help) = 1 Then
+    Dim sapi
+    Set sapi = CreateObject("sapi.spvoice")
+    sapi.Speak message
+  Else
+    ' 不说话
+  End If
+
+End Function
+
+Public Function GetSet(s As String)
+  Bleed = Val(GetSetting("LYVBA", "Settings", "Bleed", "2.0"))
+  Line_len = Val(GetSetting("LYVBA", "Settings", "Line_len", "3.0"))
+  Outline_Width = Val(GetSetting("LYVBA", "Settings", "Outline_Width", "0.2"))
+' Debug.Print Bleed, Line_len, Outline_Width
+
+  If s = "Bleed" Then
+    GetSet = Bleed
+  ElseIf s = "Line_len" Then
+    GetSet = Line_len
+  ElseIf s = "Outline_Width" Then
+    GetSet = Outline_Width
+  End If
+  
+End Function
+
+Public Function Create_Tolerance() As Double
+  Dim text As String
+  If GlobalUserData.Exists("Tolerance", 1) Then
+    text = GlobalUserData("Tolerance", 1)
+  End If
+  text = InputBox("请输入容差值 0.1 --> 9.9", "容差值(mm)", text)
+  If text = "" Then Exit Function
+  GlobalUserData("Tolerance", 1) = text
+  Create_Tolerance = Val(text)
+End Function
+
+Public Function Set_Space_Width(Optional ByVal OnlyRead As Boolean = False) As Double
+  Dim text As String
+  If GlobalUserData.Exists("SpaceWidth", 1) Then
+    text = GlobalUserData("SpaceWidth", 1)
+    If OnlyRead Then
+      Set_Space_Width = Val(text)
+      Exit Function
+    End If
+  End If
+  text = InputBox("请输入间隔宽度值 -99 --> 99", "设置间隔宽度(mm)", text)
+  If text = "" Then Exit Function
+  GlobalUserData("SpaceWidth", 1) = text
+  Set_Space_Width = Val(text)
+End Function
+
+'// 获得剪贴板文本字符
+Public Function GetClipBoardString() As String
+  On Error Resume Next
+  Dim MyData As New DataObject
+  GetClipBoardString = ""
+  MyData.GetFromClipboard
+  GetClipBoardString = MyData.GetText
+  Set MyData = Nothing
+End Function
+
+'// 文本字符复制到剪贴板
+Public Function WriteClipBoard(ByVal s As String)
+  On Error Resume Next
+
+' VBA_WIN10(vba7) 使用PutInClipboard乱码解决办法
+#If VBA7 Then
+  With CreateObject("Forms.TextBox.1")
+    .MultiLine = True
+    .text = s
+    .SelStart = 0
+    .SelLength = .TextLength
+    .Copy
+  End With
+#Else
+  Dim MyData As New DataObject
+  MyData.SetText s
+  MyData.PutInClipboard
+#End If
+End Function
+
+'// 换行转空格 多个空格换成一个空格
+Public Function Newline_to_Space(ByVal str As String) As String
+  str = VBA.Replace(str, Chr(13), " ")
+  str = VBA.Replace(str, Chr(9), " ")
+  Do While InStr(str, "  ")
+      str = VBA.Replace(str, "  ", " ")
+  Loop
+  Newline_to_Space = str
+End Function
+
+'// 获得数组元素个数
+Public Function arrlen(src As Variant) As Integer
+  On Error Resume Next '空意味着 0 长度
+  arrlen = (UBound(src) - LBound(src))
+End Function
+
+'// 对数组进行排序[单维]
+Public Function ArraySort(src As Variant) As Variant
+  Dim out As Long, i As Long, tmp As Variant
+  For out = LBound(src) To UBound(src) - 1
+    For i = out + 1 To UBound(src)
+      If src(out) > src(i) Then
+        tmp = src(i): src(i) = src(out): src(out) = tmp
+      End If
+    Next i
+  Next out
+  
+  ArraySort = src
+End Function
+
+'//  把一个数组倒序
+Public Function ArrayReverse(arr)
+    Dim i As Integer, n As Integer
+    n = UBound(arr)
+    Dim P(): ReDim P(n)
+    For i = 0 To n
+        P(i) = arr(n - i)
+    Next
+    ArrayReverse = P
+End Function
+
+'// 测试数组排序
+Private Function test_ArraySort()
+  Dim arr As Variant, i As Integer
+  arr = Array(5, 4, 3, 2, 1, 9, 999, 33)
+  For i = 0 To arrlen(arr) - 1
+    Debug.Print arr(i);
+  Next i
+  Debug.Print arrlen(arr)
+  ArraySort arr
+  For i = 0 To arrlen(arr) - 1
+    Debug.Print arr(i);
+  Next i
+End Function
+
+'// 两点连线的角度:返回角度(相对于X轴的角度)
+'// p为末点,O为始点
+Public Function alfaPP(P, o)
+    Dim pi As Double: pi = 4 * Atn(1)
+    Dim beta As Double
+    If P(0) = o(0) And P(1) = o(1) Then '二点重合
+        alfaPP = 0
+        Exit Function
+    ElseIf P(0) = o(0) And P(1) > o(1) Then
+        beta = pi / 2
+    ElseIf P(0) = o(0) And P(1) < o(1) Then
+        beta = -pi / 2
+    ElseIf P(1) = o(1) And P(0) < o(0) Then
+        beta = pi
+    ElseIf P(1) = o(1) And P(0) > o(0) Then
+        beta = 0
+    Else
+        beta = Atn((P(1) - o(1)) / VBA.Abs(P(0) - o(0)))
+        If P(1) > o(1) And P(0) < o(0) Then
+            beta = pi - beta
+        ElseIf P(1) < o(1) And P(0) < o(0) Then
+            beta = -(pi + beta)
+        End If
+    End If
+    alfaPP = beta * 180 / pi
+End Function
+
+'// 求过P点到线段AB上的垂足点(XY平面内的二维计算)
+Public Function pFootInXY(P, a, b)
+    If a(0) = b(0) Then
+        pFootInXY = Array(a(0), P(1), 0#): Exit Function
+    End If
+    If a(1) = b(1) Then
+        pFootInXY = Array(P(0), a(1), 0#): Exit Function
+    End If
+    Dim aa, bb, c, d, x, y
+    aa = (a(1) - b(1)) / (a(0) - b(0))
+    bb = a(1) - aa * a(0)
+    c = -(a(0) - b(0)) / (a(1) - b(1))
+    d = P(1) - c * P(0)
+    x = (d - bb) / (aa - c)
+    y = aa * x + bb
+    pFootInXY = Array(x, y, 0#)
+End Function
+
+
+Public Function FindAllShapes() As ShapeRange
+  Dim s As Shape
+  Dim srPowerClipped As New ShapeRange
+  Dim sr As ShapeRange, srAll As New ShapeRange
+  
+  If ActiveSelection.Shapes.Count > 0 Then
+    Set sr = ActiveSelection.Shapes.FindShapes()
+  Else
+    Set sr = ActivePage.Shapes.FindShapes()
+  End If
+  
+  Do
+    For Each s In sr.Shapes.FindShapes(Query:="[email protected]")
+        srPowerClipped.AddRange s.PowerClip.Shapes.FindShapes()
+    Next s
+    srAll.AddRange sr
+    sr.RemoveAll
+    sr.AddRange srPowerClipped
+    srPowerClipped.RemoveAll
+  Loop Until sr.Count = 0
+  
+  Set FindAllShapes = srAll
+End Function
+
+' ************* 函数模块 ************* '
+Public Function ExistsFile_UseFso(ByVal strPath As String) As Boolean
+     Dim fso
+     Set fso = CreateObject("Scripting.FileSystemObject")
+     ExistsFile_UseFso = fso.FileExists(strPath)
+     Set fso = Nothing
+End Function
+
+Public Function test_sapi()
+  Dim message, sapi
+  MsgBox ("Please use the headset and listen to what I have to say...")
+  message = "This is a simple voice test on your Microsoft Windows."
+  Set sapi = CreateObject("sapi.spvoice")
+  sapi.Speak message
+End Function
+
+
+' Public Function WebHelp(url As String)
+'  Dim h As Longer, r As Long
+'  h = FindWindow(vbNullString, "Toolbar")
+'  r = ShellExecute(h, "", url, "", "", 1)
+' End Function
+
+

+ 39 - 39
AverageDistance.bas

@@ -1,39 +1,39 @@
-Attribute VB_Name = "AverageDistance"
-Public AutoDistribute_Key As Boolean
-Public first_StaticID As Long
-
-'// 选择的物件平均距离
-Public Function Average_Distance()
-  On Error GoTo ErrorHandler
-  API.BeginOpt
-  
-  Dim sr As ShapeRange
-  Set sr = ActiveSelectionRange
-  sr.Sort "@shape1.left<@shape2.left"
-
-  Distribute_Shapes sr
-  
-ErrorHandler:
-  API.EndOpt
-End Function
-
-Private Function Distribute_Shapes(sr As ShapeRange)
-  Dim first As Double, last As Double
-  Dim interval As Double, currentPoint As Double
-  Dim total As Integer
-  Dim sh As Shape
-  
-  first_StaticID = sr.FirstShape.StaticID
-  total = sr.Count
-  first = sr.FirstShape.CenterX
-  last = sr.LastShape.CenterX
-  interval = (last - first) / (total - 1)
-  currentPoint = first
-
-
-  For Each sh In sr
-    sh.CenterY = sr.FirstShape.CenterY
-    sh.CenterX = currentPoint
-    currentPoint = currentPoint + interval
-  Next sh
-End Function
+Attribute VB_Name = "AverageDistance"
+Public AutoDistribute_Key As Boolean
+Public first_StaticID As Long
+
+'// 选择的物件平均距离
+Public Function Average_Distance()
+  On Error GoTo ErrorHandler
+  API.BeginOpt
+  
+  Dim sr As ShapeRange
+  Set sr = ActiveSelectionRange
+  sr.Sort "@shape1.left<@shape2.left"
+
+  Distribute_Shapes sr
+  
+ErrorHandler:
+  API.EndOpt
+End Function
+
+Private Function Distribute_Shapes(sr As ShapeRange)
+  Dim first As Double, last As Double
+  Dim interval As Double, currentPoint As Double
+  Dim total As Integer
+  Dim sh As Shape
+  
+  first_StaticID = sr.FirstShape.StaticID
+  total = sr.Count
+  first = sr.FirstShape.CenterX
+  last = sr.LastShape.CenterX
+  interval = (last - first) / (total - 1)
+  currentPoint = first
+
+
+  For Each sh In sr
+    sh.CenterY = sr.FirstShape.CenterY
+    sh.CenterX = currentPoint
+    currentPoint = currentPoint + interval
+  Next sh
+End Function

+ 358 - 358
Box.bas

@@ -1,358 +1,358 @@
-Attribute VB_Name = "box"
-'// This is free and unencumbered software released into the public domain.
-'// For more information, please refer to  https://github.com/hongwenjun
-
-Public Function Simple_box_five(Optional ByVal l As Double, Optional ByVal w As Double, Optional ByVal h As Double, Optional ByVal b As Double = 15)
-  Dim sr As New ShapeRange, wing As New ShapeRange, BottomWing As ShapeRange
-  Dim sh As Shape
-  l1x = w: l2x = w + l: l3x = 2 * w + l: l4x = 2 * (w + l)
-  
-  '// 绘制主体上下盖矩形
-  Set mainRect_aw = ActiveLayer.CreateRectangle(0, 0, w, h)
-  Set mainRect_al = ActiveLayer.CreateRectangle(0, 0, l, h)
-  mainRect_al.Move l1x, 0
-  Set mainRect_bw = ActiveLayer.CreateRectangle(0, 0, w, h)
-  mainRect_bw.Move l2x, 0
-  Set mainRect_bl = ActiveLayer.CreateRectangle(0, 0, l, h)
-  mainRect_bl.Move l3x, 0
-
-  Set topRect = ActiveLayer.CreateRectangle(0, 0, l, w)
-  topRect.Move l1x, h
-
-  '// 绘制Box 圆角矩形插口
-  Set top_RoundRect = ActiveLayer.CreateRectangle(0, 0, l, b, 75, 75)
-  top_RoundRect.Move l1x, h + w
-  Set Bond = DrawBond(b, h, l4x, 0)
-
-  Set SealLine = Draw_SealLine(l, l1x, h + w - 1)
-  Set top_RoundRect = top_RoundRect.Weld(topRect, False, False)
-
-  '// 绘制box 2个翅膀
-  Set sh = DrawWing(w, (w + b) / 2 - 2)
-  wing.Add sh.Duplicate(0, h)
-  wing.Add sh.Duplicate(l2x, h)
-  wing(2).Flip cdrFlipHorizontal
-
-  '// 绘制 Box 底下翅膀 BottomWing
-  Set BottomWing = DrawBottomWing(l, w, b)
-
-  '// 添加到物件组,设置轮廓色 C100
-  sr.Add mainRect_aw: sr.Add mainRect_al: sr.Add mainRect_bw: sr.Add mainRect_bl
-  sr.Add Bond: sr.Add top_RoundRect
-  sr.AddRange BottomWing
-  sr.AddRange wing: sh.Delete
-  sr.SetOutlineProperties Color:=CreateCMYKColor(100, 0, 0, 0)
-  sr.Add SealLine
-  
-  sr.CreateSelection: sr.Group
-End Function
-
-Private Function DrawBottomWing(ByVal l As Double, ByVal w As Double, ByVal b As Double) As ShapeRange
-  Dim sr As New ShapeRange, s As Shape
-  Dim sp As SubPath, crv(3) As Curve
-  
-  w_2 = w / 2#
-  block = w * 0.275 + w * ((l - w) / w * 0.15)
-  bb = block + b: If bb < w_2 Then bb = w_2
-
-  '// 绘制 Box 底下翅膀 BottomWing
-  Set crv(1) = Application.CreateCurve(ActiveDocument)
-  Set sp = crv(1).CreateSubPath(0, 0)
-  sp.AppendLineSegment w_2, block
-  sp.AppendLineSegment w_2, bb - 5
-  sp.AppendCurveSegment2 w_2 + 5, bb, w_2, bb - 2.5, w_2 + 2.5, bb
-  sp.AppendLineSegment w, bb
-  sp.AppendLineSegment w, 0
-  sp.Closed = True
-  sr.Add ActiveLayer.CreateCurve(crv(1))
-  
-  Set crv(2) = Application.CreateCurve(ActiveDocument)
-  Set sp = crv(2).CreateSubPath(0, 0)
-  sp.AppendLineSegment w_2, block
-  sp.AppendLineSegment w_2 + b - 5, block
-  sp.AppendCurveSegment2 w_2 + b, block + 5, w_2 + b - 2.5, block, w_2 + b, block + 2.5
-  sp.AppendLineSegment w_2 + b, l - block - 5
-  sp.AppendCurveSegment2 w_2 + b - 5, l - block, w_2 + b, l - block - 2.5, w_2 + b - 2.5, l - block
-  
-  sp.AppendLineSegment w_2, l - block
-  sp.AppendLineSegment 0, l
-  sp.Closed = True
-  sr.Add ActiveLayer.CreateCurve(crv(2))
-  
-  Set crv(3) = Application.CreateCurve(ActiveDocument)
-  Set sp = crv(3).CreateSubPath(0, 0)
-  sp.AppendLineSegment 0, l
-  sp.AppendLineSegment w_2 + b, l
-  sp.AppendLineSegment w_2 + b, l - block + 5
-  sp.AppendCurveSegment2 w_2 + b - 5, l - block, w_2 + b, l - block + 2.5, w_2 + b - 2.5, l - block
-  sp.AppendLineSegment w_2, l - block
-  sp.AppendLineSegment w_2, block
-  sp.AppendLineSegment w_2 + b - 5, block
-  sp.AppendCurveSegment2 w_2 + b, block - 5, w_2 + b - 2.5, block, w_2 + b, block - 2.5
-  sp.AppendLineSegment w_2 + b, 0
-  sp.Closed = True
-  sr.Add ActiveLayer.CreateCurve(crv(3))
-  
-  '// 移动到适合的地方
-  sr(1).Move 0, -bb: sr(1).Rotate 180
-  Set s = sr(1).Duplicate(0, 0): sr.Add s
-  s.Flip cdrFlipHorizontal: s.Move w + l, 0
-  
-  sr(2).Rotate -90: sr(3).Rotate -90
-  sr(2).LeftX = 2 * w + l: sr(3).LeftX = w
-  sr(2).topY = 0: sr(3).topY = 0
-  Set DrawBottomWing = sr
-  
-End Function
-
-
-Public Function Simple_box_four(Optional ByVal l As Double, Optional ByVal w As Double, Optional ByVal h As Double, Optional ByVal b As Double = 15)
-  Dim sr As New ShapeRange, wing As New ShapeRange
-  Dim sh As Shape
-  l1x = w: l2x = w + l: l3x = 2 * w + l: l4x = 2 * (w + l)
-  
-  '// 绘制主体上下盖矩形
-  Set mainRect_aw = ActiveLayer.CreateRectangle(0, 0, w, h)
-  Set mainRect_al = ActiveLayer.CreateRectangle(0, 0, l, h)
-  mainRect_al.Move l1x, 0
-  Set mainRect_bw = ActiveLayer.CreateRectangle(0, 0, w, h)
-  mainRect_bw.Move l2x, 0
-  Set mainRect_bl = ActiveLayer.CreateRectangle(0, 0, l, h)
-  mainRect_bl.Move l3x, 0
-
-  Set topRect = ActiveLayer.CreateRectangle(0, 0, l, w)
-  topRect.Move l1x, h
-  Set bottomRect = ActiveLayer.CreateRectangle(0, 0, l, w)
-  bottomRect.Move l3x, -w
-  
-  '// 绘制Box 圆角矩形插口
-  Set top_RoundRect = ActiveLayer.CreateRectangle(0, 0, l, b, 75, 75)
-  top_RoundRect.Move l1x, h + w
-  Set bottom_RoundRect = ActiveLayer.CreateRectangle(0, 0, l, b, 0, 0, 75, 75)
-  bottom_RoundRect.Move l3x, -w - b
-  Set Bond = DrawBond(b, h, l4x, 0)
-  
-  Set SealLine = Draw_SealLine(l, l1x, h + w - 1)
-  Set SealLine2 = Draw_SealLine(l, l3x, -w - 1)
-  SealLine2.Rotate 180
-  
-  '// 绘制box 四个翅膀
-  Set sh = DrawWing(w, (w + b) / 2 - 2)
-  wing.Add sh.Duplicate(0, h)
-  wing.Add sh.Duplicate(l2x, h)
-  wing.Add sh.Duplicate(0, -sh.SizeHeight)
-  wing.Add sh.Duplicate(l2x, -sh.SizeHeight)
-  wing(2).Flip cdrFlipHorizontal
-  wing(3).Rotate 180
-  wing(4).Flip cdrFlipVertical
-
-  Set top_RoundRect = top_RoundRect.Weld(topRect, False, False)
-  Set bottom_RoundRect = bottom_RoundRect.Weld(bottomRect, False, False)
-
-  '// 添加到物件组,设置轮廓色 C100
-  sr.Add mainRect_aw: sr.Add mainRect_al: sr.Add mainRect_bw: sr.Add mainRect_bl
-  sr.Add Bond: sr.Add top_RoundRect: sr.Add bottom_RoundRect
-  sr.AddRange wing: sh.Delete
-  sr.SetOutlineProperties Color:=CreateCMYKColor(100, 0, 0, 0)
-  sr.Add SealLine: sr.Add SealLine2
-  sr.CreateSelection: sr.Group
-  
-End Function
-
-Public Function input_box_lwh() As Variant
-  Dim str, arr, n
-  str = InputBox("请输入长x宽x高,使用空格 * x 间隔" & vbNewLine & "鼠标左键-右键-Ctrl三种样式", "盒子长宽高", "120 x 100 x 150 mm") & " "
-  str = Newline_to_Space(str)
-
-  ' 替换 mm x * 换行 TAB 为空格
-  str = VBA.Replace(str, "mm", " ")
-  str = VBA.Replace(str, "x", " ")
-  str = VBA.Replace(str, "X", " ")
-  str = VBA.Replace(str, "*", " ")
-
-  '// 换行转空格 多个空格换成一个空格
-  str = API.Newline_to_Space(str)
-
-  arr = Split(str)
-  arr(0) = Val(arr(0))
-  arr(1) = Val(arr(1))
-  arr(2) = Val(arr(2))
-  arr(3) = Val(arr(3))
-  input_box_lwh = arr
-End Function
-
-Public Function Simple_box_three(Optional ByVal l As Double, Optional ByVal w As Double, Optional ByVal h As Double, Optional ByVal b As Double = 15)
-  ActiveDocument.Unit = cdrMillimeter
-  Dim sr As New ShapeRange, wing As New ShapeRange
-  Dim sh As Shape
-  boxL = 2 * l + 2 * w + b: boxH = h
-  l1x = w: l2x = w + l: l3x = 2 * w + l: l4x = 2 * (w + l)
-  
-  '// 绘制主体上下盖矩形
-  Set mainRect = ActiveLayer.CreateRectangle(0, 0, boxL, boxH)
-  Set topRect = ActiveLayer.CreateRectangle(0, 0, l, w)
-  topRect.Move l1x, h
-  Set bottomRect = ActiveLayer.CreateRectangle(0, 0, l, w)
-  bottomRect.Move l3x, -w
-  
-  '// 绘制Box 圆角矩形插口
-  Set top_RoundRect = ActiveLayer.CreateRectangle(0, 0, l, b, 75, 75)
-  top_RoundRect.Move l1x, h + w
-  Set bottom_RoundRect = ActiveLayer.CreateRectangle(0, 0, l, b, 0, 0, 75, 75)
-  bottom_RoundRect.Move l3x, -w - b
-  
-  '// 绘制box 四个翅膀
-  Set sh = DrawWing(w, (w + b) / 2 - 2)
-  wing.Add sh.Duplicate(0, h)
-  wing.Add sh.Duplicate(l2x, h)
-  wing.Add sh.Duplicate(0, -sh.SizeHeight)
-  wing.Add sh.Duplicate(l2x, -sh.SizeHeight)
-  wing(2).Flip cdrFlipHorizontal
-  wing(3).Rotate 180
-  wing(4).Flip cdrFlipVertical
-
-  Set top_RoundRect = top_RoundRect.Weld(topRect, False, False)
-  Set bottom_RoundRect = bottom_RoundRect.Weld(bottomRect, False, False)
-  
-  '// 添加到物件组,设置轮廓色 C100
-  sr.Add mainRect: sr.Add top_RoundRect: sr.Add bottom_RoundRect
-  sr.AddRange wing: sh.Delete
-  sr.SetOutlineProperties Color:=CreateCMYKColor(100, 0, 0, 0)
-  
-  '// 绘制尺寸刀痕线
-  Set sl1 = DrawLine(l1x, 0, l1x, h)
-  Set sl2 = DrawLine(l2x, 0, l2x, h)
-  Set sl3 = DrawLine(l3x, 0, l3x, h)
-  Set sl4 = DrawLine(l4x, 0, l4x, h)
-  Set SealLine = Draw_SealLine(l, l1x, h + w - 1)
-  Set SealLine2 = Draw_SealLine(l, l3x, -w - 1)
-  SealLine2.Rotate 180
-  
-  '// 盒子box 群组
-  sr.Add sl1: sr.Add sl2: sr.Add sl3: sr.Add sl4
-  sr.Add SealLine: sr.Add SealLine2
-  sr.CreateSelection: sr.Group
-  
-End Function
-
-'// 画一条线,设置轮廓色 M100
-Private Function DrawLine(x1, y1, x2, y2) As Shape
-  Set DrawLine = ActiveLayer.CreateLineSegment(x1, y1, x2, y2)
-  DrawLine.Outline.SetProperties Color:=CreateCMYKColor(0, 100, 0, 0)
-End Function
-
-'// 绘制封口线
-Private Function Draw_SealLine(ByVal l As Double, ByVal move_x As Double, ByVal move_y As Double) As Shape
-  Dim sp As SubPath, crv As Curve
-  '// 绘制 Box 翅膀 Wing
-  Set crv = Application.CreateCurve(ActiveDocument)
-  Set sp = crv.CreateSubPath(0, 2)
-  sp.AppendLineSegment 4, 2
-  sp.AppendLineSegment 6, 0
-  sp.AppendLineSegment l - 6, 0
-  sp.AppendLineSegment l - 4, 2
-  sp.AppendLineSegment l, 2
-  sp.Closed = False
-  Set Draw_SealLine = ActiveLayer.CreateCurve(crv)
-  Draw_SealLine.Outline.SetProperties Color:=CreateCMYKColor(0, 100, 0, 0)
-  Draw_SealLine.Move move_x, move_y
-End Function
-
-Private Function DrawWing(ByVal w As Double, ByVal h As Double) As Shape
-    Dim sp As SubPath, crv As Curve
-    Dim x As Double, y As Double
-    x = w: y = h
-    
-    '// 绘制 Box 翅膀 Wing
-    Set crv = Application.CreateCurve(ActiveDocument)
-    Set sp = crv.CreateSubPath(0, 0)
-    sp.AppendLineSegment 0, 4
-    sp.AppendLineSegment 2, 6
-    sp.AppendLineSegment 6, y - 2.5
-    sp.AppendCurveSegment2 8.5, y, 6.2, y - 1.25, 7, y
-    sp.AppendLineSegment x - 2, y
-    sp.AppendLineSegment x - 2, 3
-    sp.AppendLineSegment x, 0
-    
-    sp.Closed = True
-    Set DrawWing = ActiveLayer.CreateCurve(crv)
-End Function
-
-Private Function DrawBond(ByVal w As Double, ByVal h As Double, ByVal move_x As Double, ByVal move_y As Double) As Shape
-    Dim sp As SubPath, crv As Curve
-    Dim x As Double, y As Double
-    x = w: y = h
-    
-    '// 绘制 Box 粘合边 Bond
-    Set crv = Application.CreateCurve(ActiveDocument)
-    Set sp = crv.CreateSubPath(0, 0)
-    sp.AppendLineSegment 0, y
-    sp.AppendLineSegment x, y - 5
-    sp.AppendLineSegment x, 5
-
-    sp.Closed = True
-    Set DrawBond = ActiveLayer.CreateCurve(crv)
-    DrawBond.Move move_x, move_y
-End Function
-
-
-Public Function Simple_box_one()
-  ActiveDocument.Unit = cdrMillimeter
-  l = 100: w = 50: h = 70: b = 15
-  boxL = 2 * l + 2 * w + b
-  boxH = h
-  l1x = w
-  l2x = w + l
-  l3x = 2 * w + l
-  l4x = 2 * (w + l)
-  
-  Set Rect = ActiveLayer.CreateRectangle(0, 0, boxL, boxH)
-  Set sl1 = DrawLine(l1x, 0, l1x, h)
-  Set sl2 = DrawLine(l2x, 0, l2x, h)
-  Set sl3 = DrawLine(l3x, 0, l3x, h)
-  Set sl4 = DrawLine(l4x, 0, l4x, h)
-End Function
-
-Public Function Simple_box_two()
-  ActiveDocument.Unit = cdrMillimeter
-  l = 100: w = 50: h = 70: b = 15
-  boxL = 2 * l + 2 * w + b: boxH = h
-  l1x = w: l2x = w + l: l3x = 2 * w + l: l4x = 2 * (w + l)
-  
-  Set mainRect = ActiveLayer.CreateRectangle(0, 0, boxL, boxH)
-  
-  Set topRect = ActiveLayer.CreateRectangle(0, 0, l, w)
-  topRect.Move l1x, h
-  Set bottomRect = ActiveLayer.CreateRectangle(0, 0, l, w)
-  bottomRect.Move l3x, -w
-  
-  Set sl1 = DrawLine(l1x, 0, l1x, h)
-  Set sl2 = DrawLine(l2x, 0, l2x, h)
-  Set sl3 = DrawLine(l3x, 0, l3x, h)
-  Set sl4 = DrawLine(l4x, 0, l4x, h)
-End Function
-
-
-Public Function Simple_3Deffect()
-  Dim sr As ShapeRange            '// 定义物件范围
-  Set sr = ActiveSelectionRange   '// 选择3个物件
-  
-  If sr.Count >= 3 Then
-  
-  '// 先上下再左右排序
-#If VBA7 Then
-    sr.Sort " @shape1.Top * 100 - @shape1.Left > @shape2.Top * 100 - @shape2.Left"
-#Else
-    Set ssr = X4_Sort_ShapeRange(sr, topWt_left)
-#End If
-
-    sr(1).Stretch 0.951, 0.525      ' 顶盖物件缩放修正和变形
-    sr(1).Skew 41.7, 7#
-      
-    sr(2).Stretch 0.951, 0.937      ' 正面物件缩放修正和变形
-    sr(2).Skew 0#, 7#
-    
-    sr(3).Stretch 0.468, 0.937      ' 侧面物件缩放修正和变形
-    sr(3).Skew 0#, -45#
-  End If
-End Function
+Attribute VB_Name = "box"
+'// This is free and unencumbered software released into the public domain.
+'// For more information, please refer to  https://github.com/hongwenjun
+
+Public Function Simple_box_five(Optional ByVal l As Double, Optional ByVal w As Double, Optional ByVal h As Double, Optional ByVal b As Double = 15)
+  Dim sr As New ShapeRange, wing As New ShapeRange, BottomWing As ShapeRange
+  Dim sh As Shape
+  l1x = w: l2x = w + l: l3x = 2 * w + l: l4x = 2 * (w + l)
+  
+  '// 绘制主体上下盖矩形
+  Set mainRect_aw = ActiveLayer.CreateRectangle(0, 0, w, h)
+  Set mainRect_al = ActiveLayer.CreateRectangle(0, 0, l, h)
+  mainRect_al.Move l1x, 0
+  Set mainRect_bw = ActiveLayer.CreateRectangle(0, 0, w, h)
+  mainRect_bw.Move l2x, 0
+  Set mainRect_bl = ActiveLayer.CreateRectangle(0, 0, l, h)
+  mainRect_bl.Move l3x, 0
+
+  Set topRect = ActiveLayer.CreateRectangle(0, 0, l, w)
+  topRect.Move l1x, h
+
+  '// 绘制Box 圆角矩形插口
+  Set top_RoundRect = ActiveLayer.CreateRectangle(0, 0, l, b, 75, 75)
+  top_RoundRect.Move l1x, h + w
+  Set Bond = DrawBond(b, h, l4x, 0)
+
+  Set SealLine = Draw_SealLine(l, l1x, h + w - 1)
+  Set top_RoundRect = top_RoundRect.Weld(topRect, False, False)
+
+  '// 绘制box 2个翅膀
+  Set sh = DrawWing(w, (w + b) / 2 - 2)
+  wing.Add sh.Duplicate(0, h)
+  wing.Add sh.Duplicate(l2x, h)
+  wing(2).Flip cdrFlipHorizontal
+
+  '// 绘制 Box 底下翅膀 BottomWing
+  Set BottomWing = DrawBottomWing(l, w, b)
+
+  '// 添加到物件组,设置轮廓色 C100
+  sr.Add mainRect_aw: sr.Add mainRect_al: sr.Add mainRect_bw: sr.Add mainRect_bl
+  sr.Add Bond: sr.Add top_RoundRect
+  sr.AddRange BottomWing
+  sr.AddRange wing: sh.Delete
+  sr.SetOutlineProperties Color:=CreateCMYKColor(100, 0, 0, 0)
+  sr.Add SealLine
+  
+  sr.CreateSelection: sr.Group
+End Function
+
+Private Function DrawBottomWing(ByVal l As Double, ByVal w As Double, ByVal b As Double) As ShapeRange
+  Dim sr As New ShapeRange, s As Shape
+  Dim sp As SubPath, crv(3) As Curve
+  
+  w_2 = w / 2#
+  block = w * 0.275 + w * ((l - w) / w * 0.15)
+  bb = block + b: If bb < w_2 Then bb = w_2
+
+  '// 绘制 Box 底下翅膀 BottomWing
+  Set crv(1) = Application.CreateCurve(ActiveDocument)
+  Set sp = crv(1).CreateSubPath(0, 0)
+  sp.AppendLineSegment w_2, block
+  sp.AppendLineSegment w_2, bb - 5
+  sp.AppendCurveSegment2 w_2 + 5, bb, w_2, bb - 2.5, w_2 + 2.5, bb
+  sp.AppendLineSegment w, bb
+  sp.AppendLineSegment w, 0
+  sp.Closed = True
+  sr.Add ActiveLayer.CreateCurve(crv(1))
+  
+  Set crv(2) = Application.CreateCurve(ActiveDocument)
+  Set sp = crv(2).CreateSubPath(0, 0)
+  sp.AppendLineSegment w_2, block
+  sp.AppendLineSegment w_2 + b - 5, block
+  sp.AppendCurveSegment2 w_2 + b, block + 5, w_2 + b - 2.5, block, w_2 + b, block + 2.5
+  sp.AppendLineSegment w_2 + b, l - block - 5
+  sp.AppendCurveSegment2 w_2 + b - 5, l - block, w_2 + b, l - block - 2.5, w_2 + b - 2.5, l - block
+  
+  sp.AppendLineSegment w_2, l - block
+  sp.AppendLineSegment 0, l
+  sp.Closed = True
+  sr.Add ActiveLayer.CreateCurve(crv(2))
+  
+  Set crv(3) = Application.CreateCurve(ActiveDocument)
+  Set sp = crv(3).CreateSubPath(0, 0)
+  sp.AppendLineSegment 0, l
+  sp.AppendLineSegment w_2 + b, l
+  sp.AppendLineSegment w_2 + b, l - block + 5
+  sp.AppendCurveSegment2 w_2 + b - 5, l - block, w_2 + b, l - block + 2.5, w_2 + b - 2.5, l - block
+  sp.AppendLineSegment w_2, l - block
+  sp.AppendLineSegment w_2, block
+  sp.AppendLineSegment w_2 + b - 5, block
+  sp.AppendCurveSegment2 w_2 + b, block - 5, w_2 + b - 2.5, block, w_2 + b, block - 2.5
+  sp.AppendLineSegment w_2 + b, 0
+  sp.Closed = True
+  sr.Add ActiveLayer.CreateCurve(crv(3))
+  
+  '// 移动到适合的地方
+  sr(1).Move 0, -bb: sr(1).Rotate 180
+  Set s = sr(1).Duplicate(0, 0): sr.Add s
+  s.Flip cdrFlipHorizontal: s.Move w + l, 0
+  
+  sr(2).Rotate -90: sr(3).Rotate -90
+  sr(2).LeftX = 2 * w + l: sr(3).LeftX = w
+  sr(2).topY = 0: sr(3).topY = 0
+  Set DrawBottomWing = sr
+  
+End Function
+
+
+Public Function Simple_box_four(Optional ByVal l As Double, Optional ByVal w As Double, Optional ByVal h As Double, Optional ByVal b As Double = 15)
+  Dim sr As New ShapeRange, wing As New ShapeRange
+  Dim sh As Shape
+  l1x = w: l2x = w + l: l3x = 2 * w + l: l4x = 2 * (w + l)
+  
+  '// 绘制主体上下盖矩形
+  Set mainRect_aw = ActiveLayer.CreateRectangle(0, 0, w, h)
+  Set mainRect_al = ActiveLayer.CreateRectangle(0, 0, l, h)
+  mainRect_al.Move l1x, 0
+  Set mainRect_bw = ActiveLayer.CreateRectangle(0, 0, w, h)
+  mainRect_bw.Move l2x, 0
+  Set mainRect_bl = ActiveLayer.CreateRectangle(0, 0, l, h)
+  mainRect_bl.Move l3x, 0
+
+  Set topRect = ActiveLayer.CreateRectangle(0, 0, l, w)
+  topRect.Move l1x, h
+  Set bottomRect = ActiveLayer.CreateRectangle(0, 0, l, w)
+  bottomRect.Move l3x, -w
+  
+  '// 绘制Box 圆角矩形插口
+  Set top_RoundRect = ActiveLayer.CreateRectangle(0, 0, l, b, 75, 75)
+  top_RoundRect.Move l1x, h + w
+  Set bottom_RoundRect = ActiveLayer.CreateRectangle(0, 0, l, b, 0, 0, 75, 75)
+  bottom_RoundRect.Move l3x, -w - b
+  Set Bond = DrawBond(b, h, l4x, 0)
+  
+  Set SealLine = Draw_SealLine(l, l1x, h + w - 1)
+  Set SealLine2 = Draw_SealLine(l, l3x, -w - 1)
+  SealLine2.Rotate 180
+  
+  '// 绘制box 四个翅膀
+  Set sh = DrawWing(w, (w + b) / 2 - 2)
+  wing.Add sh.Duplicate(0, h)
+  wing.Add sh.Duplicate(l2x, h)
+  wing.Add sh.Duplicate(0, -sh.SizeHeight)
+  wing.Add sh.Duplicate(l2x, -sh.SizeHeight)
+  wing(2).Flip cdrFlipHorizontal
+  wing(3).Rotate 180
+  wing(4).Flip cdrFlipVertical
+
+  Set top_RoundRect = top_RoundRect.Weld(topRect, False, False)
+  Set bottom_RoundRect = bottom_RoundRect.Weld(bottomRect, False, False)
+
+  '// 添加到物件组,设置轮廓色 C100
+  sr.Add mainRect_aw: sr.Add mainRect_al: sr.Add mainRect_bw: sr.Add mainRect_bl
+  sr.Add Bond: sr.Add top_RoundRect: sr.Add bottom_RoundRect
+  sr.AddRange wing: sh.Delete
+  sr.SetOutlineProperties Color:=CreateCMYKColor(100, 0, 0, 0)
+  sr.Add SealLine: sr.Add SealLine2
+  sr.CreateSelection: sr.Group
+  
+End Function
+
+Public Function input_box_lwh() As Variant
+  Dim str, arr, n
+  str = InputBox("请输入长x宽x高,使用空格 * x 间隔" & vbNewLine & "鼠标左键-右键-Ctrl三种样式", "盒子长宽高", "120 x 100 x 150 mm") & " "
+  str = Newline_to_Space(str)
+
+  ' 替换 mm x * 换行 TAB 为空格
+  str = VBA.Replace(str, "mm", " ")
+  str = VBA.Replace(str, "x", " ")
+  str = VBA.Replace(str, "X", " ")
+  str = VBA.Replace(str, "*", " ")
+
+  '// 换行转空格 多个空格换成一个空格
+  str = API.Newline_to_Space(str)
+
+  arr = Split(str)
+  arr(0) = Val(arr(0))
+  arr(1) = Val(arr(1))
+  arr(2) = Val(arr(2))
+  arr(3) = Val(arr(3))
+  input_box_lwh = arr
+End Function
+
+Public Function Simple_box_three(Optional ByVal l As Double, Optional ByVal w As Double, Optional ByVal h As Double, Optional ByVal b As Double = 15)
+  ActiveDocument.Unit = cdrMillimeter
+  Dim sr As New ShapeRange, wing As New ShapeRange
+  Dim sh As Shape
+  boxL = 2 * l + 2 * w + b: boxH = h
+  l1x = w: l2x = w + l: l3x = 2 * w + l: l4x = 2 * (w + l)
+  
+  '// 绘制主体上下盖矩形
+  Set mainRect = ActiveLayer.CreateRectangle(0, 0, boxL, boxH)
+  Set topRect = ActiveLayer.CreateRectangle(0, 0, l, w)
+  topRect.Move l1x, h
+  Set bottomRect = ActiveLayer.CreateRectangle(0, 0, l, w)
+  bottomRect.Move l3x, -w
+  
+  '// 绘制Box 圆角矩形插口
+  Set top_RoundRect = ActiveLayer.CreateRectangle(0, 0, l, b, 75, 75)
+  top_RoundRect.Move l1x, h + w
+  Set bottom_RoundRect = ActiveLayer.CreateRectangle(0, 0, l, b, 0, 0, 75, 75)
+  bottom_RoundRect.Move l3x, -w - b
+  
+  '// 绘制box 四个翅膀
+  Set sh = DrawWing(w, (w + b) / 2 - 2)
+  wing.Add sh.Duplicate(0, h)
+  wing.Add sh.Duplicate(l2x, h)
+  wing.Add sh.Duplicate(0, -sh.SizeHeight)
+  wing.Add sh.Duplicate(l2x, -sh.SizeHeight)
+  wing(2).Flip cdrFlipHorizontal
+  wing(3).Rotate 180
+  wing(4).Flip cdrFlipVertical
+
+  Set top_RoundRect = top_RoundRect.Weld(topRect, False, False)
+  Set bottom_RoundRect = bottom_RoundRect.Weld(bottomRect, False, False)
+  
+  '// 添加到物件组,设置轮廓色 C100
+  sr.Add mainRect: sr.Add top_RoundRect: sr.Add bottom_RoundRect
+  sr.AddRange wing: sh.Delete
+  sr.SetOutlineProperties Color:=CreateCMYKColor(100, 0, 0, 0)
+  
+  '// 绘制尺寸刀痕线
+  Set sl1 = DrawLine(l1x, 0, l1x, h)
+  Set sl2 = DrawLine(l2x, 0, l2x, h)
+  Set sl3 = DrawLine(l3x, 0, l3x, h)
+  Set sl4 = DrawLine(l4x, 0, l4x, h)
+  Set SealLine = Draw_SealLine(l, l1x, h + w - 1)
+  Set SealLine2 = Draw_SealLine(l, l3x, -w - 1)
+  SealLine2.Rotate 180
+  
+  '// 盒子box 群组
+  sr.Add sl1: sr.Add sl2: sr.Add sl3: sr.Add sl4
+  sr.Add SealLine: sr.Add SealLine2
+  sr.CreateSelection: sr.Group
+  
+End Function
+
+'// 画一条线,设置轮廓色 M100
+Private Function DrawLine(x1, y1, x2, y2) As Shape
+  Set DrawLine = ActiveLayer.CreateLineSegment(x1, y1, x2, y2)
+  DrawLine.Outline.SetProperties Color:=CreateCMYKColor(0, 100, 0, 0)
+End Function
+
+'// 绘制封口线
+Private Function Draw_SealLine(ByVal l As Double, ByVal move_x As Double, ByVal move_y As Double) As Shape
+  Dim sp As SubPath, crv As Curve
+  '// 绘制 Box 翅膀 Wing
+  Set crv = Application.CreateCurve(ActiveDocument)
+  Set sp = crv.CreateSubPath(0, 2)
+  sp.AppendLineSegment 4, 2
+  sp.AppendLineSegment 6, 0
+  sp.AppendLineSegment l - 6, 0
+  sp.AppendLineSegment l - 4, 2
+  sp.AppendLineSegment l, 2
+  sp.Closed = False
+  Set Draw_SealLine = ActiveLayer.CreateCurve(crv)
+  Draw_SealLine.Outline.SetProperties Color:=CreateCMYKColor(0, 100, 0, 0)
+  Draw_SealLine.Move move_x, move_y
+End Function
+
+Private Function DrawWing(ByVal w As Double, ByVal h As Double) As Shape
+    Dim sp As SubPath, crv As Curve
+    Dim x As Double, y As Double
+    x = w: y = h
+    
+    '// 绘制 Box 翅膀 Wing
+    Set crv = Application.CreateCurve(ActiveDocument)
+    Set sp = crv.CreateSubPath(0, 0)
+    sp.AppendLineSegment 0, 4
+    sp.AppendLineSegment 2, 6
+    sp.AppendLineSegment 6, y - 2.5
+    sp.AppendCurveSegment2 8.5, y, 6.2, y - 1.25, 7, y
+    sp.AppendLineSegment x - 2, y
+    sp.AppendLineSegment x - 2, 3
+    sp.AppendLineSegment x, 0
+    
+    sp.Closed = True
+    Set DrawWing = ActiveLayer.CreateCurve(crv)
+End Function
+
+Private Function DrawBond(ByVal w As Double, ByVal h As Double, ByVal move_x As Double, ByVal move_y As Double) As Shape
+    Dim sp As SubPath, crv As Curve
+    Dim x As Double, y As Double
+    x = w: y = h
+    
+    '// 绘制 Box 粘合边 Bond
+    Set crv = Application.CreateCurve(ActiveDocument)
+    Set sp = crv.CreateSubPath(0, 0)
+    sp.AppendLineSegment 0, y
+    sp.AppendLineSegment x, y - 5
+    sp.AppendLineSegment x, 5
+
+    sp.Closed = True
+    Set DrawBond = ActiveLayer.CreateCurve(crv)
+    DrawBond.Move move_x, move_y
+End Function
+
+
+Public Function Simple_box_one()
+  ActiveDocument.Unit = cdrMillimeter
+  l = 100: w = 50: h = 70: b = 15
+  boxL = 2 * l + 2 * w + b
+  boxH = h
+  l1x = w
+  l2x = w + l
+  l3x = 2 * w + l
+  l4x = 2 * (w + l)
+  
+  Set Rect = ActiveLayer.CreateRectangle(0, 0, boxL, boxH)
+  Set sl1 = DrawLine(l1x, 0, l1x, h)
+  Set sl2 = DrawLine(l2x, 0, l2x, h)
+  Set sl3 = DrawLine(l3x, 0, l3x, h)
+  Set sl4 = DrawLine(l4x, 0, l4x, h)
+End Function
+
+Public Function Simple_box_two()
+  ActiveDocument.Unit = cdrMillimeter
+  l = 100: w = 50: h = 70: b = 15
+  boxL = 2 * l + 2 * w + b: boxH = h
+  l1x = w: l2x = w + l: l3x = 2 * w + l: l4x = 2 * (w + l)
+  
+  Set mainRect = ActiveLayer.CreateRectangle(0, 0, boxL, boxH)
+  
+  Set topRect = ActiveLayer.CreateRectangle(0, 0, l, w)
+  topRect.Move l1x, h
+  Set bottomRect = ActiveLayer.CreateRectangle(0, 0, l, w)
+  bottomRect.Move l3x, -w
+  
+  Set sl1 = DrawLine(l1x, 0, l1x, h)
+  Set sl2 = DrawLine(l2x, 0, l2x, h)
+  Set sl3 = DrawLine(l3x, 0, l3x, h)
+  Set sl4 = DrawLine(l4x, 0, l4x, h)
+End Function
+
+
+Public Function Simple_3Deffect()
+  Dim sr As ShapeRange            '// 定义物件范围
+  Set sr = ActiveSelectionRange   '// 选择3个物件
+  
+  If sr.Count >= 3 Then
+  
+  '// 先上下再左右排序
+#If VBA7 Then
+    sr.Sort " @shape1.Top * 100 - @shape1.Left > @shape2.Top * 100 - @shape2.Left"
+#Else
+    Set ssr = X4_Sort_ShapeRange(sr, topWt_left)
+#End If
+
+    sr(1).Stretch 0.951, 0.525      ' 顶盖物件缩放修正和变形
+    sr(1).Skew 41.7, 7#
+      
+    sr(2).Stretch 0.951, 0.937      ' 正面物件缩放修正和变形
+    sr(2).Skew 0#, 7#
+    
+    sr(3).Stretch 0.468, 0.937      ' 侧面物件缩放修正和变形
+    sr(3).Skew 0#, -45#
+  End If
+End Function

+ 193 - 0
Form/Form/LinesForm.frm

@@ -0,0 +1,193 @@
+VERSION 5.00
+Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} LinesForm 
+   Caption         =   "LinesForm"
+   ClientHeight    =   2430
+   ClientLeft      =   45
+   ClientTop       =   390
+   ClientWidth     =   4680
+   OleObjectBlob   =   "LinesForm.frx":0000
+   StartUpPosition =   1  'CenterOwner
+End
+Attribute VB_Name = "LinesForm"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+
+'// This is free and unencumbered software released into the public domain.
+'// For more information, please refer to  https://github.com/hongwenjun
+
+'// 插件名称 VBA_UserForm
+Private Const TOOLNAME As String = "LYVBA"
+Private Const SECTION As String = "LinesForm"
+
+'// 用户窗口初始化
+Private Sub UserForm_Initialize()
+
+  With Me
+    .StartUpPosition = 0
+    .Left = Val(GetSetting(TOOLNAME, SECTION, "form_left", 900))
+    .Top = Val(GetSetting(TOOLNAME, SECTION, "form_top", 200))
+  End With
+
+End Sub
+
+
+'// 关闭窗口时保存窗口位置
+Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
+    saveFormPos True
+End Sub
+
+'// 保存窗口位置和加载窗口位置
+Sub saveFormPos(bDoSave As Boolean)
+  If bDoSave Then 'save position
+    SaveSetting TOOLNAME, SECTION, "form_left", Me.Left
+    SaveSetting TOOLNAME, SECTION, "form_top", Me.Top
+  End If
+End Sub
+
+Private Sub MyPen_Click()
+On Error GoTo ErrorHandler
+  API.BeginOpt
+  lines.Nodes_DrawLines
+ErrorHandler:
+  API.EndOpt
+End Sub
+
+
+'// 左键右键Ctrl三键控制
+Private Sub PenDrawLines_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
+On Error GoTo ErrorHandler
+  API.BeginOpt
+  If Button = 2 Then
+    lines.Draw_Multiple_Lines cdrAlignVCenter
+    
+  ElseIf Shift = fmCtrlMask Then
+    lines.Draw_Multiple_Lines cdrAlignHCenter
+  Else
+    lines.Draw_Multiple_Lines 0
+  End If
+ErrorHandler:
+  API.EndOpt
+End Sub
+
+
+'''////  傻瓜火车排列  ////'''
+Private Sub TOP_ALIGN_BT_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
+  If Button = 2 Then
+    Tools.Simple_Train_Arrangement 3#
+  ElseIf Shift = fmCtrlMask Then
+    Tools.Simple_Train_Arrangement 0#
+  Else
+    Tools.Simple_Train_Arrangement Set_Space_Width
+  End If
+End Sub
+
+'''////  傻瓜阶梯排列  ////'''
+Private Sub LEFT_ALIGN_BT_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
+  If Button = 2 Then
+    Tools.Simple_Ladder_Arrangement 3#
+  ElseIf Shift = fmCtrlMask Then
+    Tools.Simple_Ladder_Arrangement 0#
+  Else
+    Tools.Simple_Ladder_Arrangement Set_Space_Width
+  End If
+End Sub
+
+
+Private Sub MakeBox_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
+  On Error GoTo ErrorHandler
+  API.BeginOpt
+  
+  Dim size As Variant
+  size = input_box_lwh
+  l = size(0): w = size(1): h = size(2): b = size(3)
+  If b = 0 Then b = 15
+  
+  If Button = 2 Then
+    box.Simple_box_five l, w, h, b
+  ElseIf Shift = fmCtrlMask Then
+    box.Simple_box_four l, w, h, b
+  Else
+    box.Simple_box_three l, w, h, b
+  End If
+  
+ErrorHandler:
+  API.EndOpt
+End Sub
+
+Private Sub Cmd_3D_Click()
+  box.Simple_3Deffect
+End Sub
+
+
+'// 角度和旋转工具, 左键左转,右键右转
+Private Sub Rotate_Shapes_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
+  If Button = 2 Then   '// 右键的代码
+    Shapes_Rotate -90
+  ElseIf Shift = fmCtrlMask Then     '// 左键的代码
+    Shapes_Rotate 90
+  Else    '// CTRL的代码
+    Shapes_Rotate -45
+  End If
+End Sub
+
+'// 移动和再制,我们来制作三键控制,左键只移动,右键是反方向,按CTRL 是复制的
+Private Sub Move_Left_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
+  If Button = 2 Then   '// 右键的代码
+    move_shapes 100, 0
+  ElseIf Shift = fmCtrlMask Then     '// 左键的代码
+    move_shapes -100, 0
+  Else    '// CTRL的代码
+    Duplicate_shapes -100, 0
+  End If
+End Sub
+
+Private Sub Move_Up_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
+  If Button = 2 Then   '// 右键的代码
+    move_shapes 0, -100
+  ElseIf Shift = fmCtrlMask Then     '// 左键的代码
+    move_shapes 0, 100
+  Else    '// CTRL的代码
+    Duplicate_shapes 0, 100
+  End If
+End Sub
+
+'// 测量标尺和水平尺
+Private Sub Ruler_Measuring_BT_Click()
+  '// 角度转平
+  Angle_to_Horizon
+End Sub
+
+'// 选择的物件平均距离
+Private Sub Average_Distance_BT_Click()
+  Average_Distance
+End Sub
+
+Private Sub chkAutoDistribute_Click()
+  AutoDistribute_Key = chkAutoDistribute.Value
+End Sub
+
+'// 镜像工具
+Private Sub MirrorLine_Click()
+  Mirror_ByGuide
+End Sub
+
+'// 平行线工具 CTRL 键设置距离
+Private Sub ParallelLines_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
+  Dim sp As Double
+  text = GlobalUserData("SpaceWidth", 1)
+  sp = Val(text)
+  If Button = 2 Then   '// 右键的代码
+    Create_Parallel_Lines -sp
+  ElseIf Shift = fmCtrlMask Then     '// 左键的代码
+    Create_Parallel_Lines sp
+  Else    '// CTRL的代码
+    Create_Parallel_Lines Set_Space_Width
+  End If
+End Sub
+
+'// 标记镜像参考线
+Private Sub Set_Guide_Click()
+  Set_Guides_Name
+End Sub

BIN
Form/Form/LinesForm.frx


+ 84 - 0
Form/Form/ThisMacroStorage.cls

@@ -0,0 +1,84 @@
+VERSION 1.0 CLASS
+BEGIN
+  MultiUse = -1  'True
+END
+Attribute VB_Name = "ThisMacroStorage"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = True
+Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
+Public sreg As New ShapeRange
+
+Private Sub GlobalMacroStorage_SelectionChange()
+On Error GoTo ErrorHandler
+  Dim n As Long
+  Dim nr As NodeRange
+  Dim sh As Shape
+  
+  If ActiveSelection.Shapes.Count > 0 Then
+    n = 0
+    For Each sh In ActiveSelection.Shapes
+      If sh.Type = cdrCurveShape Then
+        Set nr = sh.Curve.Selection
+        n = n + nr.Count
+      End If
+    Next sh
+
+    If n > 2 Then
+        LinesForm.Caption = "Nodes: " & n
+    ElseIf ActiveSelection.Shapes.Count > 1 Then
+       LinesForm.Caption = "Select: " & ActiveSelection.Shapes.Count
+      End If
+  Else
+      LinesForm.Caption = "LinesForm By Lanya"
+  End If
+
+  If ActiveSelection.Shapes.Count = 1 Then
+    '// 检测Ctrl:Alt:Shift键状态 17-18-16
+    
+    If scankey() = 17 Then
+      If sreg.Exists(ActiveShape) Then sreg.Remove sreg.IndexOf(ActiveShape)
+      sreg.Add ActiveShape
+      LinesForm.Caption = "ActiveShape add SREG! Count:" & sreg.Count
+    End If
+    
+    If scankey() = 18 Then
+      sreg.RemoveAll
+      LinesForm.Caption = "SREG is Removed!"
+    End If
+    
+    If scankey() = 16 Then
+      sreg.CreateSelection
+    End If
+  
+  End If
+
+  If ActiveSelection.Shapes.Count > 2 And AutoDistribute_Key Then
+    Dim sr As ShapeRange
+    Set sr = ActiveSelectionRange
+    sr.Sort "@shape1.left<@shape2.left"
+    If first_StaticID <> sr.FirstShape.StaticID Then
+      Average_Distance
+    End If
+  End If
+ErrorHandler:
+
+End Sub
+
+Private Function scankey() As Long
+    Dim ctrlPressed As Boolean
+    Dim shiftPressed As Boolean
+    Dim altPressed As Boolean
+    
+    
+    ' 检测Ctrl键的状态  ' 检测Shift键的状态   ' 检测Alt键的状态
+    ctrlPressed = GetAsyncKeyState(17) And &H8000
+    shiftPressed = GetAsyncKeyState(16) And &H8000
+    altPressed = GetAsyncKeyState(18) And &H8000
+    
+    scankey = 0
+    If altPressed Then scankey = 18
+    If shiftPressed Then scankey = 16
+    If ctrlPressed Then scankey = 17
+End Function

+ 142 - 142
MirrorParalleHorizon.bas

@@ -1,142 +1,142 @@
-Attribute VB_Name = "MirrorParalleHorizon"
-'// 两个端点的坐标,为(x1,y1)和(x2,y2) 那么其角度a的tan值: tana=(y2-y1)/(x2-x1)
-'// 所以计算arctan(y2-y1)/(x2-x1), 得到其角度值a
-'// VB中用atn(), 返回值是弧度,需要 乘以 PI /180
-Private Function lineangle(x1, y1, x2, y2) As Double
-    pi = 4 * VBA.Atn(1)    '// 计算圆周率
-    If x2 = x1 Then
-      lineangle = 90: Exit Function
-    End If
-    lineangle = VBA.Atn((y2 - y1) / (x2 - x1)) / pi * 180
-  End Function
-  
-  '// 角度转平
-  Public Function Angle_to_Horizon()
-    On Error GoTo ErrorHandler
-    API.BeginOpt
-    Set sr = ActiveSelectionRange
-    Set nr = sr.LastShape.DisplayCurve.Nodes.All
-  
-    If nr.Count = 2 Then
-      x1 = nr.FirstNode.PositionX: y1 = nr.FirstNode.PositionY
-      x2 = nr.LastNode.PositionX: y2 = nr.LastNode.PositionY
-      a = lineangle(x1, y1, x2, y2): sr.Rotate -a
-      sr.LastShape.Delete   '// 删除参考线
-    End If
-ErrorHandler:
-    API.EndOpt
-  End Function
-
-'// 自动旋转角度
-Public Function Auto_Rotation_Angle()
-  On Error GoTo ErrorHandler
-  API.BeginOpt
-  
-'  ActiveDocument.ReferencePoint = cdrCenter
-  Set sr = ActiveSelectionRange
-  Set nr = sr.LastShape.DisplayCurve.Nodes.All
-
-  If nr.Count = 2 Then
-    x1 = nr.FirstNode.PositionX: y1 = nr.FirstNode.PositionY
-    x2 = nr.LastNode.PositionX: y2 = nr.LastNode.PositionY
-    a = lineangle(x1, y1, x2, y2): sr.Rotate 90 + a
-    sr.LastShape.Delete   '// 删除参考线
-  End If
-ErrorHandler:
-  API.EndOpt
-End Function
-
-'// 交换对象
-Public Function Exchange_Object()
-  Set sr = ActiveSelectionRange
-  If sr.Count = 2 Then
-    x = sr.LastShape.CenterX: y = sr.LastShape.CenterY
-    sr.LastShape.CenterX = sr.FirstShape.CenterX: sr.LastShape.CenterY = sr.FirstShape.CenterY
-    sr.FirstShape.CenterX = x: sr.FirstShape.CenterY = y
-  End If
-End Function
-
-'// 标记镜像参考线
-Public Function Set_Guides_Name()
-  On Error GoTo ErrorHandler
-  API.BeginOpt
-  Dim sr As ShapeRange, s As Shape
-  Set sr = ActiveSelectionRange
-  
-  For Each s In sr
-    s.name = "MirrorGuides"
-  Next s
-
-'// 感谢李总捐赠,定置透明度70%
-  With ActiveSelection.Transparency
-    .ApplyUniformTransparency 70
- '   .AppliedTo = cdrApplyToFillAndOutline
- '   .MergeMode = cdrMergeNormal
-  End With
-  
-ErrorHandler:
-  API.EndOpt
-End Function
-
-'// 参考线镜像
-Public Function Mirror_ByGuide()
-  On Error GoTo ErrorHandler
-  API.BeginOpt
-  Dim sr As ShapeRange, gds As ShapeRange
-  Set sr = ActiveSelectionRange
-  Set gds = sr.Shapes.FindShapes(Query:="@name ='MirrorGuides'")
-  
-  If gds.Count > 0 Then
- '//   sr.RemoveRange gds
-    Set nr = gds(1).DisplayCurve.Nodes.All
-  Else
-    Set nr = sr.LastShape.DisplayCurve.Nodes.All
- '//   sr.Remove sr.Count
-  End If
-  
-  If nr.Count >= 2 Then
-    byshape = False
-    x1 = nr.FirstNode.PositionX: y1 = nr.FirstNode.PositionY
-    x2 = nr.LastNode.PositionX: y2 = nr.LastNode.PositionY
-    a = lineangle(x1, y1, x2, y2)  '// 参考线和水平的夹角 a
-    
-    ang = 90 - a    '// 镜像的旋转角度
-   Set s = sr.Group
-      With s
-        Set s_copy = .Duplicate   '// 复制物件保留,然后按 x1,y1 点 旋转
-        
-        .RotationCenterX = x1
-        .RotationCenterY = y1
-        .Rotate ang
-        If Not byshape Then
-            lx = .LeftX
-            .Stretch -1#, 1#    '// 通过拉伸完成镜像
-            .LeftX = lx
-            .Move (x1 - .LeftX) * 2 - .SizeWidth, 0
-            .RotationCenterX = x1     '// 之前因为镜像,旋转中心点反了,重置回来
-            .RotationCenterY = y1
-            .Rotate -ang
-        End If
-        .RotationCenterX = .CenterX   '// 重置回旋转中心点为物件中心
-        .RotationCenterY = .CenterY
-        .Ungroup
-        s_copy.Ungroup
-      End With
-  End If
-
-ErrorHandler:
-  API.EndOpt
-End Function
-
-'// 物件建立平行线
-Public Function Create_Parallel_Lines(space As Double)
-  On Error GoTo ErrorHandler
-  API.BeginOpt
-  
-  Dim sr As ShapeRange
-  Set sr = ActiveSelectionRange
-  sr.CreateParallelCurves 1, space
-
-ErrorHandler:
-  API.EndOpt
-End Function
+Attribute VB_Name = "MirrorParalleHorizon"
+'// 两个端点的坐标,为(x1,y1)和(x2,y2) 那么其角度a的tan值: tana=(y2-y1)/(x2-x1)
+'// 所以计算arctan(y2-y1)/(x2-x1), 得到其角度值a
+'// VB中用atn(), 返回值是弧度,需要 乘以 PI /180
+Private Function lineangle(x1, y1, x2, y2) As Double
+    pi = 4 * VBA.Atn(1)    '// 计算圆周率
+    If x2 = x1 Then
+      lineangle = 90: Exit Function
+    End If
+    lineangle = VBA.Atn((y2 - y1) / (x2 - x1)) / pi * 180
+  End Function
+  
+  '// 角度转平
+  Public Function Angle_to_Horizon()
+    On Error GoTo ErrorHandler
+    API.BeginOpt
+    Set sr = ActiveSelectionRange
+    Set nr = sr.LastShape.DisplayCurve.Nodes.All
+  
+    If nr.Count = 2 Then
+      x1 = nr.FirstNode.PositionX: y1 = nr.FirstNode.PositionY
+      x2 = nr.LastNode.PositionX: y2 = nr.LastNode.PositionY
+      a = lineangle(x1, y1, x2, y2): sr.Rotate -a
+      sr.LastShape.Delete   '// 删除参考线
+    End If
+ErrorHandler:
+    API.EndOpt
+  End Function
+
+'// 自动旋转角度
+Public Function Auto_Rotation_Angle()
+  On Error GoTo ErrorHandler
+  API.BeginOpt
+  
+'  ActiveDocument.ReferencePoint = cdrCenter
+  Set sr = ActiveSelectionRange
+  Set nr = sr.LastShape.DisplayCurve.Nodes.All
+
+  If nr.Count = 2 Then
+    x1 = nr.FirstNode.PositionX: y1 = nr.FirstNode.PositionY
+    x2 = nr.LastNode.PositionX: y2 = nr.LastNode.PositionY
+    a = lineangle(x1, y1, x2, y2): sr.Rotate 90 + a
+    sr.LastShape.Delete   '// 删除参考线
+  End If
+ErrorHandler:
+  API.EndOpt
+End Function
+
+'// 交换对象
+Public Function Exchange_Object()
+  Set sr = ActiveSelectionRange
+  If sr.Count = 2 Then
+    x = sr.LastShape.CenterX: y = sr.LastShape.CenterY
+    sr.LastShape.CenterX = sr.FirstShape.CenterX: sr.LastShape.CenterY = sr.FirstShape.CenterY
+    sr.FirstShape.CenterX = x: sr.FirstShape.CenterY = y
+  End If
+End Function
+
+'// 标记镜像参考线
+Public Function Set_Guides_Name()
+  On Error GoTo ErrorHandler
+  API.BeginOpt
+  Dim sr As ShapeRange, s As Shape
+  Set sr = ActiveSelectionRange
+  
+  For Each s In sr
+    s.name = "MirrorGuides"
+  Next s
+
+'// 感谢李总捐赠,定置透明度70%
+  With ActiveSelection.Transparency
+    .ApplyUniformTransparency 70
+ '   .AppliedTo = cdrApplyToFillAndOutline
+ '   .MergeMode = cdrMergeNormal
+  End With
+  
+ErrorHandler:
+  API.EndOpt
+End Function
+
+'// 参考线镜像
+Public Function Mirror_ByGuide()
+  On Error GoTo ErrorHandler
+  API.BeginOpt
+  Dim sr As ShapeRange, gds As ShapeRange
+  Set sr = ActiveSelectionRange
+  Set gds = sr.Shapes.FindShapes(Query:="@name ='MirrorGuides'")
+  
+  If gds.Count > 0 Then
+ '//   sr.RemoveRange gds
+    Set nr = gds(1).DisplayCurve.Nodes.All
+  Else
+    Set nr = sr.LastShape.DisplayCurve.Nodes.All
+ '//   sr.Remove sr.Count
+  End If
+  
+  If nr.Count >= 2 Then
+    byshape = False
+    x1 = nr.FirstNode.PositionX: y1 = nr.FirstNode.PositionY
+    x2 = nr.LastNode.PositionX: y2 = nr.LastNode.PositionY
+    a = lineangle(x1, y1, x2, y2)  '// 参考线和水平的夹角 a
+    
+    ang = 90 - a    '// 镜像的旋转角度
+   Set s = sr.Group
+      With s
+        Set s_copy = .Duplicate   '// 复制物件保留,然后按 x1,y1 点 旋转
+        
+        .RotationCenterX = x1
+        .RotationCenterY = y1
+        .Rotate ang
+        If Not byshape Then
+            lx = .LeftX
+            .Stretch -1#, 1#    '// 通过拉伸完成镜像
+            .LeftX = lx
+            .Move (x1 - .LeftX) * 2 - .SizeWidth, 0
+            .RotationCenterX = x1     '// 之前因为镜像,旋转中心点反了,重置回来
+            .RotationCenterY = y1
+            .Rotate -ang
+        End If
+        .RotationCenterX = .CenterX   '// 重置回旋转中心点为物件中心
+        .RotationCenterY = .CenterY
+        .Ungroup
+        s_copy.Ungroup
+      End With
+  End If
+
+ErrorHandler:
+  API.EndOpt
+End Function
+
+'// 物件建立平行线
+Public Function Create_Parallel_Lines(space As Double)
+  On Error GoTo ErrorHandler
+  API.BeginOpt
+  
+  Dim sr As ShapeRange
+  Set sr = ActiveSelectionRange
+  sr.CreateParallelCurves 1, space
+
+ErrorHandler:
+  API.EndOpt
+End Function

+ 42 - 42
RotateMoveDuplicate.bas

@@ -1,42 +1,42 @@
-Attribute VB_Name = "RotateMoveDuplicate"
-Public Function move_shapes(x As Double, y As Double)
-  On Error GoTo ErrorHandler
-  API.BeginOpt
-  
-  Dim sr As ShapeRange     '// 使用 ShapeRange 可以多个物件一起操作
-  Set sr = ActiveSelectionRange   '// 选择物件队列使用 ActiveSelectionRange
-  sr.Move x, y             '// 默认单位是 英寸 所以移动太远了
-  
-ErrorHandler:
-  API.EndOpt
-End Function
-
-Public Function Duplicate_shapes(x As Double, y As Double)
-  On Error GoTo ErrorHandler
-  API.BeginOpt
-  
-  Dim sr As ShapeRange
-  Dim sr_copy As ShapeRange
-  Set sr = ActiveSelectionRange
-  Set sr_copy = sr.Duplicate(x, y)    '// Duplicate 是再制,如果前面有 = 赋值,就要加上 (x,y)
-  sr_copy.CreateSelection
-
-ErrorHandler:
-  API.EndOpt
-End Function
-
-'// 批量旋转角度
-Public Function Shapes_Rotate(angle As Double)
-  On Error GoTo ErrorHandler
-  API.BeginOpt
-  
-  ActiveDocument.ReferencePoint = cdrCenter
-  Dim sr As ShapeRange
-  Set sr = ActiveSelectionRange
-  For Each s In sr
-    s.Rotate angle
-  Next
-  
-ErrorHandler:
-  API.EndOpt
-End Function
+Attribute VB_Name = "RotateMoveDuplicate"
+Public Function move_shapes(x As Double, y As Double)
+  On Error GoTo ErrorHandler
+  API.BeginOpt
+  
+  Dim sr As ShapeRange     '// 使用 ShapeRange 可以多个物件一起操作
+  Set sr = ActiveSelectionRange   '// 选择物件队列使用 ActiveSelectionRange
+  sr.Move x, y             '// 默认单位是 英寸 所以移动太远了
+  
+ErrorHandler:
+  API.EndOpt
+End Function
+
+Public Function Duplicate_shapes(x As Double, y As Double)
+  On Error GoTo ErrorHandler
+  API.BeginOpt
+  
+  Dim sr As ShapeRange
+  Dim sr_copy As ShapeRange
+  Set sr = ActiveSelectionRange
+  Set sr_copy = sr.Duplicate(x, y)    '// Duplicate 是再制,如果前面有 = 赋值,就要加上 (x,y)
+  sr_copy.CreateSelection
+
+ErrorHandler:
+  API.EndOpt
+End Function
+
+'// 批量旋转角度
+Public Function Shapes_Rotate(angle As Double)
+  On Error GoTo ErrorHandler
+  API.BeginOpt
+  
+  ActiveDocument.ReferencePoint = cdrCenter
+  Dim sr As ShapeRange
+  Set sr = ActiveSelectionRange
+  For Each s In sr
+    s.Rotate angle
+  Next
+  
+ErrorHandler:
+  API.EndOpt
+End Function

+ 56 - 56
Tools.bas

@@ -1,56 +1,56 @@
-Attribute VB_Name = "Tools"
-'// This is free and unencumbered software released into the public domain.
-'// For more information, please refer to  https://github.com/hongwenjun
-
-'// 简易火车排列
-Public Function Simple_Train_Arrangement(Space_Width As Double)
-  API.BeginOpt
-  Dim ssr As ShapeRange, s As Shape
-  Dim cnt As Integer
-  Set ssr = ActiveSelectionRange
-  cnt = 1
-
-#If VBA7 Then
-'  ssr.sort " @shape1.top>@shape2.top"
-  ssr.Sort " @shape1.left<@shape2.left"
-#Else
-' X4 不支持 ShapeRange.sort  使用 lyvba32.dll 算法库排序   2023.07.08
-  Set ssr = X4_Sort_ShapeRange(ssr, stlx)
-#End If
-
-  ActiveDocument.ReferencePoint = cdrTopLeft
-  For Each s In ssr
-    '// 底对齐 If cnt > 1 Then s.SetPosition ssr(cnt - 1).RightX, ssr(cnt - 1).BottomY
-    '// 改成顶对齐 2022-08-10
-    ActiveDocument.ReferencePoint = cdrTopLeft + cdrBottomTop
-    If cnt > 1 Then s.SetPosition ssr(cnt - 1).RightX + Space_Width, ssr(cnt - 1).topY
-    cnt = cnt + 1
-  Next s
-
-  API.EndOpt
-End Function
-
-'// 简易阶梯排列
-Public Function Simple_Ladder_Arrangement(Space_Width As Double)
-  API.BeginOpt
-  Dim ssr As ShapeRange, s As Shape
-  Dim cnt As Integer
-  Set ssr = ActiveSelectionRange
-  cnt = 1
-
-#If VBA7 Then
-  ssr.Sort " @shape1.top>@shape2.top"
-#Else
-' X4 不支持 ShapeRange.sort  使用 lyvba32.dll 算法库排序   2023.07.08
-  Set ssr = X4_Sort_ShapeRange(ssr, stty).ReverseRange
-#End If
-
-
-  ActiveDocument.ReferencePoint = cdrTopLeft
-  For Each s In ssr
-    If cnt > 1 Then s.SetPosition ssr(cnt - 1).LeftX, ssr(cnt - 1).BottomY - Space_Width
-    cnt = cnt + 1
-  Next s
-
-  API.EndOpt
-End Function
+Attribute VB_Name = "Tools"
+'// This is free and unencumbered software released into the public domain.
+'// For more information, please refer to  https://github.com/hongwenjun
+
+'// 简易火车排列
+Public Function Simple_Train_Arrangement(Space_Width As Double)
+  API.BeginOpt
+  Dim ssr As ShapeRange, s As Shape
+  Dim cnt As Integer
+  Set ssr = ActiveSelectionRange
+  cnt = 1
+
+#If VBA7 Then
+'  ssr.sort " @shape1.top>@shape2.top"
+  ssr.Sort " @shape1.left<@shape2.left"
+#Else
+' X4 不支持 ShapeRange.sort  使用 lyvba32.dll 算法库排序   2023.07.08
+  Set ssr = X4_Sort_ShapeRange(ssr, stlx)
+#End If
+
+  ActiveDocument.ReferencePoint = cdrTopLeft
+  For Each s In ssr
+    '// 底对齐 If cnt > 1 Then s.SetPosition ssr(cnt - 1).RightX, ssr(cnt - 1).BottomY
+    '// 改成顶对齐 2022-08-10
+    ActiveDocument.ReferencePoint = cdrTopLeft + cdrBottomTop
+    If cnt > 1 Then s.SetPosition ssr(cnt - 1).RightX + Space_Width, ssr(cnt - 1).TopY
+    cnt = cnt + 1
+  Next s
+
+  API.EndOpt
+End Function
+
+'// 简易阶梯排列
+Public Function Simple_Ladder_Arrangement(Space_Width As Double)
+  API.BeginOpt
+  Dim ssr As ShapeRange, s As Shape
+  Dim cnt As Integer
+  Set ssr = ActiveSelectionRange
+  cnt = 1
+
+#If VBA7 Then
+  ssr.Sort " @shape1.top>@shape2.top"
+#Else
+' X4 不支持 ShapeRange.sort  使用 lyvba32.dll 算法库排序   2023.07.08
+  Set ssr = X4_Sort_ShapeRange(ssr, stty).ReverseRange
+#End If
+
+
+  ActiveDocument.ReferencePoint = cdrTopLeft
+  For Each s In ssr
+    If cnt > 1 Then s.SetPosition ssr(cnt - 1).LeftX, ssr(cnt - 1).BottomY - Space_Width
+    cnt = cnt + 1
+  Next s
+
+  API.EndOpt
+End Function

+ 99 - 99
lines.bas

@@ -1,99 +1,99 @@
-Attribute VB_Name = "lines"
-'// This is free and unencumbered software released into the public domain.
-'// For more information, please refer to  https://github.com/hongwenjun
-
-Sub start()
-  LinesForm.Show 0
-End Sub
-
-Public Function Nodes_DrawLines()
-  Dim sr As ShapeRange, sr_tmp As New ShapeRange, sr_lines As New ShapeRange
-  Dim s As Shape, sh As Shape
-  Dim nr As NodeRange
-  Set sr = ActiveSelectionRange
-  If sr.Count = 0 Then Exit Function
-  
-  For Each sh In sr
-    Set nr = sh.Curve.Selection
-    If nr.Count > 0 Then
-      For Each n In nr
-        Set s = ActiveLayer.CreateEllipse2(n.PositionX, n.PositionY, 0.5, 0.5)
-        sr_tmp.Add s
-      Next n
-    End If
-  Next sh
-  
-  '// 没有选择节点的情况,使用物件中心划线
-  If sr_tmp.Count < 2 And sr.Count > 1 Then
-    Set Line = DrawLine(sr(1), sr(2))
-    sr_lines.Add Line
-  End If
-
-#If VBA7 Then
-    sr_tmp.Sort "@shape1.left < @shape2.left"
-#Else
-    Set sr_tmp = X4_Sort_ShapeRange(sr_tmp, stlx)
-#End If
-
-  '// 使用 Count 遍历 shaperange 这种情况方便点
-  For i = 1 To sr_tmp.Count - 1
-    Set Line = DrawLine(sr_tmp(i), sr_tmp(i + 1))
-    sr_lines.Add Line
-  Next
-  
-  sr_tmp.Delete
-  sr_lines.CreateSelection
-End Function
-
-Public Function Draw_Multiple_Lines(hv As cdrAlignType)
-  Dim sr As ShapeRange, sr_lines As New ShapeRange
-  Set sr = ActiveSelectionRange
-  
-  If sr.Count < 2 Then Exit Function
-  
-#If VBA7 Then
-  If hv = cdrAlignVCenter Then
-    '// 从左到右排序
-    sr.Sort "@shape1.left < @shape2.left"
-  ElseIf hv = cdrAlignHCenter Then
-    '// 从上到下排序
-    sr.Sort "@shape1.top < @shape2.top"
-  End If
-#Else
-  '// X4_Sort_ShapeRange for CorelDRAW X4
-  If hv = cdrAlignVCenter Then
-    Set sr = X4_Sort_ShapeRange(sr, stlx)
-  ElseIf hv = cdrAlignHCenter Then
-    Set sr = X4_Sort_ShapeRange(sr, stty)
-  End If
- 
-#End If
-
-  For i = 1 To sr.Count - 1 Step 2
-    Set Line = DrawLine(sr(i), sr(i + 1))
-    sr_lines.Add Line
-  Next
- 
-  sr_lines.CreateSelection
-End Function
-
-Public Function FirtLineTool()
-  Dim sr As ShapeRange
-  Set sr = ActiveSelectionRange
-  If sr.Count > 1 Then
-    Set Line = DrawLine(sr(1), sr(2))
-  End If
-End Function
-
-Private Function DrawLine(ByVal s1 As Shape, ByVal s2 As Shape) As Shape
-'// 创建线段方法在图层上的指定位置创建由单个线段组成的曲线。
- Set DrawLine = ActiveLayer.CreateLineSegment(s1.CenterX, s1.CenterY, s2.CenterX, s2.CenterY)
-
-End Function
-
-Private Sub Test()
-  ActiveDocument.Unit = cdrMillimeter
-  Set Rect = ActiveLayer.CreateRectangle(0, 0, 30, 30)
-  Set ell = ActiveLayer.CreateEllipse2(50, 50, 10, 10)
-  Set Line = DrawLine(Rect, ell)
-End Sub
+Attribute VB_Name = "lines"
+'// This is free and unencumbered software released into the public domain.
+'// For more information, please refer to  https://github.com/hongwenjun
+
+Sub start()
+  LinesForm.Show 0
+End Sub
+
+Public Function Nodes_DrawLines()
+  Dim sr As ShapeRange, sr_tmp As New ShapeRange, sr_lines As New ShapeRange
+  Dim s As Shape, sh As Shape
+  Dim nr As NodeRange
+  Set sr = ActiveSelectionRange
+  If sr.Count = 0 Then Exit Function
+  
+  For Each sh In sr
+    Set nr = sh.Curve.Selection
+    If nr.Count > 0 Then
+      For Each n In nr
+        Set s = ActiveLayer.CreateEllipse2(n.PositionX, n.PositionY, 0.5, 0.5)
+        sr_tmp.Add s
+      Next n
+    End If
+  Next sh
+  
+  '// 没有选择节点的情况,使用物件中心划线
+  If sr_tmp.Count < 2 And sr.Count > 1 Then
+    Set Line = DrawLine(sr(1), sr(2))
+    sr_lines.Add Line
+  End If
+
+#If VBA7 Then
+    sr_tmp.Sort "@shape1.left < @shape2.left"
+#Else
+    Set sr_tmp = X4_Sort_ShapeRange(sr_tmp, stlx)
+#End If
+
+  '// 使用 Count 遍历 shaperange 这种情况方便点
+  For i = 1 To sr_tmp.Count - 1
+    Set Line = DrawLine(sr_tmp(i), sr_tmp(i + 1))
+    sr_lines.Add Line
+  Next
+  
+  sr_tmp.Delete
+  sr_lines.CreateSelection
+End Function
+
+Public Function Draw_Multiple_Lines(hv As cdrAlignType)
+  Dim sr As ShapeRange, sr_lines As New ShapeRange
+  Set sr = ActiveSelectionRange
+  
+  If sr.Count < 2 Then Exit Function
+  
+#If VBA7 Then
+  If hv = cdrAlignVCenter Then
+    '// 从左到右排序
+    sr.Sort "@shape1.left < @shape2.left"
+  ElseIf hv = cdrAlignHCenter Then
+    '// 从上到下排序
+    sr.Sort "@shape1.top < @shape2.top"
+  End If
+#Else
+  '// X4_Sort_ShapeRange for CorelDRAW X4
+  If hv = cdrAlignVCenter Then
+    Set sr = X4_Sort_ShapeRange(sr, stlx)
+  ElseIf hv = cdrAlignHCenter Then
+    Set sr = X4_Sort_ShapeRange(sr, stty)
+  End If
+ 
+#End If
+
+  For i = 1 To sr.Count - 1 Step 2
+    Set Line = DrawLine(sr(i), sr(i + 1))
+    sr_lines.Add Line
+  Next
+ 
+  sr_lines.CreateSelection
+End Function
+
+Public Function FirtLineTool()
+  Dim sr As ShapeRange
+  Set sr = ActiveSelectionRange
+  If sr.Count > 1 Then
+    Set Line = DrawLine(sr(1), sr(2))
+  End If
+End Function
+
+Private Function DrawLine(ByVal s1 As Shape, ByVal s2 As Shape) As Shape
+'// 创建线段方法在图层上的指定位置创建由单个线段组成的曲线。
+ Set DrawLine = ActiveLayer.CreateLineSegment(s1.CenterX, s1.CenterY, s2.CenterX, s2.CenterY)
+
+End Function
+
+Private Sub Test()
+  ActiveDocument.Unit = cdrMillimeter
+  Set Rect = ActiveLayer.CreateRectangle(0, 0, 30, 30)
+  Set ell = ActiveLayer.CreateEllipse2(50, 50, 10, 10)
+  Set Line = DrawLine(Rect, ell)
+End Sub