Chuyển đến nội dung
Diễn đàn CADViet
gia_bach

Tạo 1 ứng dụng AutoCAD .NET với MS Visual C#

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

Tạo 1 ứng dụng AutoCAD .NET với MS Visual C#

 

Tạo Project :

1. Khởi động Microsoft Visual C#

2. Chọn menu : FILE → “New Project ...”. Hộp thoại New Project xuất hiện :

tut01.jpg

3. Chọn template “Class Lybrary” như trong hình và nhập tên vào mục Name, trong ví dụ này tôi để mặc định là : ClassLibrary1.

4. Một Project mới đuợc tạo và giao diện như sau : C# tạo 1 file có tên Class1.cs mà ta sẽ sử dụng ở buớc viết Code.

tut02.jpg

 

 

Khai báo thư viện (Reference):

1. Tại cửa sổ Solution Explorer bên phải phía trên, chọn tag Reference

tut03.jpg

2. Click chuột phải lên tag Reference rồi chọn “Add Reference” trên menu xổ xuống . Hộp thoại “Add Reference” xuất hiện :

tut04.jpg

3. Chọn tag “ Browse” như trong hình và chỉ đến thư mục cài đặt AutoCad, ví dụ : C:\Program Files\AutoCAD 2010.

 

4. chọn 2 file : "acmgd.dll" và "acdbmgd.dll" , click OK để kết thúc.

5. Đặt thuộc tính “Copy Local” : Tại cửa sổ Solution Explorer, tag Reference click chuột phải lên file "acmgd.dll" chọn Properties : trong cửa sổ Properties, đặt thuộc tính “Copy Local” là False.

Làm tuơng tự với file "acdbmgd.dll"

tut05.jpg

 

Tạo lệnh Cad (viết code):

Để tạo 1 lệnh mới, sử dụng thuộc tính CommandMethod

ví dụ : [CommandMethod("CadViet")]

 

Ví dụ 1 : khai báo lệnh CadViet1 thực hiện việc xuất ra màn hình thông báo

“Chào mừng bạn đến với ứng dụng AutoCAD .NET API”

 

Ví dụ 2 : khai báo lệnh CadViet2 thực hiện việc tạo 1 đối tuợng TEXT có nội dung :

“Chào mừng bạn đến với ứng dụng AutoCAD .NET API”, tại vị trí do nguời dùng chọn.

 

Bạn Copy và Paste toàn bộ đọan code sau vào file Class1.cs

using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace Gia_Bach
{
   public class Cad_command
   {
       [CommandMethod("CadViet1")]
       public static void ex1()
       {
           Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Chào mừng bạn đến với ứng dụng AutoCAD .NET API!");
       }

       [CommandMethod("CadViet2")]
       public static void ex2()
       {
           Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocume
nt;
           Editor ed = doc.Editor;
           Database db = doc.Database;

           PromptPointResult Pr = ed.GetPoint("\nChọn điểm đặt Text : ");
           Point3d pt = Pr.Value;

           if (Pr.Status != PromptStatus.OK) return;

           // Start a transaction
           using (Transaction acTrans = db.TransactionManager.StartTransaction())
           {
               // Open the Block table for read
               BlockTable acBlkTbl = acTrans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

               // Open the Block table record Model space for write
               BlockTableRecord acBlkTblRec 
                   = acTrans.GetObject(acBlkTbl[blockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

               // Create a single-line text object
               DBText acText = new DBText();
               acText.SetDatabaseDefaults();
               acText.Position = pt;
               acText.Height = 0.5;
               acText.TextString = "Chào mừng bạn đến với ứng dụng AutoCAD .NET API!";

               acBlkTblRec.AppendEntity(acText);
               acTrans.AddNewlyCreatedDBObject(acText, true);
               // Save the changes and dispose of the transaction
               acTrans.Commit();
           }
       }
   }
}

 

Lưu Project :

Chọn menu : FILE → “Save All ...”. Hộp thoại Save Project xuất hiện, chọn đuờng dẫn thích hợp, click Save để kết thúc.

 

 

Build Project :

Chọn menu : BUILD → “Build Solution” : để tạo 1 ứng dụng.

Trong truờng hợp BUILD thành công, bạn sẽ có 1 file dll trùng tên với tên Project tại đuờng dẫn :

- “ProjectName\bin\Release\ projectName.dll “

trong đó ProjectName là tên Project bạn đã đặt ở buớc Lưu Project

 

 

Thực thi lệnh : (xem thành quả)

1. Khởi động AutoCAD

2. Tại dấu nhắc (Command ) của CAD gõ lệnh NETLOAD và chỉ đến vị trí file vừa BUILD ở trên, chọn OPEN để hoàn thành lệnh NETLOAD .

3. gõ lệnh CadViet1 hay CadViet2 để bắt đầu

 

Chúc bạn thành công.

  • Vote tăng 8

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 1 hàm LISP với AutoCAD .NET

 

- Với thư viện .NET API, AutoCAD cho phép chúng ta truy cập đến cơ sở dữ liệu của một bản vẽ (đối tuợng) nhiều hơn so với các công cụ truớc đó.

VD như các thông tin về Proxy (1 sản phẩm của ObjectARX)

- Mặt khác trong LISP, phạm vi của số nguyên (Integer) bị giới hạn trong khoảng 32-bit nên trong 1 số tính toán với số nguyên lớn đôi khi bị lỗi tràn bộ nhớ (Overflow).

Để khắc phục các hạn chế này, chúng ta nhờ .NET API tính toán rồi trả lại kết quả để AutoLisp tiếp tục xử lý.

 

Sử dụng thuộc tính LispFunction để tạo 1 hàm LISP.

ví dụ : [LispFunction("HelloWorld")]

 

Ví dụ 1 : hàm LISP Proxy_Info trả về danh sách (list) thông tin của 1 Proxy

VD : (proxy_info (car(entsel)))

→ ("\"Harmony\"" "HsCellInforObj" "HS_CELLINFOROBJECT")

hay

→ ("\"Harmony\"" "HsNodeObj" "HS_NODEOBJECT")

<pre class="cadvietlispcode">using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Runtime;using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;namespace Acad_command{ public class ProxyCommands { [LispFunction("Proxy_Info")] public ResultBuffer ProxyInfo(ResultBuffer resbuf) { Document doc = AcadApp.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; Database db = doc.Database; if (resbuf == null) { ed.WriteMessage("\nError: Quá ít đối số\n"); return null; } TypedValue[] args = resbuf.AsArray(); if (args.Length == 0) { ed.WriteMessage("\nError: Quá ít đối số\n"); return null; } if (args.Length > 1) { ed.WriteMessage("\nError: Quá nhiều đối số\n"); return null; } if (args[0].TypeCode != (short)LispDataType.ObjectId) { ed.WriteMessage("\nError: Đối số không hợp lệ\n"); return null; } ObjectId id = (ObjectId)args[0].Value; ResultBuffer result = new ResultBuffer(); using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(id, OpenMode.ForRead, false) as Entity; if (ent is ProxyEntity) { ProxyEntity ProxyEnt = ent as ProxyEntity; result.Add(new TypedValue((int)LispDataType.ListBegin)); result.Add(new TypedValue((int)LispDataType.Text, ProxyEnt.ApplicationDescription)); result.Add(new TypedValue((int)LispDataType.Text, ProxyEnt.OriginalClassName)); result.Add(new TypedValue((int)LispDataType.Text, ProxyEnt.OriginalDxfName)); result.Add(new TypedValue((int)LispDataType.ListEnd)); } else { ed.WriteMessage("Entity không phải là Proxy."); return null; } tr.Commit(); } return result; } }}</pre>

 

 

Ví dụ 2 : hàm Lisp RPN_Cal tính giá trị của biếu thức (tuơng tự hàm cal của Lisp) kết quả trả về là 1 chuỗi (string).

(sử dụng hàm tính giá trị biếu thức của Vincent )

(RPN viết tắt của Reverse Polish Notation : ký pháp nghịch đảo Ba Lan)

chấp nhận các toán tử và toán hạng : + - * / ^ abs sqrt sin cos tan e pi () và ...

VD :

(RPN_cal "3^2 +abs(-1)") → "10"

(RPN_cal "sin(pi/2) +abs(-1)") → "2"

(RPN_cal "sqrt(16) – abs(-4)") → "0"

 

mã nguồn C# và dll : download here

Chỉnh sửa theo gia_bach
  • Vote tăng 2

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

Chèn POINT tại giao điểm của 2 Đối tuợng (code C#)

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace Gia_Bach
{
   public class TestCommands
   {
       [CommandMethod("giao")]
       public void GiaoDiemt()
       {
           Document doc = AcadApp.DocumentManager.MdiActiveDocument;
           Editor ed = doc.Editor;
           PromptEntityResult res1 = ed.GetEntity("\nChọn curve thứ 1 : ");
           if (res1.Status != PromptStatus.OK) return;

           PromptEntityResult res2 = ed.GetEntity("\nChọn curve thứ 2 : ");
           if (res2.Status != PromptStatus.OK) return;

           Database db = HostApplicationServices.WorkingDatabase;
           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               Entity ent1 = tr.GetObject(res1.ObjectId, OpenMode.ForRead, false) as Entity;
               Entity ent2 = tr.GetObject(res2.ObjectId, OpenMode.ForRead, false) as Entity;
               Point3dCollection points = new Point3dCollection();
               ent1.IntersectWith(ent2, Intersect.OnBothOperands, points, 0, 0);
               if (points.Count > 0)
               {
                   // Open the Block table for read
                   BlockTable acBlkTbl = 
                       tr.GetObject(db.BlockTableId,OpenMode.ForRead) as BlockTable;

                   // Open the Block table record Model space for write
                   BlockTableRecord acBlkTblRec
                       = tr.GetObject(acBlkTbl[blockTableRecord.ModelSpace],OpenMode.ForWrite) as BlockTableRecord;

                   foreach (Point3d pt in points)
                   {
                       DBPoint acPoint = new DBPoint(pt);
                       acPoint.SetDatabaseDefaults();
                       // Add the new object to the block table record and the transaction
                       acBlkTblRec.AppendEntity(acPoint);
                       tr.AddNewlyCreatedDBObject(acPoint, true);
                   }                    
                   // Save the new object to the database
                   tr.Commit();
                   ed.WriteMessage("\nTìm đuợc {0} giao điểm.", points.Count);
               }
               else 
                   ed.WriteMessage("\n*** Không có giao điểm!"); return;
           }
       }
   }
}

  • Vote tăng 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 1 ứng dụng AutoCAD .NET với MS Visual C#

 

Tạo Project :

1. Khởi động Microsoft Visual C#

2. Chọn menu : FILE → “New Project ...”. Hộp thoại New Project xuất hiện :

 

3. Chọn template “Class Lybrary” như trong hình và nhập tên vào mục Name, trong ví dụ này tôi để mặc định là : ClassLibrary1.

4. Một Project mới đuợc tạo và giao diện như sau : C# tạo 1 file có tên Class1.cs mà ta sẽ sử dụng ở buớc viết Code.

 

Khai báo thư viện (Reference):

1. Tại cửa sổ Solution Explorer bên phải phía trên, chọn tag Reference

 

2. Click chuột phải lên tag Reference rồi chọn “Add Reference” trên menu xổ xuống . Hộp thoại “Add Reference” xuất hiện :

 

3. Chọn tag “ Browse” như trong hình và chỉ đến thư mục cài đặt AutoCad, ví dụ : C:\Program Files\AutoCAD 2010.

 

4. chọn 2 file : "acmgd.dll" và "acdbmgd.dll" , click OK để kết thúc.

5. Đặt thuộc tính “Copy Local” : Tại cửa sổ Solution Explorer, tag Reference click chuột phải lên file "acmgd.dll" chọn Properties : trong cửa sổ Properties, đặt thuộc tính “Copy Local” là False.

Làm tuơng tự với file "acdbmgd.dll"

Chào anh gia_bach

Mấy ngày nay, em lỡ hẹn với Visual Studio nhiều lắm, vì công việc, thời gian không cho phép, vì... :lol:

Hôm nay, em đã cài bộ Visual Studio2008 và đang cố gắng tìm hiểu về nó, coi bộ khó ghê anh ha.

Em đã làm theo các bước của anh hướng dẫn ở trên và làm được đến bước 5 rồi

 

Và đến bước copy, paste đoạn code của anh dưới đây và thao tác Build Project : thì chương trình báo có 9 lỗi, em cũng không hiểu tại vì sao nữa... :lol:

Bạn Copy và Paste toàn bộ đọan code sau vào file Class1.cs

using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace Gia_Bach
{
   public class Cad_command
   {
       [CommandMethod("CadViet1")]
       public static void ex1()
       {
           Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Chào mừng bạn đến với ứng dụng AutoCAD .NET API!");
       }

       [CommandMethod("CadViet2")]
       public static void ex2()
       {
           Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocume


nt;
           Editor ed = doc.Editor;
           Database db = doc.Database;

           PromptPointResult Pr = ed.GetPoint("\nChọn điểm đặt Text : ");
           Point3d pt = Pr.Value;

           if (Pr.Status != PromptStatus.OK) return;

           // Start a transaction
           using (Transaction acTrans = db.TransactionManager.StartTransaction())
           {
               // Open the Block table for read
               BlockTable acBlkTbl = acTrans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

               // Open the Block table record Model space for write
               BlockTableRecord acBlkTblRec 
                   = acTrans.GetObject(acBlkTbl[blockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

               // Create a single-line text object
               DBText acText = new DBText();
               acText.SetDatabaseDefaults();
               acText.Position = pt;
               acText.Height = 0.5;
               acText.TextString = "Chào mừng bạn đến với ứng dụng AutoCAD .NET API!";

               acBlkTblRec.AppendEntity(acText);
               acTrans.AddNewlyCreatedDBObject(acText, true);
               // Save the changes and dispose of the transaction
               acTrans.Commit();
           }
       }
   }
}

 

Lưu Project :

Chọn menu : FILE → “Save All ...”. Hộp thoại Save Project xuất hiện, chọn đuờng dẫn thích hợp, click Save để kết thúc.

Build Project :

Chọn menu : BUILD → “Build Solution” : để tạo 1 ứng dụng.

Trong truờng hợp BUILD thành công, bạn sẽ có 1 file dll trùng tên với tên Project tại đuờng dẫn :

- “ProjectName\bin\Release\ projectName.dll “

trong đó ProjectName là tên Project bạn đã đặt ở buớc Lưu Project

Thực thi lệnh : (xem thành quả)

1. Khởi động AutoCAD

2. Tại dấu nhắc (Command ) của CAD gõ lệnh NETLOAD và chỉ đến vị trí file vừa BUILD ở trên, chọn OPEN để hoàn thành lệnh NETLOAD .

3. gõ lệnh CadViet1 hay CadViet2 để bắt đầu

 

Chúc bạn thành công.

Em đã copy và paste như sau :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClassLibrary2
{
   public class Class1
   {
       using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace Gia_Bach
{
   public class Cad_command
   {
       [CommandMethod("CadViet1")]
       public static void ex1()
       {
           Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Chào mừng bạn đến với ứng dụng AutoCAD .NET API!");
       }

       [CommandMethod("CadViet2")]
       public static void ex2()
       {
           Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocume




nt;
           Editor ed = doc.Editor;
           Database db = doc.Database;

           PromptPointResult Pr = ed.GetPoint("\nChọn điểm đặt Text : ");
           Point3d pt = Pr.Value;

           if (Pr.Status != PromptStatus.OK) return;

           // Start a transaction
           using (Transaction acTrans = db.TransactionManager.StartTransaction())
           {
               // Open the Block table for read
               BlockTable acBlkTbl = acTrans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

               // Open the Block table record Model space for write
               BlockTableRecord acBlkTblRec 
                   = acTrans.GetObject(acBlkTbl[blockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

               // Create a single-line text object
               DBText acText = new DBText();
               acText.SetDatabaseDefaults();
               acText.Position = pt;
               acText.Height = 0.5;
               acText.TextString = "Chào mừng bạn đến với ứng dụng AutoCAD .NET API!";

               acBlkTblRec.AppendEntity(acText);
               acTrans.AddNewlyCreatedDBObject(acText, true);
               // Save the changes and dispose of the transaction
               acTrans.Commit();
           }
       }
   }
}
   }
}

Hình ảnh mà em làm theo các bước của anh hướng dẫn đây ạ :

vs.jpg

Rất mong được hướng dẫn của anh gia_bach và các bác trên diễn đàn

Tue_NV xin chân thành cảm ơn :lol:

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
.............

Và đến bước copy, paste đoạn code của anh dưới đây và thao tác Build Project : thì chương trình báo có 9 lỗi, em cũng không hiểu tại vì sao nữa... :lol:

 

Em đã copy và paste như sau :

using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace Gia_Bach
{
   public class Cad_command
   {
       [CommandMethod("CadViet1")]
       public static void ex1()
       {
           Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Chào mừng bạn đến với ứng dụng AutoCAD .NET API!");
       }

       [CommandMethod("CadViet2")]
       public static void ex2()
       {
           Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocume

nt;
           Editor ed = doc.Editor;
           Database db = doc.Database;

           PromptPointResult Pr = ed.GetPoint("\nChọn điểm đặt Text : ");
           Point3d pt = Pr.Value;

           if (Pr.Status != PromptStatus.OK) return;

           // Start a transaction
           using (Transaction acTrans = db.TransactionManager.StartTransaction())
           {
               // Open the Block table for read
               BlockTable acBlkTbl = acTrans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;

               // Open the Block table record Model space for write
               BlockTableRecord acBlkTblRec 
                   = acTrans.GetObject(acBlkTbl[blockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

               // Create a single-line text object
               DBText acText = new DBText();
               acText.SetDatabaseDefaults();
               acText.Position = pt;
               acText.Height = 0.5;
               acText.TextString = "Chào mừng bạn đến với ứng dụng AutoCAD .NET API!";

               acBlkTblRec.AppendEntity(acText);
               acTrans.AddNewlyCreatedDBObject(acText, true);
               // Save the changes and dispose of the transaction
               acTrans.Commit();
           }
       }
   }
}
   }
}

................

Bạn phải xóa toàn bộ nội dung của file class1.cs trước khi paste vào.

  • Vote tăng 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
Bạn phải xóa toàn bộ nội dung của file class1.cs trước khi paste vào.

Cảm ơn anh gia_bach. Em đã làm theo hướng dẫn của anh rồi. Khi thao tác Build Solution

Kết quả là có 1 lỗi ở Error list :

1; expected :lol:

Đây là lỗi gì ạ? Như vầy thì chưa tạo được file .dll phải không ạ?

Cách khắc phục như thế nào?

Đây là file class1.cs mà em đã làm theo sự hướng dẫn của anh :

http://www.cadviet.com/upfiles/3/class1.rar

 

Rất mong anh hướng dẫn tiếp :lol:

Cho em hỏi thêm là mục đích mình Add reference 2 file : "acmgd.dll" và "acdbmgd.dll"

và đặt thuộc tính “Copy Local” là False cho 2 file này?

Và tại sao khi mở file class1.cs đã tạo trước đó thì trên menu Build không có nữa? :lol:

build.jpg

Cảm ơn anh.

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 anh gia_bach. Em đã làm theo hướng dẫn của anh rồi. Khi thao tác Build Solution

Kết quả là có 1 lỗi ở Error list :

1; expected :lol:

Đây là lỗi gì ạ? Như vầy thì chưa tạo được file .dll phải không ạ?

Cách khắc phục như thế nào?

Đây là file class1.cs mà em đã làm theo sự hướng dẫn của anh :

http://www.cadviet.com/upfiles/3/class1.rar

 

Rất mong anh hướng dẫn tiếp :lol:

Cho em hỏi thêm là mục đích mình Add reference 2 file : "acmgd.dll" và "acdbmgd.dll"

và đặt thuộc tính “Copy Local” là False cho 2 file này?

Và tại sao khi mở file class1.cs đã tạo trước đó thì trên menu Build không có nữa? :lol:

 

Cảm ơn anh.

1. bị lỗi xuống dòng (do copy từ web) :

Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocume

nt;

 

-> Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

đuơng nhiên khi có lỗi thì không tạo đuợc file dll.

 

2. file : "acmgd.dll" ,"acdbmgd.dll" (và nhiều file khác) chứa các API .NET do CAD cung cấp

(tuơng tự với LISP phải gọi hàm (vl-load-com) truớc khi sử dụng các hàm VL-***)

- thuộc tính “Copy Local” là False : nghĩa là không cần copy các file này ("acmgd.dll" hay"acdbmgd.dll") tới thư mục OutPut , mà để CAD tự tìm các file này trong thư mục cài đặt CAD khi thưc thi.

 

3.menu Build : chỉ có thể Build 1 solution (bao gồm các file tham chiếu *.dll, file *.cs, *.csproj ....)

  • Vote tăng 2

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. bị lỗi xuống dòng (do copy từ web) :

Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocume

nt;

 

-> Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

đuơng nhiên khi có lỗi thì không tạo đuợc file dll.

 

2. file : "acmgd.dll" ,"acdbmgd.dll" (và nhiều file khác) chứa các API .NET do CAD cung cấp

(tuơng tự với LISP phải gọi hàm (vl-load-com) truớc khi sử dụng các hàm VL-***)

- thuộc tính “Copy Local” là False : nghĩa là không cần copy các file này ("acmgd.dll" hay"acdbmgd.dll") tới thư mục OutPut , mà để CAD tự tìm các file này trong thư mục cài đặt CAD khi thưc thi.

 

3.menu Build : chỉ có thể Build 1 solution (bao gồm các file tham chiếu *.dll, file *.cs, *.csproj ....)

Build successed rồi anh ạ.

Em đã gõ lệnh CADVIET1 và đã chạy thành công. :lol:

Nhưng gõ lệnh CADVIET2 thì sau khi Chọn điểm đặt Text thì nó không có ra kết quả chi cả. Anh có thể xem lại chổ này 1 chút được không? :lol:

 

Em đã bắt đầu chào "AUTOCAD .NET API""HELLO WORLD" rồi anh ạ. Hy vọng sẽ tạo ra những ứng dụng thật sự hiệu quả.

Em chỉ có thắc mắc chổ ý thứ 3 ở bài viết trên của anh 1 tý ạ: Khi đã mở file class1.cs , vì nó báo lỗi, nên phải sửa lại những chổ bị lỗi rồi phải Build Solution lại nhưng em chẳng thấy menu Build ở đâu? để Build Solution và tạo ra file .dll. Anh có thể nói rõ hơn ý thứ 3 ở bài viết trên của anh được không? Em đã sửa lỗi rồi mà chẳng thấy menu Build đâu anh ạ??

 

Cảm ơn anh rất nhiều :lol:

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
Build successed rồi anh ạ.

Em đã gõ lệnh CADVIET1 và đã chạy thành công. :lol:

Nhưng gõ lệnh CADVIET2 thì sau khi Chọn điểm đặt Text thì nó không có ra kết quả chi cả. Anh có thể xem lại chổ này 1 chút được không? :lol:

 

Em đã bắt đầu chào "AUTOCAD .NET API""HELLO WORLD" rồi anh ạ. Hy vọng sẽ tạo ra những ứng dụng thật sự hiệu quả.

Em chỉ có thắc mắc chổ ý thứ 3 ở bài viết trên của anh 1 tý ạ: Khi đã mở file class1.cs , vì nó báo lỗi, nên phải sửa lại những chổ bị lỗi rồi phải Build Solution lại nhưng em chẳng thấy menu Build ở đâu? để Build Solution và tạo ra file .dll. Anh có thể nói rõ hơn ý thứ 3 ở bài viết trên của anh được không? Em đã sửa lỗi rồi mà chẳng thấy menu Build đâu anh ạ??

 

Cảm ơn anh rất nhiều :lol:

"Chào mừng bạn đến với ứng dụng AutoCAD .NET API!"

 

1. sau khi Chọn điểm đặt Text thì nó không có ra kết quả chi cả

có thể là do dòng này : cText.Height = 0.5;

(chiều cao Text = 0.5), bạn thay đổi cho phù hợp.

 

2. Để Build Solution bạn phải mở Solution đó (khi bạn mở file *.cs thì chỉ biên tập nội dung file này đuợc thôi.)

Sau khi mở 1 Solution hay Project , ở Tag Solution Explorer (thuờng nằm phía trên bên phải)

tut03.jpg

bạn click vô các file ***.cs, Visual C# sẽ mở file này cho bạn biên tập.

  • Vote tăng 2

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
"Chào mừng bạn đến với ứng dụng AutoCAD .NET API!"

 

1. sau khi Chọn điểm đặt Text thì nó không có ra kết quả chi cả

có thể là do dòng này : cText.Height = 0.5;

(chiều cao Text = 0.5), bạn thay đổi cho phù hợp.

 

2. Để Build Solution bạn phải mở Solution đó (khi bạn mở file *.cs thì chỉ biên tập nội dung file này đuợc thôi.)

Sau khi mở 1 Solution hay Project , ở Tag Solution Explorer (thuờng nằm phía trên bên phải)

tut03.jpg

bạn click vô các file ***.cs, Visual C# sẽ mở file này cho bạn biên tập.

Chào anh gia_bach

1 Lệnh CADVIET2 : em đã chạy thành công rồi anh ạ

2. Em vẫn chưa Build Solution được anh ạ. Em không hiểu vì sao nữa? Để em thử lại

3. Em có những thắc mắc này, muốn hỏi anh :

a)

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

-> Những dòng này là thủ tục bắt buộc ở đầu phần chương trình phải không anh?

Em có đọc và tìm hiểu cấu trúc của 1 Chương trình C# : gồm 3 phần là Namespace, Class và Method và Namespace chứa các class, class chứ method và trong method là các câu lệnh.

Em đọc qua cấu trúc của cây thư mục trong sách thì cũng lờ mờ hiểu được chút đỉnh nhưng ở những dòng này thì bí quá, chưa hiểu được vì em mới bắt đầu và vốn tiếng Anh có hạn :lol:

{

public class Cad_command

{

[CommandMethod("CadViet1")]

public static void ex1()

{

Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Chào mừng bạn đến với ứng dụng AutoCAD .NET API!");

}

Em muốn hỏi anh mấy dòng :

public class Cad_command

public static void ex1()

-> Nghĩa là gì ạ? Có phải định nghĩa 1 Class không?

Rồi hàm ShowAlertDialog thì mình có thể tham khảo chổ nào ạ? Theo em đọc và hiểu chính là nó đang xuất ra Dialog để hiển thị câu "Chào mừng bạn đến với ứng dụng AutoCAD .NET API!". Nhưng em tìm hoài trong Help mà chẳng thấy nó đâu??

 

Rất mong anh gia_bach giải thích.

Cảm ơn anh.

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
Chào anh gia_bach

1 Lệnh CADVIET2 : em đã chạy thành công rồi anh ạ

2. Em vẫn chưa Build Solution được anh ạ. Em không hiểu vì sao nữa? Để em thử lại

3. Em có những thắc mắc này, muốn hỏi anh :

a)

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

-> Những dòng này là thủ tục bắt buộc ở đầu phần chương trình phải không anh?

Em có đọc và tìm hiểu cấu trúc của 1 Chương trình C# : gồm 3 phần là Namespace, Class và Method và Namespace chứa các class, class chứ method và trong method là các câu lệnh.

..............

Tình hình là : phương châm "đi tắt đón đầu" có vẻ gặp trục trặc rồi!

 

Một vài ý cùng bạn (sưu tầm từ nhiều nguồn) :

namespace

Như chúng ta đã biết .NET cung cấp một thư viện các lớp đồ sộ và thư viện này có tên là FCL (Framework Class Library). Mỗi lớp có một tên riêng, vì vậy FCL có hàng ngàn tên như ArrayList, Dictionary, FileSelector,…

Điều này làm nảy sinh vấn đề, người lập trình không thể nào nhớ hết được tên của các lớp trong .NET Framework. Tệ hơn nữa là sau này có thể ta tạo lại một lớp trùng với lớp đã có chẳng hạn. Ví dụ trong quá trình phát triển một ứng dụng ta cần xây dựng một lớp từ điển và lấy tên là Dictionary, và điều này dẫn đến sự tranh chấp khi biên dịch vì C# chỉ cho phép một tên duy nhất.

Chắc chắn rằng khi đó chúng ta phải đổi tên của lớp từ điển mà ta vừa tạo thành một cái tên khác chẳng hạn như myDictionary. Khi đó sẽ làm cho việc phát triển các ứng dụng trở nên phức tạp, cồng kềnh. Đến một sự phát triển nhất định nào đó thì chính là cơn ác mộng cho nhà phát triển.

Giải pháp để giải quyết vấn đề này là việc tạo ra một namespace, namsespace sẽ hạn chế phạm vi của một tên, làm cho tên này chỉ có ý nghĩa trong vùng đã định nghĩa. Giả sử có một người nói Tùng là một kỹ sư, từ kỹ sư phải đi kèm với một lĩnh vực nhất định nào đó, vì nếu không thì chúng ta sẽ không biết được là anh ta là kỹ sư cầu đường, cơ khí hay phần mềm. Khi đó một lập trình viên C# sẽ bảo rằng Tùng là CauDuong.KySu phân biệt với CoKhi.KySu hay PhanMem.KySu. Namespace trong trường hợp này là CauDuong, CoKhi, PhanMem sẽ hạn chế phạm vi của những từ theo sau. Nó tạo ra một vùng không gian để tên sau đó có nghĩa.

Tương tự như vậy ta cứ tạo các namespace để phân thành các vùng cho các lớp trùng tên không tranh chấp với nhau.

Tương tự như vậy, .NET Framework có xây dựng một lớp Dictionary bên trong namespace System.Collections, và tương ứng ta có thể tạo một lớp Dictionary khác nằm trong namespace ProgramCSharp.DataStructures, điều này hoàn toàn không dẫn đến sự tranh chấp với nhau.

 

using

Để làm cho chương trình gọn hơn, và không cần phải viết từng namespace cho từng đối tượng, C# cung cấp từ khóa là using, sau từ khóa này là một namespace hay subnamespace với mô tả đầy đủ trong cấu trúc phân cấp của nó.

VD : ta có thể dùng dòng lệnh :

using Autodesk.AutoCAD.ApplicationServices;

ở đầu chương trình và khi đó trong chương trình chúng ta không cần phải viết đầy đủ :

Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Chào mừng bạn đến với ứng dụng AutoCAD .NET API!");

mà chỉ cần viết :

Application.ShowAlertDialog("Chào mừng bạn đến với ứng dụng AutoCAD .NET API!");

 

-> Chỉ cần khai báo những namespace (using ...) mà chúng ta sẽ dùng

 

..............

public class Cad_command

public static void ex1()

-> Nghĩa là gì ạ? Có phải định nghĩa 1 Class không?

Rồi hàm ShowAlertDialog thì mình có thể tham khảo chổ nào ạ? Theo em đọc và hiểu chính là nó đang xuất ra Dialog để hiển thị câu "Chào mừng bạn đến với ứng dụng AutoCAD .NET API!". Nhưng em tìm hoài trong Help mà chẳng thấy nó đâu??

............

các dòng này định nghĩa 1 class có tên là Cad_command.

 

Để xem Help, trong Visual C# vô menu View-> Object Browser xuất hiện cửa sổ Object Browser.

vì hàm ShowAlertDialog

viết đầy đủ là : Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(string message);

thuộc namespace : Autodesk.AutoCAD.ApplicationServices (trong file acmgd.dll)

class Application

nên bạn click vô file acmgd.dll -> Autodesk.AutoCAD.ApplicationServices -> Application -> ShowAlertDialog

kết quả sẽ là :

objectbrowser.jpg

  • Vote tăng 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
Bác có cách nào build solution từ vba không?

 

Vì em phải lọ mọ đi học NET để bảo mật cho cái soft cùn của Em đây...

Nghe nói có Tool để convert vba -> VB.NET, bạn thử search xem sao ?

 

Còn chuyện "bảo mật" thì tui cũng nghe nói là .Net chưa chắc đã an toàn ?! (dĩ nhiên đó chỉ là chuyện của các Pro)

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

chào anh GiaBach, em vừa nhân được 1 đề tài thiết kế giao diện cho người dùng vẽ hình vào đó bằng các nút lệnh như: line, arck, circle,spline, và nhập vào đó các thông số như vẽ đường thẳng thì nhấn vào 1 điểm và nhập vào độ dài và góc tương tự như autocad nhưng nó đơn giản hơn là chỉ với 4 nút lệnh thôi. Chương trình này là giao diện của bàn máy phay CNC 3 trục, và trên giao diện có 1 nút transmit khi người dùng vẽ xong nhấn vào nút đó thì thông số về hình vẽ sẽ được xuất xuống máy phay CNC gia công. Phần đầu em chỉ mới làm giao diện thôi, em có thể dùng C# tạo giao diện cho người dùng vẽ lên đó các hình như line, circle nhưng về phần xử lý toạ độ và góc toạ độ cũng như cách nhập các thông số trong C# em chưa làm đc và đang bí về phần này. Rất mong anh GiaBach chỉ dẫn cho em, hoặc anh có tài liệu liên quan có thể chia sẻ cho em với. Em rất cảm ơn anh chúc anh nhiều sức khoẻ.

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
chào anh GiaBach, em vừa nhân được 1 đề tài thiết kế giao diện cho người dùng vẽ hình vào đó bằng các nút lệnh như: line, arck, circle,spline, và nhập vào đó các thông số như vẽ đường thẳng thì nhấn vào 1 điểm và nhập vào độ dài và góc tương tự như autocad nhưng nó đơn giản hơn là chỉ với 4 nút lệnh thôi. Chương trình này là giao diện của bàn máy phay CNC 3 trục, và trên giao diện có 1 nút transmit khi người dùng vẽ xong nhấn vào nút đó thì thông số về hình vẽ sẽ được xuất xuống máy phay CNC gia công. Phần đầu em chỉ mới làm giao diện thôi, em có thể dùng C# tạo giao diện cho người dùng vẽ lên đó các hình như line, circle nhưng về phần xử lý toạ độ và góc toạ độ cũng như cách nhập các thông số trong C# em chưa làm đc và đang bí về phần này. Rất mong anh GiaBach chỉ dẫn cho em, hoặc anh có tài liệu liên quan có thể chia sẻ cho em với. Em rất cảm ơn anh chúc anh nhiều sức khoẻ.

Bạn tham khảo AutoCAD Drawing Using C# của Sheel Gohe

http://www.codeproject.com/KB/cs/AutoCAD_CSharp.aspx

  • Vote tăng 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
Bạn tham khảo AutoCAD Drawing Using C# của Sheel Gohe

http://www.codeproject.com/KB/cs/AutoCAD_CSharp.aspx

cảm ơn anh, trong đoạn code này có dòng ghi phải reference tới autocad dll trước khi chạy code, em kiếm trong thằng autocad 2007 không ra cái autocad.dll, hay là nó dùng 2 cái dll giống như anh vậy?

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 anh, trong đoạn code này có dòng ghi phải reference tới autocad dll trước khi chạy code, em kiếm trong thằng autocad 2007 không ra cái autocad.dll, hay là nó dùng 2 cái dll giống như anh vậy?

Bạn thử file này : CadAutomation for CAD2007

Sourcode : download here

Add reference cho 2 file :

- acax??enu.tlb : The AutoCAD type library

axdb??enu.tlb : The AutoCAD/ObjectDBX Common type library

tại thư mục : C:\Program Files\Common Files\Autodesk Shared

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 thử file này : CadAutomation for CAD2007

Sourcode : download here

Add reference cho 2 file :

- acax??enu.tlb : The AutoCAD type library

axdb??enu.tlb : The AutoCAD/ObjectDBX Common type library

tại thư mục : C:\Program Files\Common Files\Autodesk Shared

 

cảm ơn anh Gia Bạch em đã chạy được rồi, nhưng cái của em làm hoàn toàn khác cái này, nó hoàn toàn độc lập với autocad, nó là 1 giao diện tương tự như autocad nhưng đơn giản hơn chỉ với các nút lệnh line, circle, arc, spline, và cho người dùng nhập thông số đầu vào như autocad, em đang dùng C# để tạo ra cái khung màn hình cho người dùng vẽ và đang bí ở chỗ chia lưới cũng như giới hạn khung lại còn 800x600, anh Gia Bạch đã từng làm qua hay có tài liệu về cái này không giúp em với.

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ôi cũng đang triển khai giao diện riêng dùng cho thiết kế công việc của mình.

 

Chương trình có thể vẽ các line, circle... và chọn, sửa đổi chúng.

 

Chương trình mẫu ở đây.

 

cảm ơn anhcos, đây chính là cái em đang cần và chỉ cần 2d là đủ rồi, hiện giờ toàn bộ tài liệu em có chỉ có thể giúp em làm được thế này thôi http://www.mediafire.com/file/kwcqqc231t23...erInterface.rar anh nhấn nút trái chuột vào 1 điểm trong giao diện và nhấn nút phải chuột và điểm khác rồi nhấn nút vẽ Line sẽ vẽ đc đường thẳng. Em đang ở gần công viên Lê thị Riêng quận 10 tpHCM, anh anhcos ở đâu vậy? em rất cần anh giúp đỡ để hoàn thành giao diện này. Anh có thể chia sẻ cho em tài liệu mà anh đọc để làm được giao diện như vậy không? thanks anhcos

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ôi làm việc cũng gần đó, tôi sẽ giúp bạn làm phần này.

Tài liệu thì chỉ có mỗi help VB của CAD thôi.

  • Vote tăng 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

@v3rarz: code C# về chương trình vẽ Line, Circle và Spline (chưa có phần vẽ Arc - cái này để bạn tự làm)

Nhập dữ liệu từ bàn phím và chuột (hỗ trợ truy bắt điểm CEN, END, MID)

Tải về ở đây.

  • Vote tăng 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 1 hàm LISP với AutoCAD .NET

 

- Với thư viện .NET API, AutoCAD cho phép chúng ta truy cập đến cơ sở dữ liệu của một bản vẽ (đối tuợng) nhiều hơn so với các công cụ truớc đó.

VD như các thông tin về Proxy (1 sản phẩm của ObjectARX)

- Mặt khác trong LISP, phạm vi của số nguyên (Integer) bị giới hạn trong khoảng 32-bit nên trong 1 số tính toán với số nguyên lớn đôi khi bị lỗi tràn bộ nhớ (Overflow).

Để khắc phục các hạn chế này, chúng ta nhờ .NET API tính toán rồi trả lại kết quả để AutoLisp tiếp tục xử lý.

 

Sử dụng thuộc tính LispFunction để tạo 1 hàm LISP.

ví dụ : [LispFunction("HelloWorld")]

 

Ví dụ 1 : hàm LISP Proxy_Info trả về danh sách (list) thông tin của 1 Proxy

VD : (proxy_info (car(entsel)))

→ ("\"Harmony\"" "HsCellInforObj" "HS_CELLINFOROBJECT")

hay

→ ("\"Harmony\"" "HsNodeObj" "HS_NODEOBJECT")

<pre class="cadvietlispcode">using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Runtime;using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;namespace Acad_command{ public class ProxyCommands { [LispFunction("Proxy_Info")] public ResultBuffer ProxyInfo(ResultBuffer resbuf) { Document doc = AcadApp.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; Database db = doc.Database; if (resbuf == null) { ed.WriteMessage("\nError: Quá ít đối số\n"); return null; } TypedValue[] args = resbuf.AsArray(); if (args.Length == 0) { ed.WriteMessage("\nError: Quá ít đối số\n"); return null; } if (args.Length > 1) { ed.WriteMessage("\nError: Quá nhiều đối số\n"); return null; } if (args[0].TypeCode != (short)LispDataType.ObjectId) { ed.WriteMessage("\nError: Đối số không hợp lệ\n"); return null; } ObjectId id = (ObjectId)args[0].Value; ResultBuffer result = new ResultBuffer(); using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(id, OpenMode.ForRead, false) as Entity; if (ent is ProxyEntity) { ProxyEntity ProxyEnt = ent as ProxyEntity; result.Add(new TypedValue((int)LispDataType.ListBegin)); result.Add(new TypedValue((int)LispDataType.Text, ProxyEnt.ApplicationDescription)); result.Add(new TypedValue((int)LispDataType.Text, ProxyEnt.OriginalClassName)); result.Add(new TypedValue((int)LispDataType.Text, ProxyEnt.OriginalDxfName)); result.Add(new TypedValue((int)LispDataType.ListEnd)); } else { ed.WriteMessage("Entity không phải là Proxy."); return null; } tr.Commit(); } return result; } }}</pre>

 

 

Ví dụ 2 : hàm Lisp RPN_Cal tính giá trị của biếu thức (tuơng tự hàm cal của Lisp) kết quả trả về là 1 chuỗi (string).

(sử dụng hàm tính giá trị biếu thức của Vincent )

(RPN viết tắt của Reverse Polish Notation : ký pháp nghịch đảo Ba Lan)

chấp nhận các toán tử và toán hạng : + - * / ^ abs sqrt sin cos tan e pi () và ...

VD :

(RPN_cal "3^2 +abs(-1)") → "10"

(RPN_cal "sin(pi/2) +abs(-1)") → "2"

(RPN_cal "sqrt(16) – abs(-4)") → "0"

 

mã nguồn C# và dll : download here

Cám ơn Tue_NV đã chỉ điểm vị trí để tham khảo hàm RPN_Cal .

Gia_Bach xem lại giúp, mình kg vào link này download here đc.

Gia_Bach có thể biên dịch nó thành dll để sử dụng chung trong windows được kg

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 Tue_NV đã chỉ điểm vị trí để tham khảo hàm RPN_Cal .

Gia_Bach xem lại giúp, mình kg vào link này download here đc.

Gia_Bach có thể biên dịch nó thành dll để sử dụng chung trong windows được kg

Vụ này Tue_NV không giúp bác được. File cũ PRN_Cal.dll đã tải của anh gia_bach không còn trong máy của Tue_NV nữa :( .

Chắc bác chờ anh gia bach và Có thông báo này ở đường Link mà bác download:

http://www.megashare.vnn.vn/

chắc bác phải tạm chờ vậy :)

  • Vote tăng 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

×