Hi, I have been trying to export fbx using TwinMotion Dynamic Link. I would like to export fbx files from many revit files, so I would like to know how I can use PostCommand and then operate windows forms on the export panel. I tried to use "SendKeys" but I couldn't make it.
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Events;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace TwinMotion
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.DB.Macros.AddInId("1D1D7C97-4450-43CA-A675-22C2FCC465D5")]
public partial class ThisApplication
{
private void Module_Startup(object sender, EventArgs e)
{
}
private void Module_Shutdown(object sender, EventArgs e)
{
}
#region Revit Macros generated code
private void InternalStartup()
{
this.Startup += new System.EventHandler(Module_Startup);
this.Shutdown += new System.EventHandler(Module_Shutdown);
}
#endregion
void OnDialogBoxShowing(object sender, DialogBoxShowingEventArgs args )
{
//DialogBoxShowingEventArgs args
TaskDialogShowingEventArgs e2 = args as TaskDialogShowingEventArgs;
e2.OverrideResult((int)TaskDialogResult.Ok);
}
public void myMacro()
{
Document doc = this.ActiveUIDocument.Document;
//Application app = doc.Application;
//UIApplication uiapp = new UIApplication(app);
UIApplication uiapp = new UIApplication(Application);
try
{
//RevitCommandId id = RevitCommandId.LookupPostableCommandId(PostableCommand.ViewRange);
RevitCommandId id = RevitCommandId.LookupPostableCommandId(PostableCommand.PlaceAComponent);
string name = "CustomCtrl_%CustomCtrl_%Twinmotion 2020%Twinmotion Direct Link%ExportButton";
RevitCommandId id_addin = RevitCommandId.LookupCommandId(name);
if (id_addin != null)
{
//TaskDialog.Show("Test", "Found ID");
uiapp.DialogBoxShowing += new EventHandler<DialogBoxShowingEventArgs>(OnDialogBoxShowing );
uiapp.PostCommand(id_addin);
}
}
catch
{
TaskDialog.Show("Test", "error");
}
finally{
uiapp.DialogBoxShowing -= new EventHandler<DialogBoxShowingEventArgs>(OnDialogBoxShowing );
}
}
}
}
Solved! Go to Solution.
Solved by jeremytammik. Go to Solution.
I am a very new on Revit API forum. Any advice would be greatly appreciated! 🙂
Welcome to the Revit API.
Unfortunately, the Revit API provides no support for the scenario you describe.
The native Windows API does provide all the required functionality to simulate any user input you like.
Therefore, you can use the Windows API to drive the required workflow.
I used such a mechanism to implement a simple Windows form clicker:
https://github.com/jeremytammik/JtClicker
You can try to implement something similar for your requirements.
However, as said, that has nothing whatsoever to do with the Revit API.
I hope this helps.
Best regards,
Jeremy
Hi Jeremy,
Thank you for your reply! I am able to export automatically by Windows API as you showed me the example!
void OnDialogBoxShowing(object sender, DialogBoxShowingEventArgs args )
{
//DialogBoxShowingEventArgs args
TaskDialogShowingEventArgs e2 = args as TaskDialogShowingEventArgs;
e2.OverrideResult((int)TaskDialogResult.Ok);
}
static async void RunCommands(UIApplication uiapp,RevitCommandId id_addin){
uiapp.PostCommand(id_addin);
await Task.Delay(400);
SendKeys.Send("{ENTER}");
await Task.Delay(400);
SendKeys.Send("{ENTER}");
await Task.Delay(400);
SendKeys.Send("{ENTER}");
await Task.Delay(400);
SendKeys.Send("{ESCAPE}");
await Task.Delay(400);
SendKeys.Send("{ESCAPE}");
}
public void myMacro()
{
Document doc = this.ActiveUIDocument.Document;
//Application app = doc.Application;
//UIApplication uiapp = new UIApplication(app);
UIApplication uiapp = new UIApplication(Application);
try
{
//RevitCommandId id = RevitCommandId.LookupPostableCommandId(PostableCommand.ViewRange);
RevitCommandId id = RevitCommandId.LookupPostableCommandId(PostableCommand.PlaceAComponent);
string name = "CustomCtrl_%CustomCtrl_%Twinmotion 2020%Twinmotion Direct Link%ExportButton";
RevitCommandId id_addin = RevitCommandId.LookupCommandId(name);
if (id_addin != null)
{
//TaskDialog.Show("Test", "Found ID");
uiapp.DialogBoxShowing += new EventHandler<DialogBoxShowingEventArgs>(OnDialogBoxShowing );
//uiapp.PostCommand(id_addin);
RunCommands(uiapp, id_addin);
}
}
catch
{
TaskDialog.Show("Test", "error");
}
finally{
uiapp.DialogBoxShowing -= new EventHandler<DialogBoxShowingEventArgs>(OnDialogBoxShowing );
}
}
Best,
Yuko
Congratulations on solving this, and thank you very much for your appreciation and above all for sharing your nice clean solution!
Any thoughts on how to do this with Python?
I just can't seem to get Send Keys to function. Where are you getting SendKeys from?
Thank you for sharing your solution. It saved me unbelievable amount of time, maybe days or weeks. Thank you VERY VERY MUCH!!!
I cleaned the code and made it more readable in case someone needs it. My own Revit plugin calls this Twinmotion macro automatically after Revit starts up.
using System.Threading.Tasks;
using Autodesk.Revit.UI;
using System.Windows.Forms;
using Autodesk.Revit.UI.Events;
namespace YourNamespaceHere
{
public class Class2 : IExternalApplication
{
UIControlledApplication UIControlledApplication;
public Result OnStartup(UIControlledApplication Application)
{
UIControlledApplication = Application;
UIControlledApplication.Idling += Application_Idling;
return Result.Succeeded;
}
public Result OnShutdown(UIControlledApplication Application) => Result.Succeeded;
void Application_Idling(object Sender, IdlingEventArgs E)
{
UIControlledApplication.Idling -= Application_Idling;
var UIApplication = (UIApplication)Sender;
MyMacro(UIApplication);
//TaskDialog.Show("Application_Idling", Sender.GetType().FullName);
}
void OnDialogBoxShowing(object Sender, DialogBoxShowingEventArgs Args) => ((TaskDialogShowingEventArgs)Args).OverrideResult((int)TaskDialogResult.Ok);
static async void RunCommands(UIApplication UIapp, RevitCommandId Id_Addin)
{
UIapp.PostCommand(Id_Addin);
await Task.Delay(400);
SendKeys.Send("{ENTER}");
await Task.Delay(400);
SendKeys.Send("{ENTER}");
await Task.Delay(400);
SendKeys.Send("{ENTER}");
await Task.Delay(400);
SendKeys.Send("{ESCAPE}");
await Task.Delay(400);
SendKeys.Send("{ESCAPE}");
}
void MyMacro(UIApplication UIapp)
{
try
{
var Name = "CustomCtrl_%CustomCtrl_%Twinmotion 2020%Twinmotion Direct Link%ExportButton";
var Id_Addin = RevitCommandId.LookupCommandId(Name);
if (Id_Addin != null)
{
UIapp.DialogBoxShowing += OnDialogBoxShowing;
RunCommands(UIapp, Id_Addin);
}
}
catch
{
TaskDialog.Show("Test", "error");
}
finally
{
UIapp.DialogBoxShowing -= OnDialogBoxShowing;
}
}
}
}