先回お知らせした「AutoCAD 2014 JavaScript APIと既存APIとの連携の開発環境」を使い、JavaScript API と .Net Managed APIによる以下の連動したカスタマイズと、htmlとJavaScript APIによるデータベースI/O処理について掲載させていただきます。
これは、dotNetカスタムコマンド内より、JavaScript APIでコーディングされた html ファイルと jsファイルをAPIによってロードするカスタマイズの方法を理解していただくと共に、パレットとしてhtmlファイルを表示させ、パレット上の各ボタンからは、dotNetカスタムコマンド環境内のdotNetManagedクラス(dotNet API)を使い、データベースアクセス処理およびJavaScriptからの引数情報でオブジェクトの追加処理を実行させる(既存のdotNetAPIで作成されたカスタムコマンド処理を動作させることをイメージとしたサンプル)のほか、パレット上のボタンから直接JavaScript( js )ファイル内にコーディングされたJavaScript APIを使って JavaScriptファイルとhtml間のオブジェクト情報のI/O の動作の理解を目的としています。
今回の処理の内容:
1. Netカスタムコマンドを使ってhtmlとJavaScriptファイルをロードしツールパレットにhtmlを表示
2. htmlのボタン1 -> JavaScript -> .Netマネージコードでデータベースへ追加処理の呼び出し
(呼び出された.Netカスタムコマンド内で、Json.Netを使いJavaScriptから引数の引き渡しデータを使ってデータベースへ線分とテキストオブジェクトの追加処理)
3. htmlのボタン2-> JavaScript -> .Netマネージコードでデータベースクエリー処理の呼び出し
(呼び出された.Netカスタムコマンド内で、データベースのクエリー処理)
4. htmlのボタン3 -> JavaScript -> JavaScript APIでリアクタ処理の追加
(JavaScript API を使ってオブジェクトにリアクタをセットし、Object ID一覧をhtml上に表示)
5. htmlのボタン4 -> JavaScript -> JavaScript APIでリアクタ処理の解除
(JavaScript API を使って、オブジェクトに付加されたリアクタの解除処理を実行)
<< Htmlファイルの作成とコーディング >>
(1). VS Express 2012 for Webを起動し、JsLaunch.html を作成し、”ボタン”を4つと、”テキストエリア”を2つ配置する。
(a). [ファイル] -> [ 新しいファイル ] -> [ Webタブ ] を選択し、テンプレートより[ HTML ページ ]を選択し[ 開く ] ボタンを押す。
(b). [デザイン]を選択し [ ツールボックス ] -> [ Input(Button) ] をドラッギングして“ボタン”を4つ配置し、続いて”Textarea” をドラッギングして“テキストエリア”を2つ配置する。
(2). エディタ上の [ ソース ] タブで切り替えて、html のコーディングを開始する。
以下は、“デザイン”タブで確認した、完成した html の 表現となります。
注意:ブログ掲載の都合上、htmlタグ < > の前後に半角スペースが挿入されていますので、ご注意ください。
① < head >タグ内のタイトルと、JavaScriptAPI用の Autodesk.AutoCAD.js とカスタマイズ用の JsLaunch.js を定義し、
の動作時のファンクションを onMyLoadとして定義。< head >
< meta charset=”utf-8″ / >
< title >JavaScript連動動作< /title >
< script type =”text/javascript” src = “http://www.autocadws.com/jsapi/v1/Autodesk.AutoCAD.js”>< /script >
< script type =”text/javascript” src = “JsLaunch.js” >< /script >
< script type =”text/javascript” >
function onMyLoad() {
write(” HtmlページよりJ avaScriptをロード”);
}
< /script >
② < head >タグ内に“< style type”タグを使って< body >の背景とフォントと文字種類と大きさ、テキストエリアのフォントと文字種類と大きさを設定
< style type="text/css" ><br />
body {font-family: sans-serif; font-size: 10pt;
background-color: #686868;
color:#FFF;
}
textarea {font-family: Consolas; font-size: 8pt; }
#EventEntity{
height: 96px;
}
#EventLog {
height: 89px;
margin-bottom: 5px;
}
< /style >
< /head >
③ < body >タグ内に起動時のonMyLoad()ファンクションを追加し、各ボタンが押されたときに onclick を使って jsファイル側の起動関数の呼び出し「Button1は’NetCmdRead()’」でボタン文字は’.Net側のRead’」、「Button2は’ NetCmdWrite()’」でボタン文字は’.Net側のWrite ‘」、「Button3は’ JavaSelectEntity()’」でボタン文字は’ JavaScript側で監視開始’」、「Button4は’ JavaStopEventEntity ()’」でボタン文字は’ JavaScript側で監視終了’」に変更し、テキストエリアは、それぞれcols=”30″ rows=”10″ に変更する。
< body onload =”onMyLoad()” >
< p > コマンド:< br/ >
< input id=”Button1″ type=”button” style=’width: 200px’ onclick= NetDBAdd ()’ value=’.Net側のdotNetDBAdd関数’ / >< br / >
< input id=”Button2″ type=”button” style=’width: 200px’ onclick=’NetDBAccess()’ value=”.Net側のdotNetDBAccess関数” / >< br / >
< input id=”Button3″ type=”button” style=’width: 200px’ onclick=’JavaSelectEntity()’ value=”JavaScript側で監視開始” / >< br / >
< input id=”Button4″ type=”button” style=’width: 200px’ onclick=’JavaStopEventEntity()’ value=”JavaScript側で監視終了” / >< /p >
< p > 監視するエンティティ:< br/ >
< textarea id=” EventEntity” cols=”30″ name=”S1″ rows=”10″ readonly=”readonly” >< /textarea >< /p >
< p > エンティティのログ:< br/ >
< textarea id=” EventLog” cols=”30″ name=”S2″ rows=”10″ readonly=”readonly” >< /textarea >< /p >
< /body >
(3). [ファイル] -> [ HtmlPage1.html の保存 ] にて、任意のホルダに [ ファイル名 ] を JsLaunch.html として保存する。
<< JavaScriptファイルの作成とコーディング >>
(1). VS Express for 2012 Webを起動し、JsLaunch.js を作成し、”ボタン”を4つと、”テキストエリア”を2つ配置する。
(a). [ファイル] -> [ 新しいファイル ] -> [ Webタブ ] を選択し、テンプレートより[ JavaScript ファイル ]を選択し[ 開く ] ボタンを押す。
① ボタン1:の実装
//——————————————————————–
// Button1
// .Net側のdotNetDBAdd関数を呼び出す関数
// execAsyncでJSON.stringifyを使い引数付でdotNet側の「dotNetDBAdd」を呼ぶ
//——————————————————————–
// dotNet側に引き渡す情報
var stPoint = new Acad.Point3d(10, 10, 0);
var enPoint = new Acad.Point3d(20, 20, 0);
var hight = 5;
function NetDBAdd() {
execAsync(JSON.stringify({
functionName: ‘dotNetDBAdd’, // dotNet側の関数名
invokeAsCommand: false, // コマンド
functionParams: {
stPoint: stPt, // 直線の開始点
enPoint: enPt, // 直線の終了点
hight: ht // テキストの文字高さ
}
}),
OnNetSuccess, // dotNet側からの成功時に呼び出すJS側の関数
OnNetError); // dotNet側からのエラー時に呼び出すJS側の関数
}
② ボタン2:の実装
//——————————————————————–
// Button2
// .Net側のdotNetDBAccess関数を呼び出す関数
// execAsyncでJSON.stringifyを使い、dotNet側の「dotNetDBAccess」を呼ぶ
//——————————————————————–
function NetDBAccess() {
execAsync(JSON.stringify({
functionName: ‘dotNetDBAccess’, // dotNet側の関数名
invokeAsCommand: false, // コマンド
functionParams: { args: ‘args’ } // 引数名 args
}),
OnNetSuccess, // dotNet側からの成功時に呼び出すJS側の関数
OnNetError); // dotNet側からのエラー時に呼び出すJS側の関数
}
// dotNet側からの成功時に呼び出すJS側の関数
function OnNetSuccess(result) {
write(“\n”);
}
// dotNet側からのエラー時に呼び出すJS側の関数
function OnNetError(result) {
write(“\nOnParseError: ” + result);
}
③ ボタン3:の実装
//——————————————————————–
// Button3
// JavaScript側でObjectの選択と監視開始ボタンの動作用関数
//——————————————————————–
// イベントが付加されたオブジェクト郡用のコレクション
// AutoCADのオブジェクト識別子のコレクションとして初期化
var oEventEnt = new Acad.OSet();
// htmlの「エンティティのログ:」テキストアリア(EventLog)を確保し
// ObjectModifiedイベントで反応したオブジェクトの情報を追加表示
function onObjectModified(eventname, args) {
var TextLog = document.getElementById(‘EventLog’);
TextLog.value = TextLog.value + “オブジェクトの修正: ” + args.id + ‘\n’;
}
// htmlの「エンティティのログ:」テキストアリア(EventLog)を確保し
// Erasedイベントで反応したオブジェクトの情報を追加表示
function onObjectErased(eventname, args) {
var TextLog = document.getElementById(‘EventLog’);
TextLog.value = TextLog.value + “オブジェクトの削除: ” + args.id + ‘\n’;
}
// Acad.Editor.getEntityで正常の場合に呼び出される関数
// JSON.parseを使って引数の実行結果の解析
function onComplete(jsonPromptResult) {
// JSON.parseを使って引数の実行結果の解析
var resultObj = JSON.parse(jsonPromptResult);
if (resultObj) {
// 正常の場合<br />
if (resultObj.status == 5100) {
// htmlの「監視するエンティティ:」テキストアリア(EventEntity)を確保し
// 選択されたオブジェクトの情報を追加表示
var TextIds = document.getElementById(‘EventEntity’);
EventEntity.value = EventEntity.value + resultObj.objectId + ‘\n’;
// AutoCADのオブジェクト識別子のコレクションに<br />
// 選択オブジェクトされたオブジェクトを追加
oEventEnt.add(resultObj.objectId);
// オブジェクトの「modified」イベント通知をセット<br />
Acad.Application.activedocument.startObserving(
oEventEnt,
Acad.Application.activedocument.eventname.modified,
onObjectModified);
// オブジェクトの「erased」イベント通知をセット
Acad.Application.activedocument.startObserving(
oEventEnt,
Acad.Application.activedocument.eventname.erased,
onObjectErased);
}
//キーワードの入力は何もしない<br />
else if (resultObj.status == -5005) {
}
// リターン/スペースバー=null入力は何もしない<br />
else if (resultObj.status == 5000) {
}
// キャンセルキーは何もしない<br />
else if (resultObj.status == -5002) {
}
//その他も何もしない<br />
else {
}
}
}
// 選択のエラー
function onError(jsonPromptResult) {
write(“選択エラー: ” + jsonPromptResult);
var resultObj = JSON.parse(jsonPromptResult);<br />
if (resultObj) {
}
}
// 実際にhtml側の「ボタン3」が押された時に呼び出される関数
function JavaSelectEntity() {
try {
// エンティティ選択用のPromptEntityOptionsを用意し
// 選択条件をセット
var peo = new Acad.PromptEntityOptions();
peo.setMessageAndKeywords(“\nエンティティの選択:”, “”);
peo.rejectMessage = “\n無効なオブジェクトの選択です”;
peo.singlePickInSpace = true;
peo.allowObjectOnLockedLayer = true;
// エンティティの選択<br />
// 正常=onComplete, エラー= onErrorの呼び出し
Acad.Editor.getEntity(peo).then(
onComplete,
onError);
}
catch (e) {
write(e.message);
}
}
④ ボタン4:の実装
//——————————————————————–
// Button4
// JavaScript側で監視終了ボタンの動作用関数
// テキストエリアの初期化・各イベント通知の中止・
// イベントが付加されたオブジェクト郡用のコレクションの初期化
//——————————————————————–
function JavaStopEventEntity() {
// htmlの「監視するエンティティ:」テキストアリア(EventEntity)のクリア
var TextIds = document.getElementById(‘EventEntity’);
EventEntity.value = “”;
// htmlの「エンティティのログ:」テキストアリア(EventLog)のクリア
var TextLog = document.getElementById(‘EventLog’);
EventLog.value = “”;
// オブジェクトの「modified」イベント通知を中止<br />
Acad.Application.activedocument.stopObserving(
oEventEnt,
Acad.Application.activedocument.eventname.modified,
onObjectModified);
// オブジェクトの「erased」イベント通知を中止
Acad.Application.activedocument.stopObserving(
oEventEnt,
Acad.Application.activedocument.eventname.erased,
onObjectErased);
// イベントが付加されたオブジェクト郡用のコレクションの初期化
oEventEnt = new Acad.OSet();
}
(2). [ファイル] -> [JavaScript1.js の保存 ] にて、任意のホルダに [ ファイル名 ] を JsLaunch.js として、JsLaunc.htmlファイルと同じホルダに保存する。<- 注意してください。
<< C# dotNetカスタムコマンドの作成とコーディング >>
(1). VS Express 2012 for Desktopを起動し、.Net C#言語で JsLaunchCmd プロジェクトを作成する。
(a). [ファイル] -> [ 新しいファイル ] ->テンプレートより[ Visual C# ] ->[ Autodesk ]を選択し[ Autodesk 2014 CSharp plug-in ]を選択し、名前を[ JsLaunchCmd ]、場所を[JsLaunchCmd ]( JsLaunch.html とJsLaunch.js ファイルの格納ホルダ ) 、ソリューションのディレクトリを作成チェックボックスをOn にして[ 開く ] ボタンを押す。
(b). [AutoCAD .NET Wizard Configurator ] で ObjectARX SDKのホルダーを [C:\Autodesk_ObjectARX_2014_Win_64_and_32Bit\inc ] 、AutoCAD 2014のホルダーを[C:\Program Files\Autodesk\AutoCAD 2014 ]として[ OK ] ボタンを押す。
(c). 参照設定で[ AcCoreMgd , AcDbMgd , AcMgd ] の [ ローカルコピー ] が [ False ] で [ バージョン ] が [ 19.1.0.0 ] であるか確認する。
(d). 参照設定の [ 参照の追加 ] で [ System.Windows.Forms ] を追加する。
(2) . JsLaunch.html ファイルをロードしパレットに表示するコマンドを作成する。
(a). [ソリューションエクスプローラー] で [myCommands.cs ] を選択し、コマンド名を[ AdnJsLoad ] とする。
(b). GetStringメソッドでJsLaunch.htmlのホルダー名の入力後に、パレットセットを確認して[ツール] -> [ GUIDの作成 ] にて作成した 唯一無二のGUIDを用いてPaletttsetを追加する。
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptResult filepath = ed.GetString(“\nJsLaunch.htmlファイルのホルダー名をフルパスで入力 : “);
if (filepath.Status != PromptStatus.OK)
return;
string filename = filepath.StringResult + “\” + “” + “JsLaunch.html”;
// JsLaunch.htmlファイルの存在の確認
if (System.IO.File.Exists(filename))
{
// パレットセットを確認して、PaletteSetの追加
if (oPaletttset == null)
{
// 第2引数のGuidは「ツール」->「Guidの作成」で作成します
oPaletttset = new Autodesk.AutoCAD.Windows.PaletteSet(
“JavaScript連動動作”,
new Guid(“AE909B5F-9245-4DDE-AC9F-A427F1771DE0”));
}
// U.R.L 文字に変換
String url = “file:///” + filename;
try
{
String tabName = “”;
Uri uri = new Uri(url);
if (uri.IsFile)
{
//セグメントよりタブを抽出
String[] segments = uri.Segments;
if (segments.Length > 0)
{
tabName = segments[segments.Length – 1];
String[] fileSplit = tabName.Split(‘.’);
if (fileSplit.Length > 0)
tabName = fileSplit[0];
}
}
else
{
tabName = uri.Host;
}
// パレットの存在を確認し更新のために、一旦削除する
if (oPaletttset.Count != 0)
{
oPaletttset[0].PaletteSet.Remove(0);
}
// パレットの追加表示
Autodesk.AutoCAD.Windows.Palette p = oPaletttset.Add(tabName, uri);
oPaletttset.Visible = true;
}
catch (UriFormatException ex)
{
ed.WriteMessage(“U.R.Lが見つかりません : ” + ex.Message);
}
}
else
{
ed.WriteMessage(filename + “ファイルは見つかりません”);
}
(3). JsLaunch.htmlの“ボタン1”が押された時の処理を作成する。
JavaScriptからdotNet環境の「JavaScriptCallback」に引数を渡すにはJson.Net環境を利用する方法があります。
このJson.Netは以下の手順で、使用するプロジェクトにインストールして組み込むことができます。
コーディング内で使用するに当たり、myCommands.csの先頭に“using Newtonsoft.Json.Linq;”を追加
using Newtonsoft.Json.Linq;
// ———————————————————-
// ボタンで1呼び出される関数
// JavaScriptより引き渡された引数を、Json.Netを使って開始点と終了点に変換し
// Lineの作成 及び 終了点と文字高さを使って DBTestの作成
[JavaScriptCallback(“dotNetDBAdd”)]
public string dotNetDBAdd(string jsonArgs)
{
// 引数を変換( Json.NetによるJObjectを使用 )
var o = JObject.Parse(jsonArgs);
// 開始点の作成
var sx = (double)o[“functionParams”][“stPoint”][“x”];
var sy = (double)o[“functionParams”][“stPoint”][“y”];
var sz = (double)o[“functionParams”][“stPoint”][“z”];
var stPoint = new Point3d(sx, sy, sz);
// 終了点の作成
var ex = (double)o[“functionParams”][“enPoint”][“x”];
var ey = (double)o[“functionParams”][“enPoint”][“y”];
var ez = (double)o[“functionParams”][“enPoint”][“z”];
var enPoint = new Point3d(ex, ey, ez);
// 文字高さの作成
var high = (double)o[“functionParams”][“hight”];
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;<br />
Database db = doc.Database;
Editor ed = doc.Editor;
//ドキュメントをロックする<br />
using (DocumentLock lk = doc.LockDocument())
{
using (Transaction tx = doc.TransactionManager.StartTransaction())
{
BlockTableRecord btr = tx.GetObject(db.CurrentSpaceId, OpenMode.ForWrite)
as BlockTableRecord;
// 開始点と終了点を使って Lineの作成
Line oLine = new Line(stPoint, enPoint);
btr.AppendEntity(oLine);
tx.AddNewlyCreatedDBObject(oLine, true);
// 終了点と文字高さを使って DBTestの作成
DBText otext = new DBText();
otext.TextString = “JavaScriptからの起動指示”;
otext.Position = enPoint ;
otext.Height=high;
btr.AppendEntity(otext);
tx.AddNewlyCreatedDBObject(otext, true);
// コミット
tx.Commit();
}
}
return “{\”retCode\”:0, \”result\”:\”OK\”}”;
}
(4). JsLaunch.htmlの“ボタン2”が押された時の処理を作成する。
JavaScriptCallback ステートメントを使って、JavaScriptより呼び出し可能な”dotNetDBAccess” コマンドを作成する。
[JavaScriptCallback(“dotNetDBAccess”)]
public string dotNetDBAccess(string jsonArgs)
{
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
using (Transaction tx = doc.TransactionManager.StartTransaction())<br />
{
BlockTableRecord btr = tx.GetObject(db.CurrentSpaceId, OpenMode.ForRead)
as BlockTableRecord;
ed.WriteMessage(“\nブロックテーブルレコード内のダンプ”);
foreach (ObjectId id in btr)
{
ed.WriteMessage(“\nエンティティ: ” + id.ObjectClass.Name);
}
tx.Commit();<br />
}
return "{\"retCode\":0, \"result\":\"OK\"}";<br />
}
(5). [ ビルド ] -> [ ソリューションのビルド ] にて エラーの無いことを確認する。
(6). [ ファイル ] -> [ 全てを保存 ] にて プロジェクトを含むすべてのファイルを保存する。
<< 実行と確認 >>
(1). [ NETLOAD ] コマンドで-> [JsLaunchCmd.dll ] ロード。
例、C:\AdnJavaDemoホルダにVisualStudioのC#プロジェクトを作成したならば、以下となります。
C:\AdnJavaDemo\JsLaunchCmd\JsLaunchCmd\bin\Debug\ JsLaunchCmd.dll
(2).コマンドラインより[ ADNJSLOAD ] コマンドを起動して、フルパス入力文字に” C:\AdnJavaDemo” を入力し確認する。
(3).セキュリティ警告ダイアログが現れる場合は、以下の[ Autodesk-Technical Q&A ] を参照してシステム変数TRUSTEDPATHS および TRUSTEDDOMAINS への追加変更をお願いします。
セキュリティ警告ダイアログについて
http://tech.autodesk.jp/faq/faq/adsk_result_dd.asp?QA_ID=7977
サンプルプロジェクト一式は ここより ダウンロードいただけます。
Shigekazu Saito.

Leave a Reply