/

17 tháng 3, 2013

Bài 5: Quản lý đối tượng

Giới thiệu


Trong bài trước, chúng ta đã nói về vòng đời đối tượng. Trong bài này chũng ta sẽ tìm hiểu sâu hơn về cách quản lý đối tượng AutoCAD. Như đã đề cập từ trước, mọi đối tượng đều có riêng một mã định danh là ObjectId. Đây là chìa khóa để  lấy được con trỏ và thực hiện các thao tác đọc ghi.

Phương thức truy cập tiêu chuẩn được thực hiện bởi quá trình OPEN (để ghi, để đọc hoặc để thông báo), một vài quá trình khác và cuối cùng là phương thức CLOSE. Cách tiếp cận khác, hiệu quả hơn nhiều là thông qua giao dịch. Cơ chế này vô cùng an toàn và hiệu quả. Hãy cùng nói về cả hai phương thức đó.

Sử dụng phương thức Mở / Đóng (OPEN / CLOSE)


Đây là phương thức sử dụng nhiều nhất, nhưng vô tình lại rất nguy hiểm vì bạn có thể quên đóng đối tượng và gây ra việc truy cập trái phép hoặc thậm chí là lỗi chí tử sẽ làm AutoCAD ngừng hoạt động.

Hàm tiêu chuẩn để mở một đối tượng là acdbOpenObject(). Hàm này sẽ mở mọi đối tượng dẫn xuất từ lớp AcDbObject và cung cấp cho bạn một con trỏ kiểu C++ để truy cập đến mọi thuộc tính và phương thức của đối tượng.
 Một trong những khai báo của hàm này là:

inline Acad::ErrorStatus acdbOpenObject(AcDbObject *& pObj, AcDbObjectId id, AcDb::OpenMode mode, bool openErased);
pObjCon trỏ tới đối tượng được mở
idMã định danh ObjectId của đối tượng
modePhương thức mở đối tượng (để đọc, để ghi hoặc thông báo)
openErasedBiến vào Boolean quyết định có mở đối tượng đã được xóa hay không

Hàm này nhận được một con trỏ rỗng tới AcDbObject bằng cách tham chiếu sẽ được điền bởi AutoCAD nếu tìm được đối tượng có mã Id tương ứng. Tiếp đến, bạn cần phải cung cấp dự định làm việc trên đối tượng, có thể là Ghi, Đọc hoặc Thông báo. Tham số cuối cùng quyết định xem bạn muốn mở đối tượng trong tình trạng bị xóa không. Hãy nhớ rằng chúng ta đã nói về việc đối tượng đã bị xóa nhưng vẫn tồn tại trong CSDL của AutoCAD cho đến khi bạn thực hiện quá trình ghi tệp tiếp theo.

Mục đích mở đối tượng rất quan trọng vì nó sẽ giới hạn việc bạn có thể thao tác trên đối tượng. Nếu bạn mở để Đọc , bạn sẽ không thể gọi các phương thức để thay đổi đối tượng. Nhưng nếu bạn mở để Ghi, bạn vừa có thể chỉnh sửa, vừa có thể đọc thông tin của đối tượng. Ah, vậy tốt hơn hết là mở để Ghi phải không?

Khẳng định là KHÔNG!

Khi mở một đối tượng dưới dạng Ghi, AutoCAD khởi động một vài thủ tục trước đó và gây ra quá tải hệ thống. Nếu thủ tục của bạn mở vài đối tượng khác nhau và cùng sử dụng phương thức Ghi, bạn sẽ mất mát tiến trình.

Cùng một đối tượng có thể được Đọc 256 lần một lúc nhưng điều đó không được khuyến cáo. Bạn phải luôn đóng đối tượng sớm nhất có thể. Nếu đối tượng được mở để Ghi, bạn không thể mở nó lần nữa để Ghi tiếp. Về cơ bản, bạn cần tuân thủ luật lệ sau:

Mở đối tượng với cách thức khác nhau
Đối tượng mở để:kForReadkForWritekForNotify
openedForReadeAtMaxReaderseWasOpenForRead(Succeeds)
openedForWriteeWasOpenForWriteeWasOpenForWrite(Succeeds)
openedForNotifyeWasOpenForNotifyeWasOpenForNotifyeWasOpenForNotify
wasNotifying(Succeeds)eWasNotifyingeWasNotifying
UndoeWasOpenForUndoeWasOpenForUndo(Succeeds)

Tốt hơn hết là luôn mở đối tượng dưới dạng Đọc, phân tích nếu bạn cần phải chỉnh sửa nó thì hãy nâng cấp thành tiến trình Ghi sử dụng phương thức upgradeOpen (). Phương thức này sẽ chuyển tình trạng của đối tượng từ Đọc sang Ghi. Quay trở lại tình trạng Đọc bằng phương thức downgradeOpen (). Các phương thức này rất hữu dụng. Một tiến trình đơn giản để sử dụng các phương thức này là:

void changeColor(AcDbObjectId id) {
AcDbEntity* pEnt = NULL;
if (acdbOpenObject(pEnt, id, AcDb::kForRead) == Acad::eOk) {
if (pEnt->colorIndex() != 3) {
pEnt->upgradeOpen();
pEnt->setColorIndex(3);
}
else {
acutPrintf(_T("\nEntity already has color=3"));
}
pEnt->close();
}
}

Sử dụng mô hình giao dịch

Giao dịch (transaction) là phương thức quản lý đối tượng tốt và hiệu quả hơn rất nhiều. Chúng có thể được lồng vào và nó cho phép thực hiện quá trình dài mà không hạn chế số lượng Đọc và Ghi. Về cơ bản, bạn mở một giao dịch, thực hiện các thay đổi, và cuối cùng thực hiện kết thúc hoặc hủy bỏ giao dịch.
Giao dịch rất tuyệt vời khi ứng dụng có sử dụng đến hộp thoại để thay đổi đối tượng. Khi hộp thoại được mở, bạn bắt đầu một giao dịch mới và, tùy thuộc khi người dùng chọn OK hoặc CANCEL, bạn gọi phương thức kết thúc hoặc hủy bỏ giao dịch.


Khi bạn hủy bỏ giao dịch, toàn bộ thay đổi trước đó sẽ bị hủy bỏ theo. Vì vậy, thay đổi chỉ được thực sự áp dụng chỉ khi bạn kết thúc giao dịch. Một đặc điểm tuyệt vời khác là bạn có thể mở đối tượng để Ghi hoặc Đọc nhiều lần cùng một lúc.

Không cần thiết phải đóng đối tượng trong một giao dịch. Phương thức kết thúc hoặc hủy bỏ sẽ đóng toàn bộ các đối tượng đang được mở và tiến hành thay đổi nếu cần thiết. Không khuyên bạn trộn lẫn quá trình chuẩn OPEN / CLOSE với Giao dịch TRANSACTIONS vì một vài giới hạn thiết kế. Bạn có thể tìm hiểu chi tiết về vấn đề này trong tài liệu SDK. Bây giờ hãy xem ví dụ về một giao dịch như sau:

    void changeColor(AcDbObjectId id) {
AcDbEntity* pEnt = NULL;
acdbTransactionManager->startTransaction();
if (acdbTransactionManager->getObject((AcDbObject*&)pEnt, id, AcDb::kForRead) == Acad::eOk) {
if (pEnt->colorIndex() != 3) {
pEnt->upgradeOpen();pEnt->setColorIndex(3);
}
else {
acutPrintf(_T("\nEntity already has color=3"));
}
}acdbTransactionManager->endTransaction();
}

Lần này, bạn mở đối tượng bằng phương thức getObject() cũng tương tự acdbOpenObject() nhưng bạn không cần phải đóng đối tượng. Toàn bộ quá trình chỉ kết thúc khi phương thức endTransaction() được gọi tới. Chỉ khi đó mọi thay đổi mới được áp dụng bằng một quá trình duy nhất.
 
Link nguồn: Arxdummies

Không có nhận xét nào:

Đăng nhận xét