Event Handling an Abstract Class - vb.net

Basically, I have a custom child form class which has events that will be passed to the parent. In the custom child form, I have a declaration of a "MustInherit" class that inherits the DevExpress User Control Class.
The reason for this, is I have many user controls that derive from this base class, and the child form can have an instance of any one of these controls, and doesnt care which. The only requirement is that the child form can handle the same events from each type of control the same way.
Some watered down code snippets(still pretty long unfortunately):
'''Inherited Class
Public Class ChildControlInheritedClass
'A Button Click event that starts the chain of events.
Private Sub btnMoveDocker_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConvertToTab.Click
OnMoveToDocker(Me, New ChildGridMoveArgs(Me))
End Sub
End Class
'''Base Class
Public MustInherit Class ChildControlBaseClass
Inherits DevExpress.XtraEditors.XtraUserControl
Public Class ChildGridMoveArgs
Inherits System.EventArgs
Public Sub New(ByVal _ChildControl As ChildControlInheritedClass)
ChildControl = _ChildControl
End Sub
Public ChildControl As ChildControlInheritedClass
End Class
Public Event MoveToDocker(ByVal sender As Object, ByVal e As ChildGridMoveArgs)
Protected Overridable Sub OnMoveToDocker(ByVal sender As Object, ByVal e As ChildGridMoveArgs)
'''Once this RaiseEvent is fired, nothing happens. The child form is oblivious.
RaiseEvent MoveToDocker(sender, e)
End Sub
End Class
'''Child Form Class
Public Class ChildForm
Private WithEvents cgChild As ChildControlBaseClass
Public Property ChildGrid() As ChildControlInheritedClass
Get
Return cgChild
End Get
Set(ByVal value As ChildControlInheritedClass)
RemoveHandler cgChild.MoveToDocker, AddressOf cgChild_MoveToDocker
cgChild.Dispose()
cgChild = Nothing
cgChild = value
AddHandler cgChild.MoveToDocker, AddressOf cgChild_MoveToDocker
End Set
End Property
Public Event MoveToDocker(ByVal sender As Object, ByVal e As ChildControlInheritedClass.ChildGridMoveArgs)
Public Sub cgChild_MoveToDocker(ByVal sender As Object, ByVal e As ChildControlInheritedClass.ChildGridMoveArgs)
RaiseEvent MoveToDocker(sender, New ChildControlInheritedClass.ChildGridMoveArgs(cgChild))
End Sub
End Class
Public Class frmMain
Private Sub OpenNewWindow()
Dim frm As New ChildForm
Dim chld As New ChildControlInheritedClass
frm.ChildGrid = chld
frm.Show()
End Sub
End Class
In a nutshell, thats how I made the child form and how everything is suppose to work. But when I press the button in the inherited child control, the event only gets as far as the base class and never traverses the RaiseEvent into the child form thats suppose to handle the event.
Am I even in the ballpark here?
Thanks for reading!

You forgot to add your event handle by using AddHandler or Handles identifier. See below using the Handles cgChild.MoveToDocker identifier.
Public Class ChildForm
...
Public Sub cgChild_MoveToDocker(ByVal sender As Object, ByVal e As ChildControlInheritedClass.ChildGridMoveArgs) Handles cgChild.MoveToDocker
RaiseEvent MoveToDocker(sender, New ChildControlInheritedClass.ChildGridMoveArgs(cgChild))
End Sub
End Class

Related

PropertyChanged subroutine is not called/triggered

Windows Forms Application in VS2012
Target .NET Framework: 4.5
Created a project containing a Form (Form1) and a class (Class1). Form has a button (Button1) object. Code below:
Class1:
Imports System.ComponentModel
Public Class Class1
Implements INotifyPropertyChanged
Private _PropValue As String
Public Property PropValue As String
Get
Return _PropValue
End Get
Set(value As String)
_PropValue = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("PropValue"))
MsgBox("Event Raised") ' FOR TESTING
End Set
End Property
Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
End Class
Form1:
Imports System.ComponentModel
Public Class Form1
Private WithEvents _Class1 As Class1
Private Sub _Class1_PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Handles _Class1.PropertyChanged
MsgBox("Property Changed subroutine") ' FOR TESTING
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim tmpObj As Class1 = New Class1
tmpObj.PropValue = "Value-1"
tmpObj.PropValue = "Value-2"
End Sub
End Class
When executing the application and clicking on Button1, received 2 popup messages "Event Raised" from MsgBox in Class1. I'm trying to get the message "Property Changed subroutine" from _Class1_PropertyChanged subroutine. Haven't been successful so far.
You're not changing the property value of the object whose event you're handling. You're handling the event of the object you assign to the _Class1 field but you're changing the property value of a different object assigned to the tmpObj local variable. Get rid of that local variable and use the field only.

Inherited class event is not fired

First of all, this is my very first question in this community. Please give me some advice if I did it in the wrong way.
I need a little bit help. I am actually working on a BMEcat class library, BMEcat is a data exchange format for electronic catalogs. Anything works fine, but I realized that there is a memory problem while processing very large files. Because of this, I want to send an event for any processed article/product instead of creating a huge structure in memory.
This is the point where my problem begins.
I have a class CTRANSACTION, from which the classes CT_NEW_CATALOG, CT_UPDATE_PRODUCTS and CT_UPDATE_PRICES are derived.
In the base class CTRANSACTION there is an event defined:
Public Event Transaction_OnNewArticle(ByVal sender As Object, ByVal e As ArticleEventArgs)
The class CBMECAT has the variable
Public WithEvents TRANSACTION As CTRANSACTION
and the event handler
Private Sub TRANSACTION_Transaction_OnNewArticle(sender As Object, e As ArticleEventArgs) Handles TRANSACTION.Transaction_OnNewArticle
'...
End Sub
Because I cannot send the event Transaction_OnNewArticle from the derived CT_NEW_CATALOG class I let it call the TransactionEventOnNewArticle method instead, which is defined in CTRANSACTION. TransactionEventOnNewArticle then calls RaiseEvent Transaction_OnNewArticle.
Everything works wonderful, but the event Transaction_OnNewArticle is not fired. Is there a way to fix it?
Public MustInherit Class CTRANSACTION
Inherits CBMECAT_NODE
Public Event Transaction_OnNewArticle(ByVal sender As Object, ByVal e As ArticleEventArgs)
Public Sub TransactionEventOnNewArticle(ByVal sender As Object, ByVal e As ArticleEventArgs)
RaiseEvent Transaction_OnNewArticle(sender, e)
End Sub
Public Class CT_NEW_CATALOG
Inherits CTRANSACTION
Public Overrides Sub EventOnNewArticle(ByVal sender As Object, ByVal e As ArticleEventArgs)
TransactionEventOnNewArticle(sender, e)
End Sub
Public Class CBMECAT
Inherits CBMECAT_NODE
Public WithEvents TRANSACTION As CTRANSACTION
Private Sub TRANSACTION_Transaction_OnNewArticle(sender As Object, e As ArticleEventArgs) Handles TRANSACTION.Transaction_OnNewArticle
'THIS method is never called - why?
End Sub
End Class
UPDATE
Public Class CBMECAT_ELEMENT
Public Overridable Sub EventOnNewArticle(ByVal sender As Object, ByVal e As ArticleEventArgs)
End Sub
'Please notice that CBMECAT_ELEMENT is the base class of EVERY other class in the library.
'There is a class CBMECAT_NODE, which represents every node of the BMEcat XML structure and is derived from CBMECAT_ELEMENT.
'In CBMECAT_NODE is EventOnNewArticle called whenever an article is processed;
Public Class CBMECAT_NODE
Inherits CBMECAT_ELEMENT
Public Overridable Function CreateChildNode(ByRef Nodename As String, Optional ByRef Parent As CBMECAT_NODE = Nothing) As CBMECAT_ELEMENT
Select Case Nodename
[..]
Case ELEMENT_ARTICLE
CreateChildNode = New CARTICLE(Parent)
Dim e As New ArticleEventArgs With
{
.ARTICLE = CreateChildNode
}
EventOnNewArticle(Me, e)
[..]
UPDATE
Public Class CARTICLE
Inherits CBMECAT_NODE
Public Sub New(ByRef Father As CBMECAT_NODE)
[..]
Public Overrides Sub Read()
[..]
Public Overrides Sub Write()
[..]
Public Overrides Sub Validate()
[..]
UPDATE
Calling sequence:
CBMECAT_NODE.CreateChildNode calls CT_NEW_CATALOG.EventOnNewArticle <- OK
CT_NEW_CATALOG.EventOnNewArticle calls CTRANSACTION.TransactionEventOnNewArticle <- OK
CTRANSACTION.TransactionEventOnNewArticle fires Event Transaction_OnNewArticle
but this event is not received by the event handlier in CBMECAT
If I fire the event manually from a method in CTRANSACTION the event IS received by the event handler.
I also experimentet with AddHandler/RemoveHandler, but this also did not work.
Thank you, Visual Vincent, for helping me to focus the problem and to solve it. In deed it was "a little bit" complicated.
Class CBMECAT had the following read method:
Public Overrides Sub Read()
MyBase.Read()
GetContent(HEADER, ELEMENT_HEADER)
Select Case TransactionType
Case TransactionTypes.T_NEW_CATALOG
GetContent(TRANSACTION, ELEMENT_T_NEW_CATALOG)
Case TransactionTypes.T_UPDATE_PRICES
GetContent(TRANSACTION, ELEMENT_T_UPDATE_PRICES)
Case TransactionTypes.T_UPDATE_PRODUCTS
GetContent(TRANSACTION, ELEMENT_T_UPDATE_PRODUCTS)
Case Else
ReportError(ERROR_BMECAT_UNKNOWN_TRANSACTION_TYPE)
End Select
Validate()
End Sub
MyBase.Read reads the complete XML file and while reading it, the events should be fired. But at this moment the variable TRANSACTION is not assigned by it´s value. This is done by calling GetContent after the reading process has finished.
I have changed to:
TRANSACTION = New CT_NEW_CATALOG
TRANSACTION.Read()
Now all events are fired as expected.
I will remove TransactionEventOnNewArticle() from CBMECAT_ELEMENT. Thanks again, Vincent, for your suggestion. :-)

VB.Net Inheritance Override

I'm new to VB.Net (I'm from a foxpro background) and have had my head in a book for the last two weeks trying to get started with some of the basics.
I'm trying to master class inheritance and have what I hope is not too much of a challenging question.
I've created a class and compiled it as a DLL. It simply allows me to place a button on a form. I just want to capture the Click event - which I've managed to do but would like to override the inherited code rather than having both fire which seems to be happening at the moment.
I realise I could just double click the control and enter code directly into the MyButton1 click event but wanted to trap this programmatically instead via the handler.
I thought this would just be a case of using the overridable / overrides options.
Here's the code in my class:
Imports System.Windows.Forms
Imports System.Drawing
Public Class MyButton
Inherits Windows.Forms.Button
Sub New()
End Sub
Protected Overridable Sub MyButton_Click(sender As Object, e As System.EventArgs) Handles Me.Click
MsgBox("Base Click")
End Sub
End Class
Then I place the button on my form and name it MyButton1 and in the load event:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddHandler MyButton1.Click, AddressOf Button_Click
End Sub
Private Sub Button_Click()
MsgBox("Actual Click")
End Sub
Problem is, both events fire and I want the option to override / turn off the base event.
I thought I could just add the 'overrides' keyword to the Button_Click routine i.e.:
Private Sub Overrides Button_Click()
but I get an error message Sub Button_Click() cannot be declared 'overrides' because it does not override a sub in a base class
So to clarify - at the moment my code fires both events so I get two messages. I want to be able to turn off / supress the base class event.
Any help would be much appreciated.
I thought this would just be a case of using the overridable /
overrides options.
The fundamental problem here is that you're trying to push a square peg into a round hole.
To override something, you need to have inheritance involved. The derived class is overriding something that was inherited from the base class. For instance, if you inherited from your MyButton class to create a new type of Button called MyButtonDerived, then you could do it as expected:
Public Class MyButton
Inherits Windows.Forms.Button
Protected Overridable Sub MyButton_Click(sender As Object, e As System.EventArgs) Handles Me.Click
MsgBox("Base Click")
End Sub
End Class
Public Class MyButtonDerived
Inherits MyButton
Protected Overrides Sub MyButton_Click(sender As Object, e As EventArgs)
' We don't call the base method...
' MyBase.MyButton_Click(sender, e)
' ... and instead do something else:
MsgBox("Derived Click")
End Sub
End Class
In contrast, when you've placed MyButton onto the Form as in your original problem description, no inheritance has taken place. Instead what you've setup is "object composition"; the form contains an instance of the button (not derived from it). While it may be possible to change what happens when the button is clicked from the form itself, this is not a case that can be solved with OOP, inheritance and overriding.
If MyButton was not designed in such a way that allows the end user to suppress its base functionality, then your options are limited in how you can use it. Here is an example of what it might look like if MyButton was designed to allow the end user to suppress its base click functionality:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MyButton1.SuppressDefaultClick = True
End Sub
Private Sub MyButton1_Click(sender As Object, e As EventArgs) Handles MyButton1.Click
MsgBox("Form Click Code")
End Sub
End Class
Public Class MyButton
Inherits Windows.Forms.Button
Private _suppress As Boolean = False
Public Property SuppressDefaultClick As Boolean
Get
Return _suppress
End Get
Set(value As Boolean)
_suppress = value
End Set
End Property
Protected Overridable Sub MyButton_Click(sender As Object, e As System.EventArgs) Handles Me.Click
If Not SuppressDefaultClick Then
MsgBox("Base Click")
End If
End Sub
End Class
If MyButton didn't include a way to suppress its built-in click handler like above then you'd have to resort to other means to solve your problem. In that case you'd have to prevent the button from ever receiving the message that the left mouse button has been clicked at all, and instead implement your own routine. This approach would be a considered a hack, since you are working around the limitations of something and not using it in the way it was originally intended. Here's one way the hack could be implemented:
Public Class Form1
Private WithEvents TMBC As TrapMyButtonClick
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TMBC = New TrapMyButtonClick(Me.MyButton1)
End Sub
Private Sub TMBC_Click(sender As MyButton) Handles TMBC.Click
MsgBox("Form Click Code")
End Sub
Private Class TrapMyButtonClick
Inherits NativeWindow
Private _mb As MyButton
Private Const WM_LBUTTONDOWN As Integer = &H201
Public Event Click(ByVal sender As MyButton)
Public Sub New(ByVal mb As MyButton)
If Not IsNothing(mb) AndAlso mb.IsHandleCreated Then
_mb = mb
Me.AssignHandle(mb.Handle)
End If
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
Case WM_LBUTTONDOWN
RaiseEvent Click(Me._mb) ' raise our custom even that the form has subscribed to
Exit Sub ' Suppress default behavior
End Select
MyBase.WndProc(m)
End Sub
End Class
End Class
Public Class MyButton
Inherits Windows.Forms.Button
Protected Overridable Sub MyButton_Click(sender As Object, e As System.EventArgs) Handles Me.Click
MsgBox("Base Click")
End Sub
End Class
You are getting 2 messages because you have set 2 different event handlers for the Click event:
The MyButton_Click method defined in your MyButton class.
The Button_Click method set in your AddHandler call on the form.
As noted in a comment above, you need to override the Button.OnClick method in your MyButton class instead of creating a new method:
Imports System.Windows.Forms
Imports System.Drawing
Public Class MyButton
Inherits Windows.Forms.Button
Sub New()
End Sub
' Override the OnClick event defined in "Button" class.
Protected Overrides Sub OnClick(e As System.EventArgs)
' Call the Click event from "Button" class.
MyBase.OnClick(e)
' Some custom events.
MsgBox("MyButton Click")
End Sub
End Class
It might be a good exercise to set breakpoints in the Button_Click and MyButton.OnClick methods so you can see exactly how the stack is created.

Can't Remove Listview Item From Second Form

I am having an issue when trying to delete ListView Items from a second form.
For example, if I use the following command on Form1 it works:
Listview1.SelectedItems(0).Remove
However, if I attempt to remove from Form2 like so:
Form1.Listview1.SelectedItems(0).Remove
I get the following error:
"Invalid argument=value of '0' is not valid for 'index'. Parameter name: index"
I then tried to get a count of items from the listview on Form2 and it gives me a return of 0
Form1.Listview1.Items.Count
I'm not sure what my problem is.
Update
I have posted a brief example of my code (using your suggestion as I can understand it):
frmShowMessages
Private Sub ViewMessage()
Dim frm As New frmViewMailMessage
frm.Show()
End Sub
Public Sub DeleteItem(ByVal index As Integer)
lsvReceivedMessages.Items(index).Remove()
End Sub
frmViewMessage
Private instanceForm as frmShowMessages
Private Sub frmViewMailMessage_Load(sender As Object, e As EventArgs) Handles MyBase.Load
instanceForm = New frmShowMessages()
End Sub
Private Sub cmdDelete_Click(sender As Object, e As EventArgs) Handles cmdDelete.Click
instanceForm.DeleteItem(_index)
End Sub
Hopefully my code can help identify where my issue is.
In VB.net usually you get a default Form instance for each of your Form. Probably you are creating an instance of Form1 and then you are trying to access ListView1 of default instance.
E.g.
Sub ButtonClick()
Dim f As New Form1()
f.Show()
' at this point if you access f's ListView you will get correct count
f.ListView1.Items.Count
' however if you try to access default instance it will NOT have any item
Form1.ListView.Items.Count
End Sub
It means your instance f is NOT equal to default Form1 instance.
Solution can be, make the f variable as class level variable and use it everywhere. Or if Form1 will have only 1 instance, then you can use the default instance everywhere.
Personally I would NOT go with direct control accessing over forms. I would create a Public method which should return the data as list to the caller, in this case your Form2.
UPDATED-2:
As per your given scenario, I am simplifying things for you, and doing implementation using Event.
Public Class frmShowMessages
Private Sub btnOpenMessage_Click(sender As System.Object, e As System.EventArgs) Handles btnOpenMessage.Click
Dim frmView As New frmViewMessage(Me.ListView1.SelectedItems(0).Index)
AddHandler frmView.MessageDeleted, AddressOf DeleteMessageHandler
frmView.Show()
End Sub
Private Sub DeleteMessageHandler(sender As Object, e As frmViewMessage.MessageDeletedEventArgs)
Me.ListView1.Items.RemoveAt(e.MessageIndex)
End Sub
End Class
Public Class frmViewMessage
' a class which will be used for Event communication
Public Class MessageDeletedEventArgs
Inherits EventArgs
Public Property MessageIndex As Integer
Public Sub New(ByVal iIndex As Integer)
MyBase.New()
Me.MessageIndex = iIndex
End Sub
End Class
' main event which will alert the parent that a message deletion should be done
Public Event MessageDeleted As EventHandler(Of MessageDeletedEventArgs)
' private variable that will hold the MessageIndex
Private Property MessageIndex As Integer
' method that is responsible to raise event
Protected Overridable Sub OnMessageDeleted()
RaiseEvent MessageDeleted(Me, New MessageDeletedEventArgs(Me.MessageIndex))
End Sub
' we want to create this Form using the MessageIndex of ListView
Public Sub New(ByVal iMessageIndex As Integer)
Me.InitializeComponent()
Me.MessageIndex = iMessageIndex
End Sub
' the delete button will raise the event to indicate parent that
' a deletion of message should be done
Private Sub btnDelete_Click(sender As System.Object, e As System.EventArgs) Handles btnDelete.Click
Me.OnMessageDeleted()
End Sub
End Class

Events in a VB.Net multi-project solution

Is it possible, to raise a global event in a multiproject solution in VB.Net. For example, project 1 has a form called Form1. On Form1 there is a button, that when clicked, raises an event, where project2 can handle that event, and even project3 could handle that event.
You can have a dedicated Project that has a Class whose sole purpose is to house a "Global Event". Make that Class implement the Singleton Pattern so that all the projects will access the same instance. All the other projects can Reference this Project and could look like this:
' This is in Project3
Public Class Class1
Private Sub New()
End Sub
Private Shared _Instance As Class1
Public Event GlobalEvent()
Public Shared ReadOnly Property Instance As Class1
Get
If IsNothing(_Instance) Then
_Instance = New Class1
End If
Return _Instance
End Get
End Property
Public Sub RingTheBell()
RaiseEvent GlobalEvent()
End Sub
End Class
Here is FormA in Project1, displaying FormB in Project2 (Project1 has a reference to both Project2 and Project3). We grab the singleton instance and call the RingTheBell() method to raise the "Global Event":
' This is in Project1
Public Class FormA
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim frmB As New Project2.FormB
frmB.Show()
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Project3.Class1.Instance.RingTheBell()
End Sub
End Class
Finally, over in Project2, we also grab the singleton instance and subscribe to its GlobalEvent (Project2 only has a reference to Project3):
' This is in Project2
Public Class FormB
Private WithEvents x As Project3.Class1 = Project3.Class1.Instance
Private Sub x_GlobalEvent() Handles x.GlobalEvent
MessageBox.Show("GlobalEvent() trapped in Project2")
End Sub
End Class
So any Project that wants to subscribe to the "Global Event" simply adds a Reference to Project3 and uses the Instance() method which returns the singleton instance to which that Project can subscribe to the event with.
This is possible via a number of possible routes. I'd prefer dependency injection in this case.
First, create your global event owner project. I named mine GlobalEventSample. I removed the default namespace and declared it here explicitly to make the code structure more obvious:
Namespace GlobalEventSample
Public Module Module1
Public Event GlobalEvent As EventHandler
Public Sub Main()
Console.WriteLine("Press any key to raise event...")
Console.ReadKey(True)
RaiseEvent GlobalEvent(Nothing, EventArgs.Empty)
Console.WriteLine("Press any key to quit...")
Console.ReadKey(True)
End Sub
End Module
End Namespace
Now create the consumer project. I named mine GlobalEventConsumer. I removed the default namespace and declared it here explicitly (just as above):
Namespace GlobalEventConsumer
Public Interface IGlobalEventOwner
Event GlobalEvent As EventHandler
End Interface
Public Class Class1
Public Sub New(ByVal globalEvent As IGlobalEventOwner)
AddHandler globalEvent.GlobalEvent, AddressOf GlobalEventHandler
End Sub
Public Shared Sub GlobalEventHandler(ByVal sender As Object, ByVal e As EventArgs)
Console.WriteLine("Event Handled!")
End Sub
End Class
End Namespace
Notice that I've declared an interface named "IGlobalEventOwner". All it does is define an object with an event. This event has a signature identical to the global event we want to handle.
Go back to the sample project and create a reference to the consumer project.
The consumer project requires an object which implements IGlobalEventOwner. Modules cannot implement interfaces, so we instead create a private class, GlobalEventRouter, which will simply handle the module's event and then fire its own event. Finally, we will create a new instance of Class 1 in the Main sub and pass an instance of the GlobalEventRouter class.
Namespace GlobalEventSample
Public Module Module1
Public Event GlobalEvent As EventHandler
Public Sub Main()
Dim consumer As New GlobalEventConsumer.Class1(New GlobalEventRouter())
Console.WriteLine("Press any key to raise event...")
Console.ReadKey(True)
RaiseEvent GlobalEvent(Nothing, EventArgs.Empty)
Console.WriteLine("Press any key to quit...")
Console.ReadKey(True)
End Sub
Private Class GlobalEventRouter
Implements GlobalEventConsumer.IGlobalEventOwner
Public Event GlobalEvent(ByVal sender As Object, ByVal e As System.EventArgs) Implements GlobalEventConsumer.IGlobalEventOwner.GlobalEvent
Public Sub New()
AddHandler Module1.GlobalEvent, AddressOf GlobalEventHandler
End Sub
Private Sub GlobalEventHandler(ByVal sender As Object, ByVal e As EventArgs)
RaiseEvent GlobalEvent(sender, e)
End Sub
End Class
End Module
End Namespace
The output:
Press any key to raise event...
Event Handled!
Press any key to quit...