Chuyển đến nội dung
Diễn đàn CADViet
Đăng nhập để thực hiện theo  
ngokiet

Lập trình AutoCad.net cho Lisp?

Các bài được khuyến nghị

Viết Lisp cho AutoCad nó cũng có giới hạn nhất định. Một số hàm lisp không hỗ trợ tốt Tiếng Việt unicode. Nhất là các hàm visual

Sau khi mày mò thừ visual studio để lập trình cho autoCad thì mình thấy cũng có thể viết vb.net để lập trình thêm 1 số hàm có thể sử dụng cho lisp.

Mình viết ở đây một số hàm mình viết có thể sử dụng cho lisp.

- Về cách đặt các thông số cho visual studio để lập trình được cho autoCad thì nhiều bài viết đã đề cập. Mình không nhắc lại ở đây nữa.

1. Hàm kstrcase 

   <LispFunction("kstrcase")> Public Function kstrcase(ss As ResultBuffer) As Object
        If ss(1).Typecode = 5019 Then
            Return LCase(ss(0).value)
        Else
            Return UCase(ss(0).value)
        End If
    End Function

Sừ dụng trong lisp : (kstrcase str code)

srt: string, code là T or nil

Nó trả về string là chữ hoa nếu Code là T và chữ thường nếu code là nil

Ví dụ:  (kstrcase "Cad việt" T) -> "CAD VIỆT"

Mình viết hàm này do nó hỗ trợ tốt unicode (Hàm chuẩn của lisp không hỗ trợ unicode)

2.Hàm về file

	<LispFunction("checkfileexist")> Public Function cfexist(st As ResultBuffer) As Object
        If My.Computer.FileSystem.FileExists(st(0).value) Then
            Return New TypedValue(5021)
        Else
            Return New TypedValue(5019)
        End If
    End Function
    <LispFunction("checkpathexist")> Public Function cpexist(st As ResultBuffer) As Object
        If My.Computer.FileSystem.DirectoryExists(st(0).value) Then
            Return New TypedValue(5021)
        Else
            Return New TypedValue(5019)
        End If
    End Function
    <LispFunction("Listfileinpath")> Public Function listfile(st As ResultBuffer) As Object
        If My.Computer.FileSystem.DirectoryExists(st(0).value) Then
            Dim rr As ResultBuffer = New ResultBuffer
            For Each s As String In System.IO.Directory.GetFiles(st(0).value)
                rr.Add(New TypedValue(5005, s))
            Next
            Return rr
        Else
            Return New TypedValue(5019)
        End If
    End Function
    <LispFunction("getpath")> Public Function Getpath1(st As ResultBuffer) As Object
        Return System.IO.Path.GetDirectoryName(st(0).value)
    End Function
    <LispFunction("getfilename")> Public Function Getfilename1(st As ResultBuffer) As Object
        Return System.IO.Path.GetFileName(st(0).value)
    End Function
    <LispFunction("getextfile")> Public Function getextfile1(st As ResultBuffer) As Object
        Return System.IO.Path.GetExtension(st(0).value)
    End Function

Ở đây mình có 6 hàm thường sử dụng. Hỗ trợ path và filename unicode

(checkfileexist filename) : Kiểm tra file có tồn tại hay không?  -vd  (checkfileexist "D:\\bai tap\\abc.dwg")

(checkpathexit path) : Kiểm tra đương dẫn có tồn tại hay không? 

(listfilepath path): Trả về danh sách file trong đường dẫn

(getpath filename): Trả về đường dẫn của filename

(getfilename filename): Trả về tên file

(getextfile filename): Trả về phần mở rộng của file

3. Hàm về open/save file text

	<LispFunction("opentext")> Public Function opentext(st As ResultBuffer) As Object
        Dim filen As String = st(0).value
        If My.Computer.FileSystem.FileExists(filen) Then
            filen = My.Computer.FileSystem.ReadAllText(filen)
            Dim s1() As String = System.Text.RegularExpressions.Regex.Split(filen, vbCrLf)
            Dim rr As ResultBuffer = New ResultBuffer
            For Each S2 In s1
                rr.Add(New TypedValue(5005, S2))
            Next
            Return rr
        Else
            Return New TypedValue(5019)
        End If
    End Function
    <LispFunction("savetext")> Public Function savetext(st As ResultBuffer) As Object
        Dim ss() As TypedValue = st.AsArray
        Dim s1 As String = ""
        For i As Long = 1 To ss.Count - 1
            Select Case ss(i).TypeCode
                Case 5001 To 5005
                    s1 = s1 & ss(i).Value & vbCrLf
                Case 5002
                    s1 = s1 & ss(i).Value.x.ToString & "," & ss(i).Value.y.ToString & vbCrLf
                Case 5009
                    s1 = s1 & ss(i).Value.x.ToString & "," & ss(i).Value.y.ToString & "," & ss(i).Value.z.ToString & vbCrLf
            End Select
        Next
        Try
            My.Computer.FileSystem.WriteAllText(st(0).value, s1, False)
        Catch ex As Exception
            Return New TypedValue(5019)
            Exit Function
        End Try
        Return New TypedValue(5021)
    End Function

Ở đây có 2 hàm hỗ trợ tên file unicode

(opentext filename) :  Đọc dữ liệu từ filename.  {Hỗ trợ sẵn file unicode, utf8, ansi

  Trả về kết quả là 1 list of string. Mỗi dòng là 1 string.

(savetext filename value):  Ghi dữ liệu lên filename

 Value là 1 list string. Trả về kết quả là T nếu ghi thành công; nil thì thất bại.

Hàm này ghi file theo chuẩn utf8.

 

 

Với các ví dụ trên thì các bạn có thể viết riêng function lisp cho mình dùng. Mình up lên đây file dll cho các bạn viết lisp có thể sử dụng luôn.

Cách sừ dụng

Dùng lệnh Cad là netload chọn file vd2.dll hay dùng lệnh lisp : (command "_netload" "vd2.dll")

Bạn có thể tham khảo thêm cách load file dll của autocad ( Thêm vào trust file)

 

Trong vd2 mình có thêm 1 hàm getfileds Để chọn 1 hay nhiều file 1 lúc : Gần giống hàm getfield của lisp

Cách sử dụng

 (getfileds "Chọn file cần" "D:\\Cadviet\\dtd.txt" "File văn bản |*.txt;*.cvs|Tất cả file |*.*" 3)

"Chọn file cần" : Tên dialog chọn file

"D:\\Cadviet\\dtd.txt" : Tên file mặc định

"File văn bản |*.txt;*.cvs|Tất cả file |*.*" : Các kiểu bộ lọc - Cấu trúc theo chuẩn của window

3: code bit 1:  Multiselect  bit 2: Check file exist.

 

Có thắc mắc gì thì cứ hỏi ở đây. Mình sẽ trả lời.

Nếu sừ dụng được thì cho mình 1 like để mình biết.

 

Thanks. Chúc mọi người vui vẻ.

 

 

 

 

vd2.rar

  • Like 1

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Cám ơn bạn NgoKiet. Tôi down vd2.dll về dùng lệnh netload nhưng nó báo lỗi như vầy:

Command: NETLOAD

Cannot load assembly. Error details: System.BadImageFormatException: Could not 
load file or assembly 'file:///D:\vd2.dll' or one of its dependencies. This 
assembly is built by a runtime newer than the currently loaded runtime and 
cannot be loaded.
File name: 'file:///D:\vd2.dll'
   at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, 
Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, 
Boolean throwOnFileNotFound, Boolean forIntrospection)
   at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, 
Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, 
Boolean throwOnFileNotFound, Boolean forIntrospection)
   at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, 
Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
   at System.Reflection.Assembly.InternalLoadFrom(String assemblyFile, Evidence 
securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, 
Boolean forIntrospection, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.LoadFrom(String assemblyFile)
   at Autodesk.AutoCAD.Runtime.ExtensionLoader.Load(String fileName)
   at loadmgd()

WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value 
[HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure 
logging.
To turn this feature off, remove the registry value 
[HKLM\Software\Microsoft\Fusion!EnableLog].
 

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Bạn sài Cad bản bao nhiêu vậy. Mình test trên cad2017 và 2019. Theo mình biết thì cad dưới 2013 thì phải build lại do nó dùng thư viện dll khác nhau.

Nếu bạn sài Cad dưới 2013 thì bạn có thể gởi 2 file acmgd.dll và acdbmgd.dll cho mình mình build lại thử xem sao. ( do mình chưa cài bản cad đó).

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
43 phút trước, Doan Van Ha đã nói:

Cad2007. 2 files gởi kèm:

Lap_trinh_AutoCad_cho_Lisp_NgoKiet.zip

(Chán nhất khi dùng Net là khi Cad thay đổi thì phải sửa)

Ban thử file này nha.

 

Còn dùng net kết hợp với lisp thì để kiễm tra cad vesion để load file dll thích hợp. Hình như từ 2013-2019 là sài chung. Cad 2012 trở về trước mới khác.

vd3.zip

  • Like 1

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

MÌnh không chắc chắn 2file  trên là đủ chạy cho tất cả vesion cad vì file vd2.dll thì mình build trên net Framework 4.7 còn file dưới là .NET Framework 3.5.

Các phiên bãn CAD khác nhau thì dùng .Net Framework Khác nhau. Tuy nhiên bản mới có thể chạy được trên bản cũ nhưng ngươc lại thì không.

(2007,2008,2009 sài 2.0) (2010,2011,2012 sài 3.5) cùng sử dụng 2 file dll như 2007 là acmgd.dll và acdbmgd.dll

(2013,2014 sài 4.0) (2015,2016 sài 4.5) (2017,2018,2019 sài 4.6,4.7)  thì sử dụng 3 file dll , 2 file trên và file accoremgd.dll

 

Bác nào sài cad 2013 or 2014 có thể chép cho mình 3 file trên để mình build thử có chạy được trên Cad 2017/2019 không? Thanks.

Và test dùm mình nó có thể chạy được file vd2.dll không?

Vì mình thấy dòng báo lỗi của bác @Doan Van Ha báo do bản build runtime mới hơn bản hiện hành

This assembly is built by a runtime newer than the currently loaded runtime and 
cannot be loaded

 

 

Thanks

 

 

 

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
4 giờ trước, ngokiet đã nói:

Ban thử file này nha.

 

Còn dùng net kết hợp với lisp thì để kiễm tra cad vesion để load file dll thích hợp. Hình như từ 2013-2019 là sài chung. Cad 2012 trở về trước mới khác.

vd3.zip

Test thử 1 hàm, nó xuất thừa:

(kstrcase "Cad việt" T)
Free lisp from cadviet.com.
 Don't sale"CAD VIỆT"

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
7 giờ trước, Doan Van Ha đã nói:

Test thử 1 hàm, nó xuất thừa:

(kstrcase "Cad việt" T)
Free lisp from cadviet.com.
 Don't sale"CAD VIỆT"

Hi hi. Chỉ là đánh dấu cho vui thử thôi chứ không ảnh hưởng hàm lắm. Nó vẫn cho kết quả đúng mà.

 

Mình vừa sửa lại không còn text thừa đó nữa. Chỉ hiện text khi load dll thôi

Cả 2 bản cho Cad2007,và 2017

Mình chỉ test dll ở bản 2017 trên cad 2017,2019 chạy tốt. Bạn nào sài Cad khác test dùm và comment cho mình biết với.

Và có bổ sung thêm mấy hàm

<LispFunction("delfile")> Public Function del1(st As ResultBuffer) As Object
        Try
            System.IO.File.Delete(st(0).value)
        Catch ex As Exception
            Return New TypedValue(5019)
            Exit Function
        End Try
        Return New TypedValue(5021)
    End Function
    <LispFunction("copyfile")> Public Function copy1(st As ResultBuffer) As Object
        Try
            System.IO.File.Copy(st(0).value, st(1).value, st(2).typecode <> 5019)
        Catch ex As Exception
            Return New TypedValue(5019)
            Exit Function
        End Try
        Return New TypedValue(5021)
    End Function
    <LispFunction("openfile")> Public Function openfile(st As ResultBuffer) As Object
        Try
            Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.Open(st(0).value, False)
        Catch ex As Exception
            Return New TypedValue(5019)
            Exit Function
        End Try
        Return New TypedValue(5021)
    End Function

(delfile "d:\\baitap2\\e.dwg") : Xóa file name.

(copyfile "d:\\baitap1\\d.dwg" "d:\\baitap2\\e.dwg" T) : Copy 1 file  trong do T/nil là ghi đè hay không. Vd (copyfile "d:\\baitap1\\d.dwg" "d:\\baitap2\\e.dwg" T)

(openfile "d:\\baitap1\\d.dwg") Mở file autocad.

 

 

Debug.rar

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Autocad.Net

Cho mình hỏi làm sao để ngăn lỗi khi tham số đầu vào ResultBuffer không có gì 

VD:

(list_so 8)    ra   (1 2 3 4 5 6 7 8)

(list_so)     báo lỗi ADS, thoát Cad

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
1 giờ trước, cuongtk2 đã nói:

Autocad.Net

Cho mình hỏi làm sao để ngăn lỗi khi tham số đầu vào ResultBuffer không có gì 

VD:

(list_so 8)    ra   (1 2 3 4 5 6 7 8)

(list_so)     báo lỗi ADS, thoát Cad

Mình chưa test nhưng cơ bản là như vậy.

Kiểm tra thamso is nothing.

Hay thamso.AsArray().Length thử xem trươc khi đọc biến.

Cũng có thể dùng hàm try catch.

 

Mình mới test. Bác thừ dủng hàm này để xem thông số cad đưa vào như thế nào

<LispFunction("test2")> Public Function test2(ss As ResultBuffer) As Object
        If ss Is Nothing Then
            MsgBox("Không có tham số")
        Else
            MsgBox(ss.ToString)
        End If

 

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
59 phút trước, cuongtk2 đã nói:

Autocad.Net

Cho mình hỏi làm sao để ngăn lỗi khi tham số đầu vào ResultBuffer không có gì 

VD:

(list_so 8)    ra   (1 2 3 4 5 6 7 8)

(list_so)     báo lỗi ADS, thoát Cad

Kiểm tra chiều dài của tham số đầu vào.

image.png.01650d401b276f5a77567c32fa35cb6c.png

 

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Mới học C# được mấy hôm nên đang ngu ngơ lắm

Như  thế này được không

- Khai báo method dưới dạng object

tạo 1 biến ResultBuffer + 1 biến TypeValue dạng nil

- Điều kiện đúng  :  add thêm cho buffer và  return buffer;

- Điều kiện sai : return typedValue; này luôn

Vậy  hàm luôn có return.

[LispFunction("TestLisp")]
        public static object TestAtomLisp1(ResultBuffer rb)
        {
            TypedValue tv;
            if (rb != null)
            {
                tv = rb.AsArray()[0];
                return tv;
            }
            else
            {
                return new TypedValue((int)LispDataType.Nil);
            }

        }

 

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

mình làm vẫn lỗi:

[LispFunction("hc:listso")]
        public object HcListSoLisp(ResultBuffer rb)
        {        
              if (rb.AsArray().Length == 1 & rb != null)
            {
                ResultBuffer buffResult = new ResultBuffer();
                Array args = rb.AsArray();
                int n = Convert.ToInt32(((TypedValue)(args.GetValue(0))).Value);
                
                for (int i = 1; i <= n; i++)
                {
                    buffResult.Add(new TypedValue((int)LispDataType.Int32, i));
                    i = i++;
                }
                return buffResult;
            }
            else 
            {
                return new TypedValue((int)LispDataType.Nil);
            }

        }

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác
48 phút trước, cuongtk2 đã nói:

Mới học C# được mấy hôm nên đang ngu ngơ lắm

Như  thế này được không

- Khai báo method dưới dạng object

tạo 1 biến ResultBuffer + 1 biến TypeValue dạng nil

- Điều kiện đúng  :  add thêm cho buffer và  return buffer;

- Điều kiện sai : return typedValue; này luôn

Vậy  hàm luôn có return.


[LispFunction("TestLisp")]
        public static object TestAtomLisp1(ResultBuffer rb)
        {
            TypedValue tv;
            if (rb != null)
            {
                tv = rb.AsArray()[0];
                return tv;
            }
            else
            {
                return new TypedValue((int)LispDataType.Nil);
            }

        }

 

Tham khảo:

        // (hc:listso)
        // (hc:listso a)
        // (hc:listso 12 2)
        // (hc:listso "5")
        // (hc:listso 12)
        [LispFunction("hc:listso")]
        public object HcListSoLisp(ResultBuffer rb)
        {
            var ed = Application.DocumentManager.MdiActiveDocument.Editor;
            if (rb == null)
            {
                ed.WriteMessage("\nVui lòng nhập tham số nguyên dương. Exit...\n");
                return new TypedValue((int)LispDataType.Nil);
            }
                
            TypedValue[] args = rb.AsArray();
            if (args.Length != 1)
            {
                ed.WriteMessage("\nChiều dài tham số không hợp lệ! Exit...\n");
                return new TypedValue((int)LispDataType.Nil);
            }

            TypedValue tv = args[0];
            if (tv.TypeCode != (int)LispDataType.Int32 && tv.TypeCode != (int)LispDataType.Int16)
            {
                ed.WriteMessage("\nKiểu của tham số không hợp lệ! Exit...\n");
                return new TypedValue((int)LispDataType.Nil);
            }

            int n = Convert.ToInt32(tv.Value);
            if (n <= 0)
            {
                ed.WriteMessage("\nVui lòng nhập tham số nguyên dương. Exit...\n");
                return new TypedValue((int)LispDataType.Nil);
            }

            ResultBuffer buffResult = new ResultBuffer();            
            for (int i = 1; i <= n; i++)
            {
                buffResult.Add(new TypedValue((int)LispDataType.Int32, i));
            }

            return buffResult;
        }

 

  • Like 1

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Tạo một tài khoản hoặc đăng nhập để nhận xét

Bạn cần phải là một thành viên để lại một bình luận

Tạo tài khoản

Đăng ký một tài khoản mới trong cộng đồng của chúng tôi. Điều đó dễ mà.

Đăng ký tài khoản mới

Đăng nhập

Bạn có sẵn sàng để tạo một tài khoản ? Đăng nhập tại đây.

Đăng nhập ngay
Đăng nhập để thực hiện theo  

×