vb.net 中自定义类中的事件

'1.先定义包含事件的类(如下)

Public Class TestEvent
    Public Event MyEvent(ByVal s As String)     '自定义事件
   
    Public Sub StartEvent(ByVal value As String) '触发事件函数
        RaiseEvent MyEvent(value)          '触发事件
    End Sub
End Class

'2.在使用事件的类中添加如下代码
  
      '声明事件对象
      Private WithEvents mEvent As TestEvent
      '实例化
      mEvent = New TestEvent
      '处理事件函数 注意:函数名必须为 变量名_事件名
       Private Sub mEvent_MyEvent(ByVal s As String) Handles mEvent.MyEvent
           MsgBox(s)
       End Sub
       '触发事件
      mEvent.StartEvent("11111")

3.
      '声明事件对象
      Private mEvent As TestEvent
     '实例化以及绑定处理函数
       mEvent = New TestEvent
         AddHandler (mEvent.MyEvent), AddressOf OnMyEvent   

      '处理事件函数
        Private Sub OnMyEvent(ByVal s As String) Handles mEvent.MyEvent
            MsgBox(s)
        End Sub    
          '触发事件
      mEvent.StartEvent("2222222")

vb.net 中自定义类中的事件


基本思路:
1,首先在要定义事件的类中声明事件,然后使用RaiseEvent 激发该事件.
Public Class Person

  Private name As String

   Public Event walked(ByVal distance As Integer)
   
  Public Sub onwalk(ByVal distance As Integer)
    RaiseEvent walked(distance)
  End Sub
End Class
2. 使用WithEvents 声明该类的对象.
  Friend WithEvents myperson As Person
3,编写事件处理代码.
  Private Sub myperson_walked(ByVal distance As Integer) -
   Handles myperson.walked
   TextBox1.Text = "walked" & distance
   End Sub
4,调用事件.
  Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)  Handles Button1.Click
  myperson.onwalk(20)
  End Sub


Vb.Net自定义事件的应用及应注意的地方
主窗体:
Public Event msg(ByVal i As Int16)   '''首先定义一个事件

Dim i As Int16 '''定义一个变量
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        i += 1
        RaiseEvent msg(i) '''激发事件
    End Sub
  

    Dim frm As Addition = Nothing '''从窗体
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If frm Is Nothing Then
            frm = New Addition
            frm.main = Me '''此处是应该注意的地方,一定要把从窗体定义的主窗体设置成此窗体,否则不会引发事件!
        End If

      '''上面定义从窗体的方法,可以避免多次实例化窗体

        frm.Show()
    End Sub

从窗体:

Public WithEvents main As main '''定义主窗体事件并执行

    Private Sub main_msg(ByVal i As Short) Handles main.msg
        Label1.Text = i
    End Sub

1,以上方法是主窗体定义事件,然后触发,在从窗体执行的情况,需要注意的是frm.main=me

此句的意思是从窗体的触发事件是主窗体定义的

2,但是在现实应用中,通常都是从窗体内容发生变化,需要及时更新主窗体,此时代码有小小的变动,如下,

需要仔细看啊!

主窗体:

   Public WithEvents add As Addition
    Dim frm As Addition = Nothing
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If frm Is Nothing Then
            frm = New Addition
            Me.add = frm    '''注意此处的区别
        End If
        frm.Show()
    End Sub

    Private Sub add_msg(ByVal i As Short) Handles add.msg
        Label1.Text = i
    End Sub

从窗体:

       Public Event msg(ByVal i As Int16)
    Dim i As Int16

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        i += 1
        RaiseEvent msg(i)
    End Sub

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/longge7685/archive/2009/06/09/4253203.aspx 呵呵

another blog

 

首先来看一下我们常见的自定义事件实现方式,首先创建可能的事件参数

DemoEventArgs:EventArgs {

1 /// <summary>
2 /// 事件参数
3 /// </summary>
4 public sealed class DemoEventArgs:EventArgs {
5
6 /// <summary>
7 /// 获取或设置事件的上下文
8 /// </summary>
9 public string Context {
10 get { return context; }
11 set { context = value; }
12 }
13 private string context;
14
15
16 }

当然,如果在实际使用中不需要事件参数的话,可以直接使用EventArgs.Empty静态字段。

紧接着我们需要定义事件成员

1/// <summary>
2 /// 事件成员
3 /// </summary>
4 public event EventHandler<DemoEventArgs> NewEv

然后,我们就需要引发这个事件

1 public void InvokeNewEvent() {
2 DemoEventArgs e = new DemoEventArgs();
3 e.Context = "Hello world";
4 this.OnNewEvent(e);
5 }
6
7 protected virtual void OnNewEvent(DemoEventArgs e) {
8 if (NewEvent!=null) {
9 NewEvent(this, e);
10 }
11 }

对于上面的代码,我们通过Reflector工具可以看到,对于事件定义

public event EventHandler<DemoEventArgs> NewEvent;

编译程序会将其翻译成两个public方法。

相应代码如下

1[MethodImpl(MethodImplOptions.Synchronized)]
2public void add_NewEvent(EventHandler<DemoEventArgs> value)
3{
4 this.NewEvent = (EventHandler<DemoEventArgs>) Delegate.Combine(this.NewEvent, value);
5}
6
7[MethodImpl(MethodImplOptions.Synchronized)]
8public void remove_NewEvent(EventHandler<DemoEventArgs> value)
9{
10 this.NewEvent = (EventHandler<DemoEventArgs>) Delegate.Remove(this.NewEvent, value);
11}
12
13
14
15
16

MethodImpOption枚举类型定义了方法是如何被执行的。Synchronized指定了同时只能由一个线程执行该方法。静态方法锁定类型,而实例方法锁定实例。这样做的目的是,保证在操作实例事件时,对于每一个对象,在同一时刻add和remove方法的线程安全。

在类型上,所有事件的add和remove方法都将使用相同的锁。这样造成,在多个线程同时对不同事件进行订阅和撤销的时候,就会出现性能损失。在MSDN上,我们可以查阅到最后由一个注意事项:“实例或类型上的锁定(如同使用 Synchronized 标志一样)对于公共类型是不推荐使用的,其原因在于除了不是自己的代码的其他代码可对公共类型和实例采用锁定。这可能导致死锁或其他同步问题。 ”

线程同步的指导方针是不应该在对象本身上加同步锁,因为同步锁将对所有的代码公开,这意味着任何人都有可能蓄意的编写代码Lock这个对象,造成其它线程死锁。

为此,在大多数情况下上述情况并不可能发生,但是对于一个完美而稳固的组件来说,这就显得相当重要。鉴于以上原因,我们重新定义事件的实现。

1 public class EventDemo {
2 /// <summary>
3 /// 私有同步锁
4 /// </summary>
5 private readonly object _eventLock = new object();
6
7 /// <summary>
8 /// 事件成员
9 /// </summary>
10 private event EventHandler<DemoEventArgs> internalNewEvent;
11 public event EventHandler<DemoEventArgs> NewEvent {
12 add {
13 lock (_eventLock) {
14 internalNewEvent += value;
15 }
16 }
17 remove {
18 lock (_eventLock) {
19 internalNewEvent -= value;
20 }
21 }
22 }
23
24 protected virtual void OnNewEvent(DemoEventArgs e) {
25 //出于线程考虑,委托字段保存到临时字段中
26 EventHandler<DemoEventArgs> t = internalNewEvent;
27 if (t!=null) {
28 internalNewEvent(this, e);
29 }
30 }
31
32 public void InvokeNewEvent() {
33 DemoEventArgs e = new DemoEventArgs();
34 e.Context = "Hello world";
35 this.OnNewEvent(e);
36 }
37
38
39
40 }

再次查看编译程序最终生成的运行时代码

1public void add_NewEvent(EventHandler<DemoEventArgs> value)
2{
3 lock (this._eventLock)
4 {
5 this.internalNewEvent = (EventHandler<DemoEventArgs>) Delegate.Combine(this.internalNewEvent, value);
6 }
7}
8
9public void remove_NewEvent(EventHandler<DemoEventArgs> value)
10{
11 lock (this._eventLock)
12 {
13 this.internalNewEvent = (EventHandler<DemoEventArgs>) Delegate.Remove(this.internalNewEvent, value);
14 }
15}

从性能上考虑,当某个组件定义大量事件时,该实例会浪费大量的内存,之所以是浪费,是因为其中很多事件都没有被订阅。这一点,我们可以参考System.Web.UI.Control中的实现。首先在内部包含了一个EventHandlerList类型的Events属性。


protected EventHandlerList Events
{
get
{
this.EnsureOccasionalFields();
if (this._occasionalFields.Events == null)
{
this._occasionalFields.Events = new EventHandlerList();
}
return this._occasionalFields.Events;
}
}


public event EventHandler DataBinding
{
add
{
this.Events.AddHandler(EventDataBinding, value);
}
remove
{
this.Events.RemoveHandler(EventDataBinding, value);
}
}
引发事件

protected virtual void OnDataBinding(EventArgs e)
{
if (this.HasEvents())
{
EventHandler handler = this._occasionalFields.Events[EventDataBinding] as EventHandler;
if (handler != null)
{
handler(this, e);
}
}
}

这样实现自我感觉不是很好,由于EventHandlerList是一个链表,造成通过内部的find方法查找时,要遍历循环。更理想的做法是使用一个Hashtable来存储委托链。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你可以通过在VB.NET使用Graphics对象和Paint事件自定义绘制图形。以下是实现自定义图形的步骤: 1. 在窗口上添加一个Panel控件,作为绘制图形的容器。 2. 在Panel控件的Paint事件编写代码,以绘制所需的图形。例如,可以使用Graphics对象的DrawLine、DrawRectangle和DrawEllipse方法绘制直线、矩形和椭圆形等。 3. 可以使用Pen和Brush对象来设置绘制图形的颜色和填充效果。 下面是一个简单的示例代码,用于在Panel控件绘制一个圆形: ``` Private Sub Panel1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint Dim g As Graphics = e.Graphics Dim pen As New Pen(Color.Red, 2) Dim brush As New SolidBrush(Color.Yellow) g.DrawEllipse(pen, 10, 10, 100, 100) g.FillEllipse(brush, 10, 10, 100, 100) End Sub ``` 在这个示例,我们在Panel1的Paint事件绘制了一个圆形。首先,我们创建了一个Graphics对象,并使用Pen对象绘制了一个红色的圆形边框。接下来,我们使用Brush对象填充了这个圆形,使其呈现出黄色。 ### 回答2: 在VB.Net,可以通过使用绘图工具和控制窗口的事件来实现自定义图形在窗口上的绘制。 第一步是创建一个窗体应用程序,并在窗体上添加一个绘图控件(如PictureBox)。可以通过在设计视图拖放一个PictureBox控件来完成此操作。 接下来,需要处理窗体的绘制事件(如Paint事件)以进行绘图。可以通过双击窗体以打开代码视图,并将处理程序添加到绘制事件。 在绘图事件处理程序,可以使用Graphics对象来进行绘图操作。可以使用Graphics对象的各种方法和属性来绘制线条、图形、文本等。例如,可以使用Graphics对象的DrawLine方法来绘制线条,使用DrawRectangle方法来绘制矩形,使用DrawEllipse方法来绘制椭圆等等。 在绘制事件处理程序,可以使用窗体的绘图控件的CreateGraphics方法来创建一个Graphics对象。此方法返回一个与该控件相关联的Graphics对象,可以使用该对象进行绘图操作。 通过在绘制事件处理程序编写所需的绘图代码,可以在窗体上自定义绘制图形。可以根据需要添加任意多个绘图代码。 请注意,绘图操作将在每次窗体被重绘时执行(例如在窗体被最小化和恢复、窗体改变大小等情况下)。因此,在绘图代码应该考虑窗体重绘的可能性,以使绘制的图形能够正确显示。 通过以上步骤,就可以在VB.Net自定义绘制图形,并在窗体上显示出来。 ### 回答3: 在使用VB.NET进行图形自定义时,可以使用绘图技术来创建和修改图形,下面是一个简单的示例: 首先,在VB.NET创建一个Windows窗体应用程序。在窗体的OnPaint事件处理程序添加以下代码: ``` Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint Dim g As Graphics = e.Graphics Dim pen As New Pen(Color.Red, 3) '创建红色画笔 '绘制一个圆形 g.DrawEllipse(pen, 50, 50, 100, 100) '绘制一个矩形 g.DrawRectangle(pen, 200, 50, 100, 100) '绘制一个文本 g.DrawString("Hello, VB.NET!", Me.Font, Brushes.Black, 100, 200) End Sub ``` 以上代码使用Graphics对象的DrawEllipse和DrawRectangle方法绘制一个圆形和一个矩形,并使用DrawString方法绘制一段文本。这些方法使用一个画笔对象来确定图形的颜色、大小等属性。 在窗体上,你可以通过Form1_Load事件处理程序或者其他适当的事件处理程序来调用Invalidate方法,以便在窗体上重新绘制图形: ``` Me.Invalidate() ``` 以上就是如何使用VB.NET进行图形的自定义。你可以根据自己的需要来修改和扩展这些代码,创建更复杂和有趣的图形。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值