![]() |
|
| |
|
![]() |
|
主题工具 | 搜索本主题 | 显示模式 |
|
![]() |
#1 |
高级会员
注册日期: 06-11
帖子: 14579
精华: 1
现金: 224494 标准币
资产: 234494 标准币
![]() |
![]() 使用.net在在文档状态栏实现文档标签控件功能 - 精华帖集合
www.dimcax.com 使用.net在在文档状态栏实现文档标签控件功能 using autodesk.autocad.applicationservices; using autodesk.autocad.databaseservices; using system.collections.generic; using system.windows.forms; //支持程序后台关闭文档 namespace freefly.arx { public class docstatusbar { // 用于存储文档与按钮的对应关系 private class doclistnode { private int mindex; //按钮的顺序 private document mdoc; //对应的文档 public int index { get { return mindex; } set { mindex = value; } } public document doc { get { return mdoc; } set { mdoc = value; } } public doclistnode(int index, document doc) { mindex = index; mdoc = doc; } } // 用于存储文档集合的状态 private class doccollectionstatus { public static int doccount = 0; //已经打开的文档数目 public static int activedoc = 0; //当前活动的文档 } private static bool isfirst = true; //记录该状态栏按钮是否第一次加载 //private static int maxcount = 7; //允许显示的最多细节数目,最后修改,增加锁定以保证稳定。 private static string firstpanename = "散步的木头"; //标志位显示的文本 private static int firstpanewidth = 30; //标志位的宽度 private static int panemaxwidth = 200; //按钮的最大宽度 private static int paneminwidth = 50; //按钮的最小宽度 private static int willdestroyeddoc = 0; //即将要关闭的文档 private static linkedlist<doclistnode> doclist = new linkedlist<doclistnode>();//将来修改为arraylist类型试试 // 增加每个文档的按钮 //应该在最前面那个标志按钮上加标志图像。 public static void mystatusbar() { if (isfirst) { autodesk.autocad.applicationservices.documentcollection doccollection = autodesk.autocad.applicationservices.application.documentmanager; try { insertstatusbaritem(0, firstpanename, "", autodesk.autocad.windows.panestyles.noborders, firstpanewidth, firstpanewidth);//修改以使界面明朗 int i = 1; foreach (document doc in doccollection) { autodesk.autocad.windows.panestyles mystyle; if (doc.isactive == true) { mystyle = autodesk.autocad.windows.panestyles.normal; doccollectionstatus.activedoc = i; } else { mystyle = autodesk.autocad.windows.panestyles.popout; } insertstatusbaritem(i, getfilename(doc.name), doc.name, mystyle, panemaxwidth, paneminwidth); doclist.addlast(new doclistnode(i, doc));//doclist.addlast(curdoclistnode);//传递静态的变量会出错。 i += 1; doccollectionstatus.doccount += 1; doc.begindocumentclose += new documentbegincloseeventhandler(doc_begindocumentclose); doc.database.savecomplete += new databaseioeventhandler(database_savecomplete); } doccollection.documentactivated += new documentcollectioneventhandler(doccollection_documentactivated); doccollection.documentcreated += new documentcollectioneventhandler(doccollection_documentcreated); doccollection.documentdestroyed += new documentdestroyedeventhandler(doccollection_documentdestroyed); isfirst = false; } catch { messagebox.show("addstatusbartodoc方法中出错!"); } } } // 在每个文档中增加一个按钮 private static void insertstatusbaritem(int index, string panetext, string panetooltiptext, autodesk.autocad.windows.panestyles mystyle, int maxwidth, int minwidth) { autodesk.autocad.applicationservices.documentcollection doccollection = autodesk.autocad.applicationservices.application.documentmanager; try { foreach (document doc in doccollection) { autodesk.autocad.windows.statusbar mystatus = doc.statusbar; autodesk.autocad.windows.panecollection docpanecolletion = mystatus.panes; autodesk.autocad.windows.pane mypane = new autodesk.autocad.windows.pane(); mypane.style = mystyle; mypane.maximumwidth = maxwidth; mypane.minimumwidth = minwidth; mypane.text = panetext; mypane.tooltiptext = panetooltiptext; mypane.mousedown += new autodesk.autocad.windows.statusbarmousedowneventhandler(statusbar_mousedown); docpanecolletion.insert(index, mypane); mystatus.update(); } } catch { messagebox.show("insertstatusbaritem方法中出错!"); } } // 新建打开文档 private static void doccollection_documentcreated(object sender, documentcollectioneventargs e) { autodesk.autocad.applicationservices.documentcollection doccollection = (autodesk.autocad.applicationservices.documentcollection)sender; document curdoc = doccollection.mdiactivedocument; try { #region 给新文档增加之前的按钮。 autodesk.autocad.windows.statusbar mystatus = curdoc.statusbar; autodesk.autocad.windows.panecollection docpanecolletion = mystatus.panes; autodesk.autocad.windows.pane mypane = new autodesk.autocad.windows.pane(); mypane.style = autodesk.autocad.windows.panestyles.noborders; //先添加前面那个标志位按钮 mypane.maximumwidth = firstpanewidth; mypane.minimumwidth = firstpanewidth; mypane.text = firstpanename; mypane.tooltiptext = ""; docpanecolletion.insert(0, mypane); foreach (doclistnode mdoc in doclist) { //注意要重新初始变量,不能与前面共用一个变量,会引起引用同一个对象 mypane = new autodesk.autocad.windows.pane(); if (mdoc.index != doccollectionstatus.activedoc) { mypane.style = autodesk.autocad.windows.panestyles.popout; } else { mypane.style = autodesk.autocad.windows.panestyles.normal; } mypane.maximumwidth = panemaxwidth; mypane.minimumwidth = paneminwidth; mypane.text = getfilename(mdoc.doc.name); mypane.tooltiptext = mdoc.doc.name; mypane.mousedown += new autodesk.autocad.windows.statusbarmousedowneventhandler(statusbar_mousedown); docpanecolletion.insert(mdoc.index, mypane); } mystatus.update(); #endregion #region 在各文档增加新文档的按钮,并修改文档链表数据,设置新文档为当前文档。 doccollectionstatus.doccount += 1; insertstatusbaritem(doccollectionstatus.doccount, getfilename(curdoc.name), curdoc.name, autodesk.autocad.windows.panestyles.popout, panemaxwidth, paneminwidth); doclist.addlast(new doclistnode(doccollectionstatus.doccount, curdoc)); int lastdoc = doccollectionstatus.activedoc; doccollectionstatus.activedoc = doccollectionstatus.doccount; foreach (document doc in doccollection) { mystatus = doc.statusbar; docpanecolletion = mystatus.panes; docpanecolletion[lastdoc].style = autodesk.autocad.windows.panestyles.popout; docpanecolletion[doccollectionstatus.activedoc].style = autodesk.autocad.windows.panestyles.normal; mystatus.update(); } curdoc.begindocumentclose += new documentbegincloseeventhandler(doc_begindocumentclose); curdoc.database.savecomplete += new databaseioeventhandler(database_savecomplete); #endregion } catch { messagebox.show("doccollection_documentcreated事件中出错!"); } } // 由选取菜单、打开、关闭文档而改变活动文档引起的事件处理,必须保证发生这个事件以前文档状态链表更新过。 private static void doccollection_documentactivated(object sender, documentcollectioneventargs e) { autodesk.autocad.applicationservices.documentcollection doccollection = autodesk.autocad.applicationservices.application.documentmanager; document curdoc = autodesk.autocad.applicationservices.application.documentmanager.mdiactivedocument; try { foreach (doclistnode mdoc in doclist) { if (mdoc.doc.equals(curdoc)) { if (mdoc.index != doccollectionstatus.activedoc) { int lastdoc = doccollectionstatus.activedoc; doccollectionstatus.activedoc = mdoc.index; foreach (document doc1 in doccollection) { autodesk.autocad.windows.statusbar mystatus = doc1.statusbar; autodesk.autocad.windows.panecollection docpanecolletion = mystatus.panes; docpanecolletion[lastdoc].style = autodesk.autocad.windows.panestyles.popout; docpanecolletion[doccollectionstatus.activedoc].style = autodesk.autocad.windows.panestyles.normal; mystatus.update(); } } } } } catch { messagebox.show("doccollection_documentactivated事件中出错!"); } } //包括正常关闭文档的事件,以及打开文档引起临时文档的关闭事件,注意在关闭最后一个文档时候的正确性。 //必须在这个事件中释放对要关闭的文档的引用,否则发生错误,另外注意索引的修改,防止地址越界。 private static void doc_begindocumentclose(object sender, documentbegincloseeventargs e) { autodesk.autocad.applicationservices.documentcollection doccollection = autodesk.autocad.applicationservices.application.documentmanager; try { document curdoc = (document)sender; doclistnode bedelnode = new doclistnode(0, null); bool findit = false; foreach (doclistnode mdoc in doclist) { if (mdoc.doc.equals(curdoc)) { willdestroyeddoc = mdoc.index; mdoc.doc = null; bedelnode = mdoc; findit = true; } else { if (findit) { mdoc.index -= 1; } } } doclist.remove(bedelnode); autodesk.autocad.windows.statusbar mystatus; foreach (document doc in doccollection) { mystatus = doc.statusbar; autodesk.autocad.windows.panecollection docpanecolletion = mystatus.panes; autodesk.autocad.windows.pane mypane = docpanecolletion[willdestroyeddoc]; mypane.mousedown -= new autodesk.autocad.windows.statusbarmousedowneventhandler(statusbar_mousedown); mypane = null; docpanecolletion.removeat(willdestroyeddoc); mystatus.update(); } doccollectionstatus.doccount -= 1; mystatus = curdoc.statusbar; for (int i = 0; i <= doccollectionstatus.doccount; i++) { mystatus.panes.removeat(0); } curdoc.database.savecomplete -= new databaseioeventhandler(database_savecomplete); curdoc.begindocumentclose -= new documentbegincloseeventhandler(doc_begindocumentclose); } catch { messagebox.show("doc_begindocumentclose事件中出错!"); } } // 文档关闭已完成事件 private static void doccollection_documentdestroyed(object sender, documentdestroyedeventargs e) { autodesk.autocad.applicationservices.documentcollection doccollection = (documentcollection)sender; autodesk.autocad.applicationservices.document curdoc = doccollection.mdiactivedocument; try { foreach (doclistnode mdoc in doclist) { if (mdoc.doc.equals(curdoc)) { doccollectionstatus.activedoc = mdoc.index; foreach (document doc in doccollection) { doc.statusbar.panes[mdoc.index].style = autodesk.autocad.windows.panestyles.normal; } } } } catch { messagebox.show("doccollection_documentdestroyed事件中出错!"); } } //鼠标命中状态栏文档的按钮引起的事件 private static void statusbar_mousedown(object sender, autodesk.autocad.windows.statusbarmousedowneventargs e) { autodesk.autocad.applicationservices.documentcollection doccollection = autodesk.autocad.applicationservices.application.documentmanager; document curdoc = doccollection.mdiactivedocument; autodesk.autocad.windows.pane willactivepane = (autodesk.autocad.windows.pane)sender; autodesk.autocad.windows.panecollection mdipanecolletion = curdoc.statusbar.panes; try { int lastdoc = 0; for (int i = 1; i <= doccollectionstatus.doccount; i++) if (mdipanecolletion.equals(willactivepane)) { if (doccollectionstatus.activedoc != i) { lastdoc = doccollectionstatus.activedoc; doccollectionstatus.activedoc = i; } } if (lastdoc != 0) { foreach (doclistnode var in doclist) { if (var.index == doccollectionstatus.activedoc) { doccollection.mdiactivedocument = var.doc;//文档激活 } } foreach (document doc in doccollection) { autodesk.autocad.windows.statusbar mystatus = doc.statusbar; autodesk.autocad.windows.panecollection docpanecolletion = mystatus.panes; docpanecolletion[lastdoc].style = autodesk.autocad.windows.panestyles.popout; docpanecolletion[doccollectionstatus.activedoc].style = autodesk.autocad.windows.panestyles.normal; mystatus.update(); } } } catch { messagebox.show("statusbar_mousedown事件中出错!"); } } //文档保存事件 private static void database_savecomplete(object sender, databaseioeventargs e) { try { autodesk.autocad.applicationservices.documentcollection doccollection = autodesk.autocad.applicationservices.application.documentmanager; autodesk.autocad.databaseservices.database curdatabase = (autodesk.autocad.databaseservices.database)sender; autodesk.autocad.windows.pane mypane; foreach (doclistnode mdoc in doclist) { if (mdoc.doc.database.equals(curdatabase)) { foreach (document doc in doccollection) { mypane = doc.statusbar.panes[mdoc.index]; mypane.text = getfilename(curdatabase.filename); mypane.tooltiptext = curdatabase.filename; doc.statusbar.update(); } } } } catch { messagebox.show("database_savecomplete事件中出错!"); } } // 提取文件名方法 private static string getfilename(string filename) { return filename.substring(filename.lastindexof("\\") + 1); } } } 注意,只能使用于08以上版本。07的显示不出来!实现效果: c#最适合开发autocad,因为它拥有vb容易的特点,却具有vc++的强大功能。 linkedlist是啥东东?编不过耶! linkedlist是啥东东?编不过耶! 原帖由 azbd 于 2008-5-23 11:29 am 发表 linkedlist是啥东东?编不过耶! 是一个类似于list的类,有这个命名空间就可以了:system.collections.generic c#最适合开发autocad,因为它拥有vb容易的特点,却具有vc++的强大功能。 不起作用 现在编译通过了,但是没有任何作用。我的cad为2009. 分析了一下程序,只定义了一个类。没有找到命令入口。 程序的入口是docstatusbar.mystatusbar(); 这段程序在我的程序集里面是通过自动加载来运行的,入口需要你自己添加,你可以在初始化里面运行那个入口,或者自己在那个入口函数那儿定义命令。另外需要打开cad中的图形状态栏选项,请参考下图: “散步的木头”的回答。在添加命令接口和打开图形状态栏后,能够显示,但不能用鼠标点击按钮来切换文档(没有任何动作),请指教。我是在cad2009中测试的。你说的自动加载是不是相当于netload命令。但还是要有地方调用mystatusbar()才行那! 我电脑上只有cad2008,不好意思,没有在2009上面测试过,应用到2009的话请确认那些事件在2009中能正常使用,不过按autodesk的版本发展计划,应该能通用,但可能两个版本的状态栏有一点微小的区别,也就是两个版本中缺省的状态栏里面的项目数量不一样,看懂我那个代码然后自己相应修改一下就行了,一般需要修改的可能只有一行代码。自动加载是给类定义iextensionapplication接口,然后initialize()方法中调用那个入口,再netload得时候就能自动运行。具体示例可以参考kean的有关文章。 [ ] 好多朋友反映入口的问题,我把完整的文件发上来,不过在2009下使用的问题我现在还解决不了,我电脑上只有2008,没法调试,希望大家见谅!~ 这个为修改以后的代码! |
![]() |
![]() |
GDT自动化论坛(仅游客可见) |