Diskuzní fórum a databáze tipů a utilit pro AutoCAD, Inventor, Revit a další produkty Autodesk - od firmy Arkance Systems [www.cadforum.cz]
CZ | SK | EN | DE
Přihlášení
či registrace
   právě nás čte: 6854 

Vývojové prostředky AutoCADu

Použití .NET a ObjectARX v AutoCADu

Vývoj aplikací pro AutoCAD - přehled API, LISP

Vývojové prostředky AutoCADu AutoCAD API

Visual LISP, Visual Basic/VBA, Java, ObjectARX, ActiveX, Skripty
České vysoké učení technické Praha, Fakulta elektrotechnická
Bc. Srník Albert, albert.srnik@mybox.cz

Přidávání uživatelských dat

Stažení zdrojového kódu

V tomto příkladu se podíváme, čeho je schopna část uživatelské rozhraní .NET API. Začneme uživatelským kontextovým menu. Poté implementujeme modeless, ukotvitelnou paletu podporující Drag and Drop. Pak demonstrujeme vybírání entit z modálního formuláře.

Uživatelské kontextové menu

Doposud všechny naše kódy pouze reagovaly na příkazy definované atributem CommandMethod. Pro vykonání load-time initializace aplikace AutoCAD .NET umí implementovat specifickou třídu, která to dovolí. Abychom to mohli udělat, třída potřebuje implementaci rozhraní IExtensionApplication .NET a předložit atribut assembly-levelu, který specifikuje tuto třídu jako ExtensionApplication. Třída potom může reagovat na one-time načítací a uvolňovací události.

[assembly: ExtensionApplication(typeof(Lab6_CS.AsdkClass1))]
class AsdkClass1 : IExtensionApplication
{


Modifikujeme třídu pro implementaci tohoto rozhraní. Modré čáry, které se objeví, indikují, že zde jsou nějaké požadované metody k implementaci. Jmenovitě Initialize() a Terminate(). Když implementujeme rozhraní, tato bázová třída je čistě virtuální.

public void Initialize()
{
AddContextMenu();
}
public void Terminate()
{}


Pro přidání našeho menu musíme implementovat ‘ContextMenuExtension’ pro použití. Tato třída je členem jmenného prostoru Autodesk.AutoCAD.Windows namespace. K použití ContextMenuExtension potřebujeme inicializovat one with new, vyplnit nezbytné vlastnosti a konečně zavolat Application.AddDefaultContextMenuExtension(). Způsob, jakým kontextové menu funguje je, že pro každý údaj určujeme specifickou členskou funkci, která bude zavolána při kliknutí. Toto děláme pomocí .NET ‘Delegates’. Používáme C# keywords += and -=, abychom určili, že chceme aby byla událost řízena jednou z našich funkcí.
Přidáme ‘ContextMenuExtension’ členskou proměnnou, a následující dvě funkce pro přidání a odstranění našeho uživatelského kontextového menu.


void AddContextMenu()
{
try
{
m_ContextMenu = new ContextMenuExtension();
m_ContextMenu.Title = "Acme Employee Menu";
Autodesk.AutoCAD.Windows.MenuItem mi;
mi = new Autodesk.AutoCAD.Windows.MenuItem("Create Employee");
mi.Click += new EventHandler(CallbackOnClick);
m_ContextMenu.MenuItems.Add(mi);
Autodesk.AutoCAD.ApplicationServices.Application.AddDefaultContextMenuExtension(m_ContextMenu);
}
catch
{
}
}
void RemoveContextMenu()
{
try
{
if( m_ContextMenu != null )
{
Autodesk.AutoCAD.ApplicationServices.Application.RemoveDefaultContextMenuExtension(m_ContextMenu);
m_ContextMenu = null;
}
}
catch
{
}
}

Povšimněme si funkce ‘CallbackOnClick’. Tato funkce bude zavolána jako odpověď na výběr položky menu. V našem příkladu je vše, co chceme, aby byla zavolána naše členská funkce ‘Create()’.

void CallbackOnClick(object Sender, EventArgs e)
{
Create();
}


Nyní zavoláme funkci AddContextMenu() z Initialize(), a zároveň RemoveContextMenu() z Terminate().
Data AutoCADu (včetlě výkresových databází) jsou uložena v dokumentech, kde příkazy, které přistupují k entitám uvnitř mají práva provádět modifikace. Když spustíme náš kód v odpovědi na kliknutí kontextového menu, přistupujeme k dokumentu zvenčí struktury příkazu. Když kód, který zavoláme zkusí změnit dokument přidáním Employee, spadne to. Abychom to udělali správně, musíme zamknout dokument pro přístup a pro toto používáme metodu Document.LockDocument().

void CallbackOnClick(object Sender, EventArgs e)
{
DocumentLock docLock = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.LockDocument();
Create();
docLock.Dispose();
}


Když teď spustíme kód, máme pracující kontextové menu.

Modeless ukotvitelné paletové okno s Drag and Drop


S .NET Spomůžeme vytvořit jednoduchý formulář a začlenit ho v našich paletách. Můžeme vytvořit instanci uživatelského objektu ‘PaletteSet’ pro obsažení našeho formuláře a upravení sady palet styly, které preferujeme.
Přidáme nový UserControl do projektu kliknutím pravého tlačítka na projekt v Solution Esploreru a vybereme ‘User Control’. Pojmenujeme ho jako ‘ModelessForm’. Použijeme ‘ToolBox’ k přidání ‘Edit Boxů’ a ‘Labelů’.
Použijeme okno ‘Properties’ k nastavení tří edit boxů. Nastavíme parametry::


(Name) = tb_Name
Text =


(Name) = tb_Division
Text = Sales


(Name) = tb_Salary
Text =

<’Drag to Create Employee’ Label> (Step 7, Below)
(Name) = DragLabel
Text = ‘Drag to Create Employee’


Za účelem vytvoření instance objektu palety s .NET API jsou vytvořeny instance uživatelsky ovládaného objektu (náš ModelessForm), a objektu ‘. Člen The PaletteSetu Add je volán předávaním uživatelsky ovládaného objektu a po zavolání.

Dále potřebujeme přidat příkaz pro vytvoření palety. Přidáme funkci do třídy zvanou CreatePalette a CommandMethod(), terý definuje příkaz nazvaný “PALETTE”. Toto je kód, který vytváří instanci palety:

ps = new Autodesk.AutoCAD.Windows.PaletteSet("Test Palette Set");
ps.MinimumSize = new System.Drawing.Size(300, 300);
System.Windows.Forms.UserControl myCtrl = new ModelessForm();
//ctrl.Dock = System.Windows.Forms.DockStyle.Fill;
ps.Add("test", myCtrl);
ps.Visible = true;


Přidáme kód do metody CreatePalette(). ‘ps’ musí být deklarováno vně definice funkce:

ps.Style = PaletteSetStyles.ShowTabForSingle;
ps.Opacity = 90;

Poznámka: Budete potřebovat přidat dva jmenné prostory pro objekty PaletteSet and PaletteSetStyles.
Než budeme pokračovat, provedeme rychlou úpravu. Přidáme následující členy do třídy AsdkClass1.

public static string sDivisionDefault = "Sales";
public static string sDivisionManager = "Fiona Q. Farnsby";


Tyto hodnoty budou použity jako defaultní pro Division a Division Manager. Když jsou deklarovány jako statické, jsou vytvářeny jejich instance jednou za instanci aplikace v assembly-load time.

Podpora Drag and Drop Support v Modeless formuláři:

Když uživatel přetáhne z palety do AutoCAD editoru, je získána pozice a je vytvořena nová instance Employee používající tyto hodnoty.
Nejdřív potřebujeme objekt na přetažení. Přidáme dodatečná ‘Label’ náležící textovým boxům pojmenovaný DragLabel a nastavíme text na něco jako ‘Drag to Create Employee’. Z tohoto labelu budeme schopni ovládat drag and drop do editoru AutoCADu. K detekování, kdy událost přetažení proběhne, potřebujeme vědět, kdy probíhají určité operace s myší. Nejdříve potřebujeme zaregistrovat událost následujícím kódem v konstruktoru třídy:

DragLabel.MouseMove += new System.Windows.Forms.MouseEventHandler(DragLabel_MouseMove);


Přídáme tuto funkci do deklarace třídy ModelessForm:

private void DragLabel_MouseMove( object sender, System.Windows.Forms.MouseEventArgs e)
{
if (System.Windows.Forms.Control.MouseButtons == System.Windows.Forms.MouseButtons.Left)
{
}
}


Běžně ovladače událostí vezmou dva argumenty. Odesilatele jako objekt a ‘event arguments’. Pro pohyb myši musíme udělat to samé.
Nyní víme, kdy probíhá operace pohybu myši. Můžeme jít dál a říct, že levé tlačítko mysi je právě stisknuté.

if (System.Windows.Forms.Control.MouseButtons == System.Windows.Forms.MouseButtons.Left)
{
}


Potřebujeme znát způsob, jak detekovat, kdy je objekt puštěn. K tomu použijeme bázovou třídu .NET s názvem DropTarget. Jednoduše vytvoříme třídu, která dědí od této bázové a implementuje metodu, kterou potřebujeme. V našem případě jde o OnDrop().
Přidáme třídu nazvanou ‘MyDropTarget’ do projektu, která dědí od ‘Autodesk.AutoCAD.Windows.DropTarget’. Když přidáme tuto třídu do souboru ModelessForm.cs file, musíme se ujistit, že jsme přidali třídu za třídu ModelessForm. Uvnitř této nové třídy vložíme handler pro OnDrop ebeny.

override public void OnDrop(System.Windows.Forms.DragEventArgs e)
{}


Uvnitř této funkce budeme chtít volat členy AsdkClass1 CreateDivision() a CreateEmployee(), předáním hodnot z tb_xxx edit boxů v ModelessForm class. Abychom to udělali, potřebujeme způsob, jak spojit instanci ModelessForm s touto třídou. Njelepší cesta je přes DragEventArgs. Nejdříve musíme spojit událost myši k třídě MyDropTarget.
Přidáme následující řádek dovnitř MouseButtons.Left klauzule klauzule zpět v handlenu mouse-move. MyDropTarget bude zavolán, když kurzor vstoupí do prohlížecí oblasti AutoCADu.

Autodesk.AutoCAD.ApplicationServices.Application.DoDragDrop(this, this,System.Windows.Forms.DragDropEffects.All, new MyDropTarget());


Všimněte si, že jsme předávali ‘this’ dvakrát. Poprvé je to pro argument ‘Control’ argument, a podruhé pro uživatelsky definovaná data, která jsou předávána. Poté, co předíme instanci třídy ModelessForm, můžeme ji použít k získání hodnot edit boxů v čase pustění(drop-time).
Všimněte si, že jsme vytvořili instanci třídy DropTarget jako poslední argument.To je jak náš MyDropTarget override je začleněn do mechanismu.
Zpět v handleru OnDrop použijeme argument DragEventArgs k získání pozice kurzoru v moment puštění. Pak můžeme toto konvertovat do souřadnic předtím než zavoláme CreateDivision a CreateEmployee.

Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
try
{
Point3d pt = ed.PointToWorld(new Point(e.X, e.Y));
//…


Vyprostíme objekt ModelessForm předaný uvnitř argumentu DragEventArgs.

ModelessForm ctrl = (ModelessForm)e.Data.GetData(typeof(ModelessForm));


Zavoláme členy AsdkClass1.

AsdkClass1.CreateDivision(ctrl.tb_Division.Text, AsdkClass1.sDivisionManager);
AsdkClass1.CreateEmployee(ctrl.tb_Name.Text, ctrl.tb_Division.Text, Convert.ToDouble(ctrl.tb_Salary.Text), pt);


Volání metody AsdkClass1 bez instance AsdkClass1 vyžaduje, aby funkce byly deklarovány jako ‘public static’. Poté co mohou veřejné statické metody volat jiné veřejné statické metody, budeme potřebovat změnit několik deklarací funkcí v AsdkClass1 pro použití ‘public static’. Provedeme tyto změny.

Konečně, poté co jsme znovu používali události z vnějšku kontextu příkazů AutoCADu, musíme znovu provést zmaknutí dokumentu kolem kódu, který bude modifikovat databázi. Uzamkneme stejně, jako jsme to udělali pro kontextové menu.

Entita vybraná z modálního formuláře


Zde se zaměříme na tvorbu modálního formuláře a jeho skrývání. K získání detailů employee použijemee pomocnou funkci ListEmployee.Nejdříve potřebujeme vytvořit novou třídu formuláře.
Vytvoříme novou třídu Windows Form v projektu. Zavoláme třídu ‘ModalForm’. Přidáme tři Edit boxes s labely a dvě tlačítka. Použijeme okno vlastností k nastavení tří edit boxů. Nastavíme vlastnosti na:

this.Close();

K zobrazení dialogu vytvoříme příkazovou metodu v této třídě, která vytvoří instantce formuláře jako modální dialog.

public void ShowModalForm()
{
ModalForm modalForm = new ModalForm();
Autodesk.AutoCAD.ApplicationServices.Application.ShowModalDialog(modalForm);
}


Tlačítko ‘Select Employee’ nejdříve vybere jednoduchý výběr entity. Pro toto použijeme metodu Editor.GetEntity().

PromptEntityResult prEntRes = ed.GetEntity(prEnt);


Přidáme kód do těla handlenu SelectEmployeeButton_Click s nezbytnými nastaveními proměnných databází, editoru, transakce, Try Catch bloku. Nesmíme zapomenout na Dispose.
Otestujeme návratovou hodnotu GetEntity proti PromptStatus.OK. Pokud se nerovnají, zavoláme toto.Show a opustíme handler.
Jakmile máme výsledek a je OK, múžeme zkusit použít metodu PromptEntityResult.ObjectId() pro získání Id objektu pro vybranou entitu. Toto ID může být předáno do funkce AsdkClass1.ListEmployee, dále s fixovaným polem stringů můžeme získat detaily


(Name)= tb_EmployeeDivision
Text =


(Name) = tb_DivisionManager
Text =


K zobrazení uživatelského tab dialoguv .NET API musíme udělat dva kroky. Prvním je zapsání do oznámení pro kdy je dialog vlastností spustěn předáním adresy členské funkce k zavolání. Druhým krokem je implementace odvolávací funkce. Druhý argument předaný callbacku je objekt ‘TabbedDialogEventArgs’, který musíme použít pro zavolání jeho členu ‘AddTab’. AddTab vezme takes a title string, a instanci objektu ‘TabbedDialogExtension’, který zabalí náš formulář. Uvnitř konstruktoru TabbedDialogExtension předáváme novou instanci našeho formuláře a Voláme zpět adresy, které můžeme předat k řízení jako OnOK, OnCancel or OnHelp.

Uvnitř třídy EmployeeOptions přidáme public static funkci nazvanou AddTabDialog která přidává handler pro sysém k volání:

public static void AddTabDialog()
{
Autodesk.AutoCAD.ApplicationServices.Application.DisplayingOptionDialog += new TabbedDialogEventHandler(TabHandler);
}


Pokračujeme a naimplementujeme obdobnou třídu, která odstraní handler použitím klíčového slova -= .
Přidáme následující kód, abychom implementovali handler:

private static void TabHandler(object sender, Autodesk.AutoCAD.ApplicationServices.TabbedDialogEventArgs e)
{
EmployeeOptions EmployeeOptionsPage = new EmployeeOptions();
e.AddTab("Acme Employee Options",
new TabbedDialogExtension(
EmployeeOptionsPage,
new TabbedDialogAction(EmployeeOptionsPage.OnOk)));
}


Zde jsme poprvé vytvořili instanci objektu EmployeeOptions. Pak voláme e.AddTab(), předáváme novou instanci objektu TabbedDialogExtension a TabbedDialogAction specifikující, kde zavolat pro tři kacem které jsem zapsali: Ok, Cancel a Help. V tomto příkladi vybereme pouze OK. Jsou tu dvě další override vorte konstruktoru TabbedDialogAction, které řídí ostatní.
Nyní vše, co zbývá, je specifikovat, co se stane v našem volání, které by mělo být ‘OnOK’. Hodláme pouze vyplnit sdílené členy třídy hodnotami přidanými do tb_DivisionManager a tb_EmployeeDivision Edit boxů.

public void OnOk()
{
AsdkClass1.sDivisionDefault = tb_EmployeeDivision.Text;
AsdkClass1.sDivisionManager = tb_DivisionManager.Text;
}