AddHandler命令WillStart/RemveHandler命令WillStart不工作
我试图在用户启动特定命令时更改当前层。我正在将处理程序与命令WillStart/CommandEnded/CommandCancelled等一起使用……我知道Autocad帮助告诉我;我使用命令WillStart更改AutoCAD变量“CLAYER”&在发出命令Ended时返回到原始图层。我微小的大脑(一旦确认…)在想,既然我没有操纵对象本身(我只是在改变“CLAYER”变量&检查/插入层),我仍然在遵守规则……我错了吗?因为我的代码不工作&我的“RemoveHandler命令WillStart”似乎不工作(即使解释器正在调用它)这篇文章让我毛骨悚然……&年龄越来越大……
现在,我在这个网站上查找了以前的文章,发现了一篇关于对象否决的有趣文章。我在autodesk中找不到任何关于否决的文档,除了“创建我的第一个.net项目”在internet上的内容…看起来很有希望,因为我需要掌握…
**** Hidden Message ***** 如果看不到您在代码中做了什么,就很难进行评论。但根据您有限的描述,在命令启动时设置当前层,并在命令结束/取消时将其恢复到上一层是非常容易的,您不需要Overrule的帮助(如果它可以帮助您的需要)
例如,我希望始终在给定层上绘制线,但不希望用户在每次绘制线之前都麻烦正确设置当前层,以下代码用于此目的:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using CadApp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace CommandWillStartHandler
{
public class Commands : IExtensionApplication
{
private static string _savedLayer = null;
private const string LINE_LAYER = "MyLine";
#region IExtensionApplication Interface
public void Initialize()
{
Document dwg = CadApp.DocumentManager.MdiActiveDocument;
Editor ed = dwg.Editor;
try
{
ed.WriteMessage("\nInitialising custom add-in...");
AddCommandHandler();
ed.WriteMessage("\nInitializing custom add-in completed.");
}
catch
{
ed.WriteMessage("\nInitializing custom add-in failed");
}
finally
{
Autodesk.AutoCAD.Internal.Utils.PostCommandPrompt();
}
}
public void Terminate()
{
}
private void AddCommandHandler()
{
CadApp.DocumentManager.DocumentCreated += DocumentManager_DocumentCreated;
foreach (Document d in CadApp.DocumentManager)
{
d.CommandWillStart += Document_CommandWillStart;
d.CommandEnded += Document_CommandEnded;
d.CommandCancelled += Document_CommandCancelled;
}
}
private void DocumentManager_DocumentCreated(object sender, DocumentCollectionEventArgs e)
{
e.Document.CommandWillStart += Document_CommandWillStart;
e.Document.CommandEnded += Document_CommandEnded;
e.Document.CommandCancelled += Document_CommandCancelled;
}
private void Document_CommandEnded(object sender, CommandEventArgs e)
{
Document doc = CadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
ed.WriteMessage("\nCommand {0} ended.", e.GlobalCommandName);
if (!string.IsNullOrEmpty(_savedLayer))
{
CadApp.SetSystemVariable("CLAYER", _savedLayer);
_savedLayer = null;
}
}
private void Document_CommandCancelled(object sender, CommandEventArgs e)
{
Document doc = CadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
ed.WriteMessage("\nCommand {0} cancelled.", e.GlobalCommandName);
if (!string.IsNullOrEmpty(_savedLayer))
{
CadApp.SetSystemVariable("CLAYER", _savedLayer);
_savedLayer = null;
}
}
private void Document_CommandWillStart(object sender, CommandEventArgs e)
{
Document doc = CadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
ed.WriteMessage("\nCommand {0} will start.", e.GlobalCommandName);
//Whenever "LINE" command starts, the active layer is set to
//LINE_LAYER so that the line is drawn on that layer
if (e.GlobalCommandName.ToUpper() == "LINE")
{
_savedLayer = CadApp.GetSystemVariable("CLAYER").ToString();
CadApp.SetSystemVariable("CLAYER", LINE_LAYER);
}
}
#endregion
}
}
HTH 您的代码运行良好,但我的RemoveHandler部分不起作用...在我的窗体中,我有一个“关闭”按钮,它关闭了“RemoveHandler”部分。即使在触发“RemoveHandler”之后,程序仍然发出“CommandWillStart”事件。这是我到目前为止写的(相当简单的)有问题的代码。我砍掉了大部分与事件处理程序无关的代码。关于“RemoveHandler”函数有什么不一致的地方吗?非常感谢你的帮助...谢谢!
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.ApplicationServices.Core.Application
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.ApplicationServices.Application
Imports System.Windows.Forms
Imports Autodesk.AutoCAD.Colors
Imports System.IO
Imports Autodesk.AutoCAD.Runtime
Public Class Form1
Implements IExtensionApplication
Private CurrentLayerName As String
Private _SelectedLayer As LayerData
Private Shared acDoc As Document
Public Sub Initialize() Implements IExtensionApplication.Initialize
Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Initialize")
acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
End Sub
Public Sub Terminate() Implements IExtensionApplication.Terminate
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
_SelectedLayer = New LayerData
End Sub
Private Sub myOnButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles myOnButton.Click
AddHandler acDoc.CommandWillStart, AddressOf SwapTheLayer
End Sub
Private Sub OFF_Button_Click(ByVal sender As Object, ByVal e As EventArgs) Handles OFF_Button.Click
RemoveHandler acDoc.CommandWillStart, AddressOf SwapTheLayer
End Sub
Private Sub SwapTheLayer(ByVal senderObj As Object, ByVal e As CommandEventArgs)
CurrentLayerName = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CLAYER")
Dim importedLayer As Array = _SelectedLayer.ToArray
Select Case e.GlobalCommandName
Case "MTEXT"
If checkIfLayerExistInDrawing(MText_TextBox.Text) = True Then
Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("layer exist")
Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("CLAYER", MText_TextBox.Text.ToString)
Else
Dim myCreateLay As New CreateLayer(importedLayer(0).MyLayerName,
importedLayer(0).MyLayerDescription,
importedLayer(0).MyLayerColor,
importedLayer(0).MyLayerPlot,
importedLayer(0).MyLayerLinetypeName,
importedLayer(0).MyLayerLineweight)
Autodesk.AutoCAD.ApplicationServices.Core.Application.SetSystemVariable("CLAYER", MText_TextBox.Text)
Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("layer do not exist in drawing")
End If
Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("AddHandler CommandEnded")
AddHandler acDoc.CommandEnded, AddressOf BackToOriginalLayer
AddHandler acDoc.CommandCancelled, AddressOf BackToOriginalLayer
AddHandler acDoc.CommandFailed, AddressOf BackToOriginalLayer
End Select
End Sub
Private Sub BackToOriginalLayer(ByVal senderObj As Object, ByVal e As CommandEventArgs)
Select Case e.GlobalCommandName
Case Is = "MTEXT"
Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("CLAYER", CurrentLayerName)
Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("RemoveHandler CommandEnded")
RemoveHandler acDoc.CommandEnded, AddressOf BackToOriginalLayer
RemoveHandler acDoc.CommandCancelled, AddressOf BackToOriginalLayer
RemoveHandler acDoc.CommandFailed, AddressOf BackToOriginalLayer
End Select
End Sub
Private Function checkIfLayerExistInDrawing(ByVal myLayerName As String)
Dim LayerExist As Boolean
'' Get the current document and database
Dim acCurDb As Database = acDoc.Database
'' Start a transaction
Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
'' Open the Layer table for read
Dim acLyrTbl As LayerTable
acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForRead)
'layer exist in drawing...
If acLyrTbl.Has(myLayerName) = False Then
LayerExist = False
Else
LayerExist = True
End If
End Using
Return LayerExist
End Function
End Class
我不明白这个表格是怎么显示的。我猜你有另一个CommandClass,用CommandMethod来定义你的命令,其中窗体被调用。
在没有看到其他代码(您可能认为这些代码与问题无关,但我认为它们是相关的)的情况下,我可以看到您的代码有几个问题:
1。UI设计(在本例中为表单)的良好实践是尽可能将业务逻辑(在本例中为AutoCAD相关操作、处理文档的命令事件)与UI分离。在UI模块中实现IExtensionApplication接口就更差了。您应该将添加/移除事件处理程序放在单独的类中。例如,在your command类中可以有两个CommandMethods。也就是说,你可以有两个独立的custo命令“AddHanler”和“RemoveHandler”,它们不仅可以由用户在命令行作为命令输入,也可以由你的窗体调用(看起来就像你通过调用MdiDocument将窗体显示为无模式(浮动窗体))。SendStringToExecute()。
2。您的代码没有删除事件处理程序的直接原因可能是由于您在Initialize()方法中为MdiActiveDocument设置了一个静态/共享变量aDoc,并且如果MdiActiveDocument发生更改,则从不重新指向它:AutoCAD是多文档应用程序,其活动文档可以更改。您的代码需要确保所有打开的文档都添加/删除了处理程序。或者,如果您只针对特定的文档(不是所有打开的文档),您的代码需要记住哪个文档添加了处理程序,这样您就可以相应地删除它们。还要记住,用户可以打开新文档,关闭现有文档。如果您只针对特定文档(不是所有文档),您可能还希望了解如何将CommandClass与每个文档或所有文档相关联(使用共享或非共享CommandMethod调用)。 在未来的项目中,我会记住这一点……或者在我有时间的时候修改这一点……
在我的编码中,我只是想让它在一个特定的文档中工作。一旦开始工作,我将处理多文档接口。这正是我在初始化部分使用共享/静态文档变量的原因。来自MSDN的共享主题:为了让我的处理程序工作,我认为通过将同一个MdiActiveDocument共享给我的类中的addhandler和removehandler,可以降低出错的风险……正如你所说;如果不使用共享变量,有没有关于如何实现这一点的建议<再次感谢您的时间和建议!非常感谢。。。
页:
[1]