EaBIM一直以来积极响应国家“十二五”推进建筑业信息化的号召,对建筑领域的信息技术开展深入技术交流和探讨!致力于打造“BIM-建筑师-生态技术”三位一体综合资源交流共享平台,希望为BIM与可持续设计理念及技术的普及做出微小的贡献!!!

萧闫子 发表于 2014-1-9 11:44:43

Building Coder - 拖放API



我们在讨论 Revit 2012 的拖放动作 ( drag and drop in Revit 2012 ) 时向大家展示了如何从外部进程触发标准的Revit拖放动作。但是在那时我们无法改变 Revit 接收拖放文件的默认行为。好消息是在 Revit 2013 里我们可以这么做了。

Revit 2013 SDK 的例程 UIAPI 向我们展示了最新的拖放API以及插件集成特性:应用程序可用性、预览控件、定制WPF选项对话框。需要注意的是:
1. UIAPI 是一个 External Application,所以无法使用 RvtSamples 来加载
2. UIAPI 没有在 Revit 2013 SDK 文档中出现

UIAPI 拖放命令会显示如下的无模式对话框

左侧的ListView显示已经加载的族,右侧的List显示所有可用的族。

UIApplication DoDragDrop 方法
1. DoDragDrop ( ICollection<string> )
    触发一次包含多个文件的拖放操作
2. DoDragDrop ( object, IDropHandler )
    触发一次可定制Revit接收行为的拖放操作

ApplicationEntryPoint 类也提供同样的方法,但只是针对 Revit 宏。

拖放多个文件
DoDragDrop方法的第一个重载操作的对象是一组文件,并导致确定的Revit接收行为(注意:至少在当前版本这些默认行为是无法改变)。
当只有一种CAD格式或者图片格式的文件被拖放时,Revit会弹出一个新的导入拜访编辑器来处理文件导入
当多种CAD格式或者图片格式的文件被拖放时,Revit仅会针对第一中格式弹出一个新的导入拜访编辑器来处理文件导入
当只有一个族文件被拖放时,Revit会加载该族,并弹出一个编辑器来拜访族实例
当多个族文件被拖放时,Revit会加载所有的族
当多个族文件加上其它格式的文件被拖放时,Revit会尝试打开所有文件(注意:此时不会加载族了)
如果一个有效文件或者一组有效文件被拖放,Revit会尝试合理地使用它们。如果有文件无法使用,Revit会弹出一个失败消息,但是不会抛出异常,也不会通知插件
private void listBox1_MouseMove( object sender, MouseEventArgs e )
{
    if( System.Windows.Forms.Control.MouseButtons == MouseButtons.Left )
    {
      FamilyListBoxMember member = (FamilyListBoxMember) listBox1.SelectedItem;

      // 触发标准的 Revit 拖放行为
      List<String> data = new List<String>();
      data.Add( member.FullPath );
      UIApplication.DoDragDrop( data );
    }
}

从无模式对话框调用 Revit API 的缺点
值得注意的是,从无模式对话框调用 UIApplication.DoDragDrop 意味着在非 Revit API 上下文中调用 Revit API。绝大多数情况下这是非法的,可能导致无法预测的结果。所以通常我们应该从 Idling 事件或者 external 事件的回调函数中调用 Revit API。但是针对拖放操作,这种方式却可能导致死锁。

原因是 Revit 触发的 Idling 事件和 External 事件都是假设没有用户界面操作的。如果在它们的事件回调中调用触发UI操作,可能会导致如下情况:
1. UI请求被发送到相同的消息队列。但是由于消息队列还在等待 Idling/External 事件的返回,所以这个新的UI请求将永远无法被处理
2. UI请求被发送到另外的消息队列,这个不同的消息队列最终会触发一个新的 Idling/External 事件,然后导致用户界面死锁

所以结论令人失望,没有安全的方式从无模式对话框中调用拖放操作。

定制Revit处理方式的拖放

DoDragDrap的第二个重载是个令人激动的新特性。它允许我们定义Revit接收拖放文件的行为。我们需要做的就是实现一个 IDropHandler 接口,并且在它的 Execute() 方法中
定义我们期望的行为。下面这个例子里,IDropHanlder 接收一个族类型的 ElementId,然后调用 PromptForFamilyInstancePlacement() 方法要求用户拜访它。显然,你可以向 IDropHanlder 传递任何定制的数据,来实现你的需求。
public class LoadedFamilyDropHandler : IDropHandler
{
    public void Execute( UIDocument doc, object data )
    {
      ElementId familySymbolId = (ElementId) data;

      FamilySymbol symbol = doc.Document.GetElement( familySymbolId ) as FamilySymbol;

      if( symbol != null )
      {
      doc.PromptForFamilyInstancePlacement( symbol );
      }
    }
}

private void listView_MouseMove( object sender, MouseEventArgs e )
{
    if( System.Windows.Forms.Control.MouseButtons == MouseButtons.Left )
    {
      ListViewItem selectedItem = this.listView1.SelectedItems.Cast<ListViewItem>().FirstOrDefault<ListViewItem>();

      if( selectedItem != null )
      {
         LoadedFamilyDropHandler myhandler = new LoadedFamilyDropHandler();
         UIApplication.DoDragDrop( selectedItem.Tag, myhandler );
      }
    }
}原文链接:http://blog.csdn.net/flower4wine/article/details/7554773

孙雅 发表于 2014-2-25 10:29:18

路过!!!
不发表意见……

AK47 发表于 2014-6-17 14:35:56

(*^__^*) 嘻嘻……

妮可 发表于 2014-2-20 15:10:49

顶......
楼下跟上.....

熊猫 发表于 2014-2-25 10:32:19

路过!!!
帮顶……

风吹枫落 发表于 2014-2-25 10:33:20

顶起来…………

苦田辛君 发表于 2014-3-10 16:22:29

非常感谢!!

泰安oim 发表于 2014-3-10 16:27:49

楼主辛苦……

大头佬 发表于 2014-3-10 16:28:05

看看啥…………

苦田辛君 发表于 2014-3-10 16:38:29

非常感谢!!

野风 发表于 2014-3-10 16:44:05

了解下BIM.....

教父 发表于 2014-3-10 16:54:13

谢谢老师…

chen_0003 发表于 2014-3-10 16:59:49

顶起来…………

best 发表于 2014-3-10 17:11:01

非常感谢!!

一梦千寻 发表于 2014-3-10 17:16:05

谢谢BIM大神…

bin 发表于 2014-3-13 12:19:52

顶!!!!!!!!!!
页: [1] 2 3 4
查看完整版本: Building Coder - 拖放API