Autodesk官方最新的.NET教程(六)(vb.net版)

** 第6章 更多的用户界面:添加自定义数据 ** ** **

在本章中,我们将介绍 .NET API 的用户界面部分能做些什么。我们首先将介绍一个自定义上下文菜单(快捷菜单)。接下来我们将实现一个无模式可停靠的面板(一个真正的 AutoCAD 增强辅助窗口)来支持拖放操作。接着我们将介绍通过模式窗体选取实体。最后,我们将介绍使用 AutoCAD 的选项对话框来设置雇员的缺省值。

本章还会介绍和上面内容有关的 API 。

** 第一部分 自定义上下文菜单 ** ** **


到目前为止,我们所写的代码只与 CommandMethod 属性定义的命令行进行相互操作。一个 AutoCAD .NET 程序能通过一个特殊的类来实现装载时的初始化工作。这个类只要实现 IExtensionApplication .NET 接口并暴露一个组件级别的属性(此属性把类定义为 ExtensionApplication ),就可以响应一次性的装载和卸载事件。例子:

  1<assembly: extensionapplication(gettype(asdkclass1))="">
  2
  3Public Class AsdkClass1 
  4
  5Implements IExtensionApplication 
  6
  7** 1)  ** 现在修改  AsdkClass1  类来实现上面的接口。要实现这个接口,你必须实现  Initialize()  和  Terminate  ()  函数。因为我们要实现的是一个接口,而接口中的函数总是定义为纯虚拟的。 
  8
  9Overridable Sub Initialize() Implements IExtensionApplication.Initialize 
 10
 11End Sub 
 12
 13Overridable Sub Terminate() Implements IExtensionApplication.Terminate 
 14
 15End Sub 
 16
 17为了加入自定义上下文菜单,我们必须定义一个  ‘ContextMenuExtension’  类的成员。这个类位于  Autodesk.AutoCAD.Windows  命名空间中。 
 18
 19要使用  ContextMenuExtension  ,我们必须使用  new  关键字来进行初始化,给必要的属性赋值,并调用  Application.AddDefaultContextMenuExtension()  。上下文菜单的工作方式是:对于每个菜单条目,我们定义一个成员函数来处理菜单单击事件。我们可能通过  .NET  的代理来实现。我们使用  VB  关键字  ‘AddHandler’  和  ‘AddressOf’  确定让哪个函数来处理事件。请尽快熟悉这种设计模式,因为在  .NET  中会使用很多。 
 20
 21** 2)  ** 添加一个  ‘ContextMenuExtension’  成员变量和下面两个用来添加和移除自定义菜单的函数。请好好研究一下代码来看看究竟发生了什么。 
 22
 23Sub AddContextMenu() 
 24
 25Try 
 26
 27m_ContextMenu = New ContextMenuExtension() 
 28
 29m_ContextMenu.Title = "Acme Employee Menu" 
 30
 31Dim mi As MenuItem 
 32
 33mi = New MenuItem("Create Employee") 
 34
 35AddHandler mi.Click, AddressOf CallbackOnClick 
 36
 37m_ContextMenu.MenuItems.Add(mi) 
 38
 39Application.AddDefaultContextMenuExtension(m_ContextMenu) 
 40
 41Finally 
 42
 43End Try 
 44
 45End Sub 
 46
 47Sub RemoveContextMenu() 
 48
 49Try 
 50
 51If Not m_ContextMenu Is Nothing Then 
 52
 53Application.RemoveDefaultContextMenuExtension(m_ContextMenu) 
 54
 55m_ContextMenu = Nothing 
 56
 57End If 
 58
 59Finally 
 60
 61End Try 
 62
 63End Sub 
 64
 65注意我们在代码中使用了  ‘CallbackOnClick’  函数。我们希望这个函数(我们现在还没有定义)响应菜单项选择事件。在我们的例子中,我们想要做的是调用我们的成员函数  ‘Create()’  。请加入下面的代码。 
 66
 67Sub CallbackOnClick(ByVal Sender As Object, ByVal e As System.EventArgs) 
 68
 69Create() 
 70
 71End Sub 
 72
 73现在,从  Initialize()  中调用  AddContextMenu()  函数,同样地,请在  Terminate()  中调用  RemoveContextMenu()  。 
 74
 75_ 请运行代码。使用  NETLOAD  来装载编译好的组件,然后在  AutoCAD  的空白处右击……你应该可以看到  ’Acme  ‘快捷菜单了。如果失败了,明明你做的都是正确的……为什么呢?  _
 76
 77通常,  AutoCAD  的数据是存储在文档中的,而访问实体的命令有权修改文档。当我们运行代码来响应上下文菜单单击事件,我们是从命令结构的外部来访问文档。当我们调用的代码尝试通过添加一个雇员来修改文档时,我们就碰到了错误。正确的做法是必须锁住文档,这可以通过使用  Document.LockDocument()  命令来实现。 
 78
 79** 3)  ** ** ** 修改  CallbackOnClick  来锁住文档: 
 80
 81Sub CallbackOnClick(ByVal Sender As Object, ByVal e As System.EventArgs) 
 82
 83Dim docLock As DocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument() 
 84
 85Create() 
 86
 87docLock.Dispose() 
 88
 89End Sub 
 90
 91注意,我们保留了一个  ‘DocumentLock’  对象的拷贝。要把文档解锁,我们只要销毁这个  DocumentLock  对象。 
 92
 93_ 再次运行代码。现在应该可以看到快捷菜单了。  _ _ _
 94
 95_ _
 96
 97** 第2部分 无模式对话框、可进行拖放的可停靠面板  ** ** **
 98
 99为了使我们的用户界面和  AutoCAD  实现无缝链接,我们要尽可能在所有的地方使用同样的用户界面结构。这会使应用程序看起来与  AutoCAD  结合的很好,并有效地减少代码的重复。一个很好的例子是  AutoCAD  中的可停靠面板。 
100
101使用  .NET API  ,我们可以创建一个简单的窗体并把它放到面板中。我们可以实例化一个自定义的  ‘PaletteSet’  对象来包含窗体,并可以把这个  PaletteSet  定义成我们喜欢的样式。 
102
103** 4)  ** ** ** 在解决方案浏览器中通过右击工程来添加一个用户控件。给它命名为  ModelessForm  。使用控件工具箱,加入如下所示的编辑框和标签控件。 
104
105![](http://dev.csdn.net/images/blog_csdn_net/zenghf7878/arx601.JPG)
106
107使用属性窗口设置三个编辑框的属性。设置如下: 
108
109&lt; 首先是最上面的编辑框  &gt;
110
111(  Name  )  = tb_Name 
112
113Text = &lt; 请输入一个名字  &gt;
114
115&lt; 第二个编辑框  &gt;
116
117(Name) = tb_Division 
118
119Text = Sales 
120
121&lt; 第三个编辑框  &gt;
122
123(Name) = tb_Salary 
124
125Text = &lt; 请输入薪水  &gt;
126
127** **
128
129要使用  .NET API  实例化一个面板对象,你必须要实例化用户控件对象(无模式窗体)和  ‘PaletteSet’  对象。调用  PaletteSet  的成员函数  Add  来传递用户控件对象。 
130
131** **
132
133** 5)  ** 接下来,我们要加入一个命令来创建面板。在类中加入一个名为  CreatePalette  的函数和  CommandMethod  属性来定义名为  “PALETTE”  的命令。 
134
135请看一下下面的代码块。这是实例化面板的代码。 
136
137ps = New Autodesk.AutoCAD.Windows.PaletteSet("Employee Palette”) 
138
139Dim myForm As ModelessForm = New ModelessForm() 
140
141ps.Add("Employee Palette", myForm) 
142
143ps.MinimumSize = New System.Drawing.Size(300, 300) 
144
145ps.Visible = True 
146
147** 6)  ** ** ** 把上面的代码加入到  CreatePalette()  函数。  ‘ps’  需要在函数的外部声明: 
148
149Dim ps As Autodesk.AutoCAD.Windows.PaletteSet = Nothing 
150
151在函数的实例化面板代码之前加入检查  ps  是否为  null  的代码。 
152
153编译并运行工程。在  AutoCAD  中装载组件,运行  _ ‘PALETTE’  _ _ 命令来检查面板是否被装载。  _
154
155使用  PaletteSet.Style  来看看  PaletteSetStyles  对象。例如: 
156
157ps.Style = PaletteSetStyles.ShowTabForSingle 
158
159我们也可以试试诸如透明性的属性,例如: 
160
161ps.Opacity = 65 
162
163注意:要使用  PaletteSet  和  PaletteSetStyles  对象,你必须加入两个命名空间  Autodesk.AutoCAD.Windows  和  Autodesk.AutoCAD.Windows.Palette 
164
165在我们继续之前,让我们执行一个快速的维护更新:请在  AsdkClass1  类中加入下列成员: 
166
167Public Shared sDivisionDefault As String = "Sales" 
168
169Public Shared sDivisionManager As String = "Fiona Q. Farnsby" ‘ for this, you can chose any name you like 
170
171这些值将被用作为部门和部门经理的缺省值。由于它们被声明为  ’static’  ,它们在每个程序中只实例化一次,并在组件装载的时候实例化。 
172
173** **
174
175** 第  ** ** 2a  ** ** 部分 在无模式窗体中加入拖放支持  ** ** **
176
177在这部分,我们将加入允许我们使用面板窗体中编辑框的值来创建一个雇员。当用户从面板中拖动到  AutoCAD  中,将会提示输入职位,一个新的雇员实体将使用这些值来进行创建。 
178
179** 7)  ** 为了支持拖放,我们首先需要一个对象来进行拖动。在编辑框的下面,另外加入一个名为  DragLabel  的标签控件,设置标签的文本为一些提示性的东西(  ‘Drag to Create Employee’  )。通过这个标签,我们可以在  AutoCAD  中处理拖放。 
180
181要捕捉到什么时候拖动事件发生,我们必须要知道什么时候鼠标开始操作。 
182
183首先,你要注意的是缺省地  DragLabel  被声明为  ‘WithEvents’  ,这允许  DragLabel  对象可以接收影响它的事件通知,包括我们感兴趣的  ‘MouseMove’  在内。 
184
185** 8)  ** 在  ModelessForm  类中加入下面的函数声明: 
186
187Private Sub DragLabel_MouseMove() 
188
189现在在  ‘Handles DragLabel.’  后面加入点来看智能提示  : 
190
191Private Sub _ DragLabel_MouseMove()Handles DragLabel. 
192
193可以看到我们可以选择的所有事件。找到  ‘MouseMove’  并把它加入。在  MouseMove  事件下面有一行蓝色的东西(智能提示),因为它们的形式不一样。通常,事件处理使用两个参数,一个  object  类的  sender  和与事件有关的参数。对于  MouseMove  ,我们也要做同样的事情。改变函数的声明来接收  ‘sender’  和  ‘e’  。 
194
195Private Sub DragLabel_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles DragLabel.MouseMove 
196
197End Sub 
198
199_ 运行这个工程,检查一下当鼠标经过文本的时候,函数是否被调用的。  _ _ _
200
201我们还可以进一步知道是不是按了鼠标左键  : 
202
203If (System.Windows.Forms.Control.MouseButtons = System.Windows.Forms.MouseButtons.Left) Then 
204
205End If 
206
207我们需要一个方法来检测什么时候对象被拖入到  AutoCAD  。我们可以使用  .NET  的基类  DropTarget  来实现。要使用它,你只要创建从这个基类派生的类并实现你想要的函数。在我们这个例子中,我们需要的是  OnDrop()  。 
208
209** 9)  ** 在工程中加入一个从  Autodesk.AutoCAD.Windows.DropTarget  派生的类  ‘MyDropTarget’  。如果你把这个类加入到  ModelessForm  .cs  文件中,请把这个类加入到  ModelessForm  类之后。 
210
211Public Overrides Sub OnDrop(ByVal e As System.Windows.Forms.DragEventArgs) 
212
213End Sub 
214
215在这个函数中,我们最后会调用  AsdkClass1  的成员  CreateDivision()  和  CreateEmployee  ,传入  ModelessForm  类中的编辑框的值。要实现这个功能,我们需要一个方法来连接  ModelessForm  实例。最佳的方法是通过  DragEventArgs  。但首先我们要把鼠标事件连接到  MyDropTarget  类。 
216
217** 10)  ** 加入下面的代码到鼠标左键(  MouseButtons.Left  )处理函数中: 
218
219Application.DoDragDrop(Me, Me, System.Windows.Forms.DragDropEffects.All, New MyDropTarget()) 
220
221注意我们传入  ’me’  两次。第一次是用于  Control  参数,第二次是用于传入用户自定义数据。因为我们传入的是  ModelessForm  类的实例,所以我们可以在放下的时候使用它来获取编辑框的值。 
222
223** 11)  ** 回到  OnDrop  处理函数,让我们使用参数来调用创建雇员的函数。首先,添加职位提示的代码。在  AsdkClass1.Create()  中已经有相关的代码了,位于  ‘Get Employees Coordinates…’.  注释下面。添加此代码来提示输入职位。 
224
225** 12)  ** 接下来,获取传入到  DragEventArgs  参数的  ModelessForm  对象: 
226
227Dim ctrl As ModelessForm = e.Data.GetData(GetType(ModelessForm)) 
228
229请注意一下怎样通过  GetType  关键字把参数强制转化为  ModelessForm  的实例。 
230
231** 13)  ** 使用上面的实例来调用  AsdkClass1  成员: 
232
233AsdkClass1.CreateDivision(ctrl.tb_Division.Text, AsdkClass1.sDivisionManager) 
234
235AsdkClass1.CreateEmployee(ctrl.tb_Name.Text, ctrl.tb_Division.Text, ctrl.tb_Salary.Text, prPosRes.Value()) 
236
237注意:  AsdkClass1  的方法要不通过  AsdkClass1  的实例来调用,那么方法必须被声明为  ’  Shared  ’  。因为  public static  方法只能调用其它的  Shared  方法,你需要修改几个  AsdkClass1  类中的方法为  ’  Shared  ’  。请你进行相关的修改(应该至少有  4  项要修改)。 
238
239** 14)  ** 最后,因为我们处理的事件位于  AutoCAD  命令之外,我们必须再次在会修改数据库的代码处锁住文档。请加入锁住文档的代码,加入的方法与前面的上下文菜单是一样的。 
240
241_ 编译、装载并运行组件,使用  _ _ PALETTE  _ _ 命令。你应该可以使用拖放操作来创建一个雇员了。  _ _ _
242
243_ _
244
245_ _
246
247** 第三部分 从有模式窗体中选择实体  ** ** **
248
249本章的以下部分将演示获取一个用户在屏幕上选择的雇员实例的详细信息,并把信息显示在一个有模式窗体的编辑框中。这部分的重点是创建一个有模式窗体,并在执行选择操作而窗体要失去焦点时隐藏它。为了获取雇员的详细信息,我们将使用第  4  章结束时给出的  ListEmployee  帮助函数。 
250
251首先,我们需要创建一个窗体类。这个类是一个真实的窗体而不是我们在  &lt;span lang="EN-US" style="font-size: 10pt;</assembly:>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus