Autodesk Community Tips- ADNオープン
Autodesk Community Tipsではちょっとしたコツ、やり方、ショートカット、アドバイスやヒントを共有しています。
ソート順:
Issue 選択セットで条件に合った複数のオブジェクトを取得する際、特定の座標を持つ要素を条件に設定するにはどうしたらいいでしょうか?   Solution 選択セットのフィルタリングで座標を扱う際には、オンラインヘルプ 概要 - 選択セットのフィルタ リストでの関係テスト(AutoLISP) で触れられている、カンマ区切りで関係演算子を利用する方法を利用することが出来ます。   点グループ コードの場合、X、Y、Z に対するテストを結合して単一の文字列にできます。このとき、各演算子をカンマで区切ります(たとえば、">,>,*")。文字列から演算子を省略すると、すべてを選択する演算子 "*" とみなされます(たとえば、"=,<>" では Z がチェックされません)。 次のコードは、円オブジェクトの中心のX 座標が 123.45 以上123.46 以下で、Y 座標が 500.0、Z 座標値を無視するフィルタリングを指定した C# コードの例です。 Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; TypedValue[] typeAry = new TypedValue[9]; typeAry.SetValue(new TypedValue((int)DxfCode.Operator, "<and"), 0); typeAry.SetValue(new TypedValue((int)DxfCode.Start, "CIRCLE"), 1); typeAry.SetValue(new TypedValue((int)DxfCode.Operator, "<and"), 2); typeAry.SetValue(new TypedValue((int)DxfCode.Operator, ">=,=,*"), 3); typeAry.SetValue(new TypedValue((int)DxfCode.XCoordinate, new Point3d(123.45, 500.0, 0.0)), 4); typeAry.SetValue(new TypedValue((int)DxfCode.Operator, "<=,=,*"), 5); typeAry.SetValue(new TypedValue((int)DxfCode.XCoordinate, new Point3d(123.46, 500.0, 0.0)), 6); typeAry.SetValue(new TypedValue((int)DxfCode.Operator, "and>"), 7); typeAry.SetValue(new TypedValue((int)DxfCode.Operator, "and>"), 8); SelectionFilter filter = new SelectionFilter(typeAry); PromptSelectionResult psr = ed.SelectAll(filter); if (psr.Status == PromptStatus.OK) { SelectionSet sset = psr.Value; ed.WriteMessage("\nNumber of objects selected : {0}", sset.Count.ToString()); ObjectIdCollection objIds = new ObjectIdCollection(sset.GetObjectIds()); using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent; foreach (ObjectId objId in objIds) { ent = (Entity)tr.GetObject(objId, OpenMode.ForRead); ent.Highlight(); } tr.Commit(); } } else { Application.ShowAlertDialog("\nNumber of objects selected: 0"); }  
記事全体を表示
現象 C#のコンソールアプリケーションで、Inventor Apprentice Server のApprenticeServerDocument.Thumbnailプロパティにアクセスするとエラーが発生します。 回避方法はありますか。   解決策 C#のコンソールApplicationの場合、Main関数に[STAThread]属性を付加しSTAで動作するように指定することで、Thumbnailプロパティにアクセスできるようになります。   [STAThread] static void Main(string[] args) {   なお、VB.netの場合コンソールアプリケーションはデフォルトでSTAで動作する設定のため、[STAThread]属性を付加する必要はありません。 また、C#の場合でもWindows フォームアプリケーションの場合も[STAThread]属性を付加する必要はありません。
記事全体を表示
Issue オンラインヘルプ「レイアウトをパブリッシュする(.NET) 」の例では、PublishExecute メソッドを利用して DSD ファイルを使ったバッチ印刷の方法を説明しています。ただし、この例では "DWG to PDF.PC3" を指定してプロッタ環境設定をオーバーライド(上書き)しています。 印刷対象のレイアウトに設定されたページ設定を利用してバッチ印刷する方法はありますか?   Solution PublishDsd メソッドで、定義済みのページ設定(印刷デバイスと設定)を使用してレイアウトを印刷、または、/ファイル出力することが出来ます。この場合、また、DsdData.SheetType の値を SheetType.OriginalDevice に指定することで、プロッタ環境設定(.pc3)を指定せずに連続印刷をおこなうことが可能です。 次のコードは、その C# 例です。 Try Dim collection As DsdEntryCollection = New DsdEntryCollection() Dim entry As DsdEntry entry = New DsdEntry() entry.Layout = "レイアウト1" entry.DwgName = "c:\Temp\Drawing1.dwg" entry.Nps = "Setup1" entry.Title = "Sheet1" collection.Add(entry) entry = New DsdEntry() entry.Layout = "レイアウト1" entry.DwgName = "c:\Temp\Drawing2.dwg" entry.Nps = "Setup1" entry.Title = "Sheet2" collection.Add(entry) Dim dsd As DsdData = New DsdData() dsd.SetDsdEntryCollection(collection) dsd.ProjectPath = "c:\Temp\" dsd.LogFilePath = "c:\Temp\logdwf.log" dsd.SheetType = SheetType.OriginalDevice dsd.NoOfCopies = 1 dsd.SheetSetName = "PublisherSet" dsd.WriteDsd("c:\Temp\publisher.dsd") Dim nbSheets As Integer = collection.Count Using progressDlg As PlotProgressDialog = New PlotProgressDialog(False, nbSheets, True) progressDlg.UpperPlotProgressRange = 100 progressDlg.LowerPlotProgressRange = 0 progressDlg.UpperSheetProgressRange = 100 progressDlg.LowerSheetProgressRange = 0 progressDlg.IsVisible = True Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("BACKGROUNDPLOT", 0) Dim publisher As Autodesk.AutoCAD.Publishing.Publisher = Autodesk.AutoCAD.ApplicationServices.Application.Publisher publisher.PublishDsd("c:\Temp\publisher.dsd", progressDlg) progressDlg.Destroy() End Using Catch ex As Autodesk.AutoCAD.Runtime.Exception MsgBox(ex.Message) End Try End Sub なお、PublishDsd メソッドを使用して DSD ファイルをパブリッシュする前に、BACKGROUNDPLOT システム変数を 0 に設定する必要があります。
記事全体を表示
質問 AutoCAD VBAで、ファイルの保存ダイアログを表示する方法はありますか。   回答 残念ながらAutoCADのActiveX APIにはファイルの保存ダイアログを表示するAPIが提供されておりません。 代替手段としては、Autolipsのgetfiled関数をSendCommand()メソッドを用いて実行することでダイアログを表示する方法があります。   以下はサンプルコードです。 Dim fileName As String ThisDrawing.SendCommand "(setvar " & """users1""" & "(getfiled " & """Save As""" & """c:/program files/acad2024/""" & """dwg""" & "1)) " fileName = ThisDrawing.GetVariable("users1")
記事全体を表示
Question Inventor APIでInventorのdwgファイルとAutoCADのdwgファイルを識別する方法はありますか? Answer InventorAPIの、FileManager.IsInventorDWG()メソッドを利用することで判別が可能です。 メソッドの引数には対象のdwgファイルへのフルパスを指定します。  
記事全体を表示
Question AutoCADのAPIでレイヤーをロックした場合、レイヤー上のエンティティの表示がローライト表示されません。 GUIでレイヤーをロックする場合と同様にレイヤー上のエンティティをローライト表示する方法はありますか。 Answer レイヤーのロックを設定する際に、レイヤーのプロパティを編集し、レイヤに変更がされたことをAutoCADエディタに認識させた後に、Regenを実行することでGUIからロック状態を変更した場合と同様に、ロックしたレイヤー上のエンティティをローライト表示させることが可能です。   以下は、上述の処理をLockという名前のレイヤーに対して実行するサンプルコードです。   C#  [CommandMethod("Layerlack")] static public void Layerlack() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable table = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; if (table.Has("Lock")) { LayerTableRecord record = tr.GetObject(table["Lock"],OpenMode.ForWrite) as LayerTableRecord; record.IsLocked = true; record.LineWeight = record.LineWeight; } tr.Commit(); } ed.Regen(); }    VBA Sub Example_Lock() Dim layerObj As AcadLayer Set layerObj = ThisDrawing.Layers.Add("Lock") layerObj.Lock = True layerObj.Lineweight = layerObj.Lineweight ThisDrawing.Regen acAllViewports End Sub    
記事全体を表示
Question AutoCAD .net APIで、エンティティマウスドラッグ操作(移動・回転 等)でマウス操作に追随してプレビューイメージを表示するにはどうしたらよいでしょうか。 Answer AutoCAD .net APIのEntityJigの仕組みが利用可能です。   EntityJigを継承したクラスを作成し、Sampler()メソッドをとUpdate()メソッドをオーバライドして、入力に応じた処理を実装します。   以下は、マウスに追随してプレビューを表示しながら選択したエンティティを回転させるサンプルコードとなります。  [CommandMethod("MyRotateEnt")] public static void MyRotateEnt() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; Database db = HostApplicationServices.WorkingDatabase; PromptEntityResult per = ed.GetEntity("\nPick an entity:"); if (per.Status != PromptStatus.OK) { return; } PromptPointResult pr = ed.GetPoint("\nBase Point: "); if(pr.Status != PromptStatus.OK) { return; } try { using (Transaction tx = db.TransactionManager.StartTransaction()) { Entity ent = tx.GetObject(per.ObjectId, OpenMode.ForWrite) as Entity; if (ent != null) { RotateJigger jigger = new RotateJigger(ent, pr.Value, ed.CurrentUserCoordinateSystem); if (jigger.Run() == PromptStatus.OK) { tx.Commit(); } } } } catch (System.Exception ex) { ed.WriteMessage(ex.ToString()); } } public class RotateJigger : EntityJig { private double mRt = 0.0; private Point3d mBp = new Point3d(); private double mLastAngle = 0.0; private Matrix3d mUcs; public RotateJigger(Entity ent, Point3d bp, Matrix3d ucs) : base(ent) { mBp = bp; mUcs = ucs; } protected override bool Update() { Point3d basePt = new Point3d(mBp.X, mBp.Y, mBp.Z); Matrix3d mat = Matrix3d.Rotation(mRt - mLastAngle , Vector3d.ZAxis.TransformBy(mUcs) , basePt.TransformBy(mUcs)); this.Entity.TransformBy(mat); mLastAngle = mRt; return true; } protected override SamplerStatus Sampler(JigPrompts prompts) { PromptDoubleResult pr = prompts.AcquireAngle( new JigPromptAngleOptions("\nRotation angle:") { BasePoint = mBp, UseBasePoint = true }); if (pr.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; if (pr.Value.Equals(mRt)) { return SamplerStatus.NoChange; } mRt = pr.Value; return SamplerStatus.OK; } public PromptStatus Run() { Document doc = Application.DocumentManager.MdiActiveDocument; if (doc == null) return PromptStatus.Error; return doc.Editor.Drag(this).Status; } }
記事全体を表示
Question 以下のサンプルコードの様に、AutoCAD .net APIで作成した球体のソリッドで、GUIのプロパティ表示「ジオメトリ」に中心座標や半径が表示されない。 「ジオメトリ」が表示されるようにするにはどうしたらよいでしょうか。 Document dc = Application.DocumentManager.MdiActiveDocument; Database db = dc.Database; Editor ed = dc.Editor; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable acBlkTbl; acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord acBlkTblRec; acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; double rd, x, y, z; string sLayer; short lyColor; rd = 1.0; x = 0.0; y = 0.0; z = 0.0; using (Solid3d sphere = new Solid3d()) { sphere.CreateSphere(rd); Point3d location = new Point3d(x, y, z); sphere.TransformBy(Matrix3d.Displacement(location - Point3d.Origin)); acBlkTblRec.AppendEntity(sphere); tr.AddNewlyCreatedDBObject(sphere, true); } tr.Commit(); }   Answer   APIから作成した球の場合には、タイププロパティ(GUIではAutoCADのコマンドから作成した球のプロパティを参照するとジオメトリの項目に表示されるソリッドタイプ)が設定されていないことが、GUIにジオメトリの項目が表示されない原因です。   このタイププロパティはAutoCADのコマンドから球や円柱等のプリミティブなソリッド形状を作成した場合にのみ設定され、Object ARX .net、ActiveX 等のAPIから3Dソリッドを作成した場合にはこのプロパティは設定されません。   回避方法としては、以下のサンプルコードの様に.netのコードからEditor.Command()メソッドを用いて、Shpereコマンドを実行する方法となります。   Document dc = Application.DocumentManager.MdiActiveDocument; Database db = dc.Database; Editor ed = dc.Editor; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; acLyrTbl = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; double rd, x, y, z; rd = 1.0; x = 0.0; y = 0.0; z = 0.0; Point3d location = new Point3d(locX, locY, locZ); ed.Command("_.sphere", location, rd, ""); Solid3d sphere = tr.GetObject(ed.SelectLast().Value.GetObjectIds()[0], OpenMode.ForWrite) as Solid3d; tr.Commit(); }    
記事全体を表示
Question Vault APIで、Vaultエクスプローラの「コピーデザイン」コマンドでコピーされたファイルに対してプロパティの追加等の特定の処理を行いたい。 Answer Vault APIを用いて、Vault エクスプローラのカスタムエクステンションを作成することにより、Vaultエクスプローラでのコマンドの実行とコマンドの終了をイベントとして受け取ることが出来ます。   また、Vault APIのWebサービスコマンドイベントを利用することでVaultへのファイルの追加や削除などのVault操作が行われたことをイベントとして受け取ることが可能です。   一見、これらのイベントを組み合わせることで、「コピーデザイン」コマンドの実行開始前~終了の間に、追加されたファイルをWebサービスコマンドイベントのファイル追加イベントに検出することで「コピーデザイン」コマンドにて、コピーされたファイルに対して特定の操作を行うことが可能なように思われます。   ただ、残念ながら、Vault 2021以降「コピーデザイン」機能の拡張が行われ、「コピーデザイン」コマンドは「コピーデザイン」を行う対象を選択するモードレスイアログを起動するコマンドとなり、実際のコピー処理はモードレスアログ上で操作で行われる形となったため、「コピーデザイン」コマンドの開始~終了により追加されたファイルを判定するという方法が取れなくなっています。   この要望を完全に満たすカスタマイズを行うことが出来ませんが、以下のサンプルコードの様に   1.IExplorerExtensionを実装したVault Explororのエクステンションを作成 2.OnStartupにてコマンドの開始(CommandBegin)およびCopy Designダイアログのクローズ(CopyDesignDialogClosed)のイベントハンドラを設定 3.CommandBeginイベントハンドラにて対象のコマンドがCopyDesignの場合、AddFileEventsハンドラを設定 4.設定したAddFileEventsイベントハンドラにて追加がされたファイルの情報を収集 5.CopyDesignDialogClosedイベントハンドラにて、収集したファイルの情報(追加されたファイル)に対して処理を行う   といった形で、コピーデザインダイアログのダイアログが表示されている間にVaultに追加されたファイル情報を収集して処理を行うことは可能です。 ただし、コピーデザインダイアログがモードレスダイアログであり、ダイアログ表示中にもVaultエクスプローラや別の画面も操作可能であるためコピーデザインダイアログの外でVaultに追加されたファイルの情報も収集してしまいます。   このため、コピーデザインダイアログを表示後、デザインをコピーする際にはダイアログ外での操作を行わないといった制限を、運用で制御できる状況であれば利用可能な方法となる点に注意が必要です。 public class HelloWorldCommandExtension : IExplorerExtension { private List<Tuple<long, string>> m_addedFiles = null; private static string COPY_DESING_COMMAND_ID = "CopyDesign"; public void OnStartup(IApplication application) { application.CommandBegin += new EventHandler<CommandBeginEventArgs>(application_CommandBegin); Autodesk.DataManagement.Client.Framework.Vault.Forms.Library.CopyDesignDialogClosed += new EventHandler(CopyDesignDialogClosed); } void application_CommandBegin(object sender, CommandBeginEventArgs e) { if (e.CommandId == COPY_DESING_COMMAND_ID) { m_addedFiles = new List<Tuple<long, string>>(); DocumentService.AddFileEvents.GetRestrictions += new EventHandler<AddFileCommandEventArgs>(AddFileEvents_GetRestrictions); } } void CopyDesignDialogClosed(object sender, EventArgs e) { DocumentService.AddFileEvents.GetRestrictions -= new EventHandler<AddFileCommandEventArgs>(AddFileEvents_GetRestrictions); //Update properties for added files. m_addedFiles.ForEach((item) =>{ }); m_addedFiles.Clear(); m_addedFiles = null; } void AddFileEvents_GetRestrictions(object sender, AddFileCommandEventArgs e) { m_addedFiles.Add(Tuple.Create(e.FolderId, e.FileName)); }  
記事全体を表示
症状 Inventor VBAでSketchedSymbols.Add()メソッドで正しい引数を渡しているにもかかわらず「プロシージャの呼び出し、または引数が不正です。」エラーが発生する。 再現手順 1.Inventorを起動し、図面ファイルを新規作成します。   2. VBAエディタで以下のコードを実行し、スケッチシンボルを追加します。 Public Sub CreateSketchedSymbolDefinition() ' Set a reference to the drawing document. ' This assumes a drawing document is active. Dim oDrawDoc As DrawingDocument Set oDrawDoc = ThisApplication.ActiveDocument ' Create the new sketched symbol definition. Dim oSketchedSymbolDef As SketchedSymbolDefinition Set oSketchedSymbolDef = oDrawDoc.SketchedSymbolDefinitions.Add("Circular Callout") ' Open the sketched symbol definition's sketch for edit. This is done by calling the Edit ' method of the SketchedSymbolDefinition to obtain a DrawingSketch. This actually creates ' a copy of the sketched symbol definition's and opens it for edit. Dim oSketch As DrawingSketch Call oSketchedSymbolDef.Edit(oSketch) Dim oTG As TransientGeometry Set oTG = ThisApplication.TransientGeometry ' Use the functionality of the sketch to add sketched symbol graphics. Dim oSketchLine As SketchLine Set oSketchLine = oSketch.SketchLines.AddByTwoPoints(oTG.CreatePoint2d(0, 0), oTG.CreatePoint2d(20, 0)) Dim oSketchCircle As SketchCircle Set oSketchCircle = oSketch.SketchCircles.AddByCenterRadius(oTG.CreatePoint2d(22, 0), 2) Call oSketch.GeometricConstraints.AddCoincident(oSketchLine.EndSketchPoint, oSketchCircle) ' Make the starting point of the sketch line the insertion point oSketchLine.StartSketchPoint.InsertionPoint = True ' Add a prompted text field at the center of the sketch circle. Dim sText As String sText = "<Prompt>Enter text 1</Prompt>" Dim oTextBox As TextBox Set oTextBox = oSketch.TextBoxes.AddFitted(oTG.CreatePoint2d(22, 0), sText) oTextBox.VerticalJustification = kAlignTextMiddle oTextBox.HorizontalJustification = kAlignTextCenter Call oSketchedSymbolDef.ExitEdit(True) End Sub   3.作成したスケッチシンボルをシートに追加する以下のコードを実行すると、oSketchedSymbols.Add()の行でエラーが発生します。 Public Sub InsertSketchedSymbolOnSheet() ' Set a reference to the drawing document. ' This assumes a drawing document is active. Dim oDrawDoc As DrawingDocument Set oDrawDoc = ThisApplication.ActiveDocument ' Obtain a reference to the desired sketched symbol definition. Dim oSketchedSymbolDef As SketchedSymbolDefinition Set oSketchedSymbolDef = oDrawDoc.SketchedSymbolDefinitions.Item("Circular Callout") Dim oSheet As Sheet Set oSheet = oDrawDoc.ActiveSheet ' This sketched symbol definition contains one prompted string input. An array ' must be input that contains the strings for the prompted strings. Dim sPromptStrings(0) As String sPromptStrings(0) = "A" Dim oTG As TransientGeometry Set oTG = ThisApplication.TransientGeometry ' Add an instance of the sketched symbol definition to the sheet. ' Rotate the instance by 45 degrees and scale by .75 when adding. ' The symbol will be inserted at (0,0) on the sheet. Since the ' start point of the line was marked as the insertion point, the ' start point should end up at (0,0). Dim oSketchedSymbols As Object Set oSketchedSymbols = oSheet.SketchedSymbols Dim oSketchedSymbol As SketchedSymbol Set oSketchedSymbol = oSketchedSymbols.Add(oSketchedSymbolDef, oTG.CreatePoint2d(0, 0), (3.14159 / 4), 0.75, sPromptStrings) End Sub 原因 上述のスケッチシンボルをシートに追加するコードで、SketchedSymbolsオブジェクトを格納する変数oSketchedSymbolsがObject型で宣言されていることエラーの原因です。   SketchedSymbols.Add()メソッドは、第五引数のオプショナル引数に文字列の配列を指定可能ですがSketchedSymbolsオブジェクトがObject型の変数で宣言されている場合、VBAはこの引数を文字列の配列ではなく、IUnknown型の配列に変換してメソッド呼び出し行います。 このため、指定している引数の型不一致と判断されエラーとなります。   対処法  以下サンプルコードの様にSketchedSymbolsオブジェクトを格納する変数oSketchedSymbolsを明示的にSketchedSymbols型として宣言をすることで、このエラーは発生しなくなります。   Public Sub InsertSketchedSymbolOnSheet() ' Set a reference to the drawing document. ' This assumes a drawing document is active. Dim oDrawDoc As DrawingDocument Set oDrawDoc = ThisApplication.ActiveDocument ' Obtain a reference to the desired sketched symbol definition. Dim oSketchedSymbolDef As SketchedSymbolDefinition Set oSketchedSymbolDef = oDrawDoc.SketchedSymbolDefinitions.Item("Circular Callout") Dim oSheet As Sheet Set oSheet = oDrawDoc.ActiveSheet ' This sketched symbol definition contains one prompted string input. An array ' must be input that contains the strings for the prompted strings. Dim sPromptStrings(0) As String sPromptStrings(0) = "A" Dim oTG As TransientGeometry Set oTG = ThisApplication.TransientGeometry ' Add an instance of the sketched symbol definition to the sheet. ' Rotate the instance by 45 degrees and scale by .75 when adding. ' The symbol will be inserted at (0,0) on the sheet. Since the ' start point of the line was marked as the insertion point, the ' start point should end up at (0,0). Dim oSketchedSymbols As SketchedSymbols Set oSketchedSymbols = oSheet.SketchedSymbols Dim oSketchedSymbol As SketchedSymbol Set oSketchedSymbol = oSketchedSymbols.Add(oSketchedSymbolDef, oTG.CreatePoint2d(0, 0), (3.14159 / 4), 0.75, sPromptStrings) End Sub     なお、この現象はメソッドをチェイン実行した場合にも発生します。例えば上記サンプルで以下のようにoSheet変数をObject型として宣言して、oSheet.SketchedSymbols.Add()と実行した場合などです。この場合もoSheetがObject型として宣言されているため以降のメソッド呼び出しが、VBAの実行時バインディング を用いて呼び出されるため、VBAが第五引数の変数の型をIUnknown型の配列に変換してしまうためです。 Dim oSheet As Object ... Set oSketchedSymbol = oSheet.SketchedSymbols.Add(oSketchedSymbolDef, oTG.CreatePoint2d(0, 0), (3.14159 / 4), 0.75, sPromptStrings)    
記事全体を表示
Question AutoCADでnetloadでロードしたカスタムプラグインが参照する外部Dllが読み込まれずエラーとなります。 どうすればカスタムプラグインが参照する外部Dllを読み込むことが出来ますか。 Answer Windowsのデスクトップアプリケーションがロード対象のDLLを検索する際には、「プローブ」と呼ばれるWindowsの機能が用いられます。一般的なデスクトップアプリケーションの場合、プローブでのDLLを検索は、通常以下の順で行われます。   1.アプリケーションがロードされたディレクトリ(DLLをホストするexeファイルの場所) 2.カレント・ディレクトリ 3.システム・ディレクトリ(%Systemroot%\System32) 4.16bit・システム・ディレクトリ(%Systemroot%\System) 5.Windowsディレクトリ(%Systemroot%) 6.PATH環境変数に列挙されているディレクトリ 参考: https://docs.microsoft.com/ja-jp/windows/win32/dlls/dynamic-link-library-search-order?redirectedfrom=MSDN#standard-search-order-for-desktop-applications   また、WindowsおよびAutoCADではDLLの配置先を解決する方法として上述の「プローブ」を以外に、manifestファイルを用いる等のいくつかの仕組みがあります。 代表的な方法としては以下が挙げられます。 a.厳密名を持つアセンブリの場合、acad.exe.configにDLLのパスを設定する b.AutoCADの AutoLoaderの仕組みを利用する c.対象のDLLがアセンブリの場合、System.Reflection.Assembly.LoadFromを用いて、対象の機能を実行する直前にDLLをロードする。 d.AppDomain.AssemblyResolveイベントハンドラを実装し対象のアセンブリをロードする   「プローブ」を用いた検索はmanifest等の方法で、DLLの配置先を解決できない場合に用いられる方法となりますが、厳密にDLLを指定することが難しいため、DLLのバージョンによる問題が発生する可能性があります。 このためカスタムプラグインが参照する外部Dllを読み込ませるには、まずはmanifest等で挙げた法を用いることを検討ください。   なお、上述のc及びdの方法については、プログラムの修正が必要となり、ここでは詳細は割愛し、aとbの方法について解説をします。   「a.厳密名を持つアセンブリの場合、acad.exe.configにDLLのパスを設定する」方法 外部Dllが、厳密名を持つアセンブリかは、sn.exeを用いるて以下のコマンドを実行することで判定が可能です(sn.exeはVisual Studio と共に自動的にインストールされます)。   >sn.exe" -v <外部.dllへのパス> もし対象の外部dllが厳密名を持つアセンブリであった場合、acad.exe.configに以下のようなアセンブリの厳密名とアセンブリへのパスを記述をすることで、ロードさせることが可能です。 ※DLLのパス、PublicKeyToken、Version等の情報はコマンドで取得した情報で置き換えが必要です。 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="DllToLoad" publicKeyToken="cace528f15d690ab" culture="neutral" /> <codeBase version="1.0.0.0" href= "file://C:\Documents and Settings\Administrator\My Documents\Visual Studio 2010\Projects\TestDllLoad\DllToLoad\bin\Debug\DllToLoad.dll"/> </dependentAssembly> </assemblyBinding>   b.AutoCADの AutoLoaderの仕組みを利用する AutoCADのAutoLoader メカニズムについては以下URLのリファレンスを参照してください。 https://help.autodesk.com/view/ACD/2020/JPN/?guid=GUID-5E50A846-C80B-4FFD-8DD3-C20B22098008   AutoLoaderを用いたプラグインのロードの場合、AutoLoaderがロード対象のDLL(=プラグインのDll)のロードと合わせて、バンドルフォルダを、アプリケーションのロードパスに追加をします。このため、アプリケーションは同一フォルダにある外部DLLを検索、ロードが可能になります。   ここまでの方法による解決(c, dの方法を含む)が難しい場合は、「プローブ」を用いた方法を用いての解決を検討ください。 ・acad.exeがあるディレクトリに、外部.dllを配置する ・PATH環境変数に外部.dllが存在するディレクトリを追加する 等
記事全体を表示
Question Inventorの言語設定に依存せずにInventorのAPIでBOMのソート列を指定する方法はありますか?   Answer InventorのAPIでは、BOMViewをソートする際に列名を指定する必要があります。 指定する列名は、実行中のInventorの言語設定により同じ項目でも名前が変わる(例 日本語名:”項目”、英語名:”Item”)ため、同じ列でソートする場合においても実行中のInventorの言語設定により、APIに指定する項目名を変える必要があります。   このため、複数言語での利用を想定する場合、以下のサンプルコード(日・英でのサンプル)のように、実行環境の言語に合わせてソート項目名を指定する必要があります。 Dim bv As BOMView Set bv = ThisDocument.ComponentDefinition.BOM.BOMViews(2) Select Case ThisApplication.LanguageCode Case "en-US" Call bv.Sort2("Item") Case "ja-JP" Call bv.Sort2("項目") End Select   なお、Inventor2020以前のバージョンの場合、日本語環境のInventorにて保存したデータを、英語環境のInventorで開いた場合には、上述のサンプルコードのCall bv.Sort2("Item")の実行でエラーが発生します。 この挙動については、Inventor 2021で修正対応がされています。  
記事全体を表示
Question AutoCADのVBAで、メニューマクロの^C^Cに相当する文字をSendCommandする方法はありますか? Chr(27)や文字コード27をSendCommandしても、エラーが出て動作しない。 Answer AutoCAD 2015で行われたAutoCADの内部的な実装の変更に起因し、以降のバージョンではChr(27)や文字コード27をSendCommandしてもエラーとなります。 残念ながら、現状ではEscを同期的に実行させる方法はありません。   PostCommandメソッド使用した非同期実行により、代替が可能かをご検討ください。 ThisDrawing.PostCommand Chr(27) & Chr(27)  
記事全体を表示
Question InventorAPIでDocuments オブジェクト のCountプロパティの値が2022以降とそれより前のバージョンで異なりますが、なぜでしょうか。 Answer この動作は、Invewntor 2022以降で追加されたモデル状態機能に対応する形でのAPIの動作の変更となります。   モデル状態が存在する場合、2つのドキュメントがDocumentsプロパティから取得されます。 2つのドキュメントの相違点は、片方がファクトリドキュメントもう片方がメンバドキュメントとなり、APIでは以下のプロパティにて区別が可能です。 ・ファクトリドキュメント:ComponentDefinition.IsModelStateFactory プロパティがTrue ・メンバドキュメント:ComponentDefinition.IsModelStateMemberプロパティがTrue  
記事全体を表示
Question InventorのFileDialogで、ShowSave()実行時にInitialDirectoryプロパティで指定したパスが初期表示されない。 Answer FileDialogのShowSave()メソッド実行時には、InitialDirectoryプロパティで指定したパスが無視されます。 この問題に対応するためには、FileDialogのFileNameプロパティに、ファイル名だけでなくダイアログに初期表示をしたいフォルダを含むフルパスを指定することで回避が可能です。   以下は、現在のドキュメントが存在するフォルダを指定してShowSave()を実行する場合のサンプルとなります。 Dim oFileDlg As Inventor.FileDialog = Nothing InventorVb.Application.CreateFileDialog(oFileDlg) '.ShowSave()の場合InitialDirectoryの設定は無視される 'oFileDlg.InitialDirectory = ThisDoc.Path '.ShowSave()の場合FileNameに初期表示したいフォルダまでのフルパスを含むファイル名を指定する oFileDlg.FileName = ThisDoc.Path + "\" + ThisDoc.FileName(False) oFileDlg.CancelError = True oFileDlg.ShowSave()
記事全体を表示
Question NavisworksのAPIからコマンドを実行する方法はありますか? Answer NavisworksのAPI ExecuteCommand()を用いることでAPIからコマンドを実行することが可能です。 ExecuteCommand()の第一引数には、実行するコマンドのIdを指定します。   C:\Program Files\Autodesk\<Navisworks Manage version>\Layout 配下のRoamerCommands.xmlファイルに、Navisworksの既定のコマンドのIdが定義されています。   以下は「全体表示」を実行するサンプルです。 Autodesk.Navisworks.Api.Interop.LcRmFrameworkInterface.ExecuteCommand("RoamerGUI_AutoCAM_Zoom_All", Autodesk.Navisworks.Api.Interop.LcUCIPExecutionContext.ePANEL);  
記事全体を表示
Question Vault APIで等価性エラーが発生しているファイルを取得する方法はありますか。 Answer 等価性エラーが発生している場合、プロパティコンプライアンス プロパティの値が2となっている状況です。   このため、以下のようにプロパティコンプライアンスプロパティの値が"2"(等価性が準拠していない)状態にあるFileを検索条件に指定して取得することが可能です。 SrchCond[] cond = new SrchCond[] { new SrchCond( ){ PropDefId = 39, //プロパティコンプライアンスのプロパティID SrchOper = 3, //Is exactly (or equals) SrchTxt = "2", //等価性が準拠していない PropTyp = PropertySearchType.SingleProperty, SrchRule = SearchRuleType.Must } }; string bookmark = null; SrchStatus status; ACW.File[] files = serviceManager.DocumentService.FindFilesBySearchConditions(cond, null, null, true, true, ref bookmark, out status);    また、すでに対象のFileの配列を取得しており、その中から等価性エラーが発生しているFileを抽出する場合は、以下のようにGetPropertiesを利用して、プロパティを取得して確認する形となります。 IEnumerable<long> ids = files.Select(file => file.Id); PropInst[] properties = serviceManager.PropertyService.GetProperties( "FILE", ids.ToArray(), new long[] { 39 /*プロパティコンプライアンスのプロパティID*/} ); IEnumerable<PropInst> PropInstSelection = from propInst in properties where propInst.PropDefId == 39 && propInst.Val.ToString() == "2" /*プロパティコンプライアンスのプロパティIDで等価性が準拠していない*/ select propInst;   なお、プロパティコンプライアンスプロパティのId(=39)値は、以下のサンプルのように”FILE”エンティティのプロパティを取得してループで内容を見ることで確認が可能です。 PropDef[] fileProps = serviceManager.PropertyService.GetPropertyDefinitionsByEntityClassId("FILE");  
記事全体を表示
Question AutoCADのObjectARXでハードウェアアクセラレーションをオン/オフ状態を取得する方法はありますか? Answer AutoCAD ObjectARXのAcGsManagerクラスからAcGsGraphicsKernelを取得、AcGsGraphicsKernelからAcGsConfigを取得します。 AcGsConfigのisHardwareAccelerationEnabled()メソッドにより現在のHWアクセラレーションの設定が確認できます。   なお、ビルドに当たりAcDrawBridge.libをリンクファイルに追加となります。  AcGsKernelDescriptor descriptor; descriptor.addRequirement(AcGsKernelDescriptor::k3DDrawing); AcGsGraphicsKernel* pGraphicsKernel = AcGsManager::acquireGraphicsKernel(descriptor); AcGsConfig* gsConf = pGraphicsKernel->getConfig(); if (gsConf->isHardwareAccelerationEnabled()) { acutPrintf(ACRX_T("\nHardwareAcceleration Enabled.")); } else { acutPrintf(ACRX_T("\nHardwareAcceleration Disabled.")); }
記事全体を表示
Question AutoCAD のActiveX API SetWindowToPlot()で指定した印刷範囲が特定の図面でずれる場合がある。 指定した範囲で正しく印刷する方法はありますか。 Answer 印刷範囲がずれる図面では、TARGETシステム変数の値に0ではない値が設定されている可能性があります。 ※TARGETシステム変数変数については、以下のリファレンスを参照 https://help.autodesk.com/view/ACD/2022/JPN/?guid=GUID-0649E4B8-B11A-411E-96CE-125BEBEB5B42   この場合、SetWindowToPlotで指定した座標がオフセットされてるため、指定した印刷範囲で印刷されません。 以下サンプルコードの様にSetWindowToPlot()に指定する点の座標を、ActiveViewport.Targetの値で減算することで、指定範囲で印刷されるようになります。   Sub Example_SetWindowToPlot() Dim point1 As Variant, point2 As Variant point1 = ThisDrawing.Utility.GetPoint(, "Click the lower-left of the window to plot.") ReDim Preserve point1(0 To 1) ' Change this to a 2D array by removing the Z position point2 = ThisDrawing.Utility.GetPoint(, "Click the upper-right of the window to plot.") ReDim Preserve point2(0 To 1) ' Change this to a 2D array by removing the Z position Dim currTarget As Variant currTarget = ThisDrawing.ActiveViewport.Target point1(0) = point1(0) - currTarget(0) point1(1) = point1(1) - currTarget(1) point2(0) = point2(0) - currTarget(0) point2(1) = point2(1) - currTarget(1) ThisDrawing.ActiveLayout.SetWindowToPlot point1, point2 ThisDrawing.ActiveLayout.PlotType = acWindow ThisDrawing.ActiveLayout.ConfigName = "DWG to PDF.pc3" ThisDrawing.Plot.DisplayPlotPreview acFullPreview End Sub  
記事全体を表示
Question InventorのAPIで2D図面上の任意の2点の座標を指定して寸法を追加する方法はありますか。 Answer 入力となる座標に2D図面上で図形が存在しない場合、Inventorの図面寸法を作成することができません。   このため、任意の2点の座標から長さ寸法を挿入したい場合、スケッチ上に入力座標でポイントを作成し、ポイント間の拘束寸法を作成、作成した寸法を図面に取り込むことで寸法を発生させる必要があります。   なお、この方法で作成した寸法はスケッチでの入力点に拘束されているため、図面上の図形や、ビューの元データのモデルの更新に追随して更新されません。   また、拘束寸法をシートに取り込んだ場合、寸法値はドキュメントの規格設定によりinchまたはmmとなります。寸法値をcm等の別の単位で表示したい場合は、シートに取得したスケッチの拘束寸法に対して値の上書きを行う必要があります。なお、寸法値の上書きを行っている場合スケッチ上で拘束寸法の変更を行った場合においても、値の更新が自動で行われない(上書き値が表示される)点に注意が必要です。   以下は2点の座標を元にスケッチに点を追加、拘束寸法を作成後にシートに取り込みを行うVBAのサンプルコードです。 Dim oDoc As DrawingDocument Set oDoc = ThisApplication.ActiveDocument Dim oSheet As sheet Set oSheet = oDoc.ActiveSheet Dim oSketch As sketch Dim oDimensionConstraint As DimensionConstraint Set oDimensionConstraint = addDimensionBySketchPoint(oSheet, "スケッチ1", 10, 10, 12, 10) Dim oConsraintDimensionCollection As ObjectCollection Set oConsraintDimensionCollection = ThisApplication.TransientObjects.CreateObjectCollection oConsraintDimensionCollection.Add oDimensionConstraint 'retrieve model dimension Call oSheet.DrawingDimensions.GeneralDimensions.Retrieve(oDimensionConstraint.Parent, oConsraintDimensionCollection) End Sub Public Function addDimensionBySketchPoint(oSheet As sheet, sketchName As String, x1 As Double, y1 As Double, x2 As Double, y2 As Double) As DimensionConstraint Dim oTg As TransientGeometry Set oTg = ThisApplication.TransientGeometry Dim oSketch As DrawingSketch On Error Resume Next Set oSketch = oSheet.Sketches(sketchName) On Error GoTo 0 If oSketch Is Nothing Then Set oSketch = oSheet.Sketches.Add() End If oSketch.Edit Dim p1 As Point2d Set p1 = oTg.CreatePoint2d(x1, y1) Dim p2 As Point2d Set p2 = oTg.CreatePoint2d(x2, y2) Dim skP1 As SketchPoint Set skP1 = oSketch.SketchPoints.Add(p1, False) Dim skP2 As SketchPoint Set skP2 = oSketch.SketchPoints.Add(p2, False) Dim tp As Point2d Set tp = oTg.CreatePoint2d((x2 + x1) / 2, (y2 + y1) / 2) Dim oTwoPointDistanceDimConstraint As TwoPointDistanceDimConstraint Set oTwoPointDistanceDimConstraint = oSketch.DimensionConstraints.AddTwoPointDistance(skP1, skP2, kHorizontalDim, tp) Set addDimensionBySketchPoint = oTwoPointDistanceDimConstraint oSketch.ExitEdit  
記事全体を表示