// Study the real principle of click events of controls
// A control is defined here. After compilation, place the control on the form and find the MyClick event. You can test it by adding some code.
Using System;
Using System. Collections. Generic;
Using System. Text;
Using System. ComponentModel;
Using System. Windows. Forms;
Namespace ConsoleApplication1
{
Class MyButton: Control
{
Const int WM_LBUTTONUP = 0x202;
# Region "CIDR Block description"
EventHandlerList _ myEvents;
Object _ eventClick = new object ();
# Endregion
# Region "attributes and definitions"
Public EventHandlerList MyEvents
{
Get
{
If (this. _ myEvents = null)
{
This. _ myEvents = new EventHandlerList ();
}
Return this. _ myEvents;
}
}
# Endregion
# Region "case definition"
Public event EventHandler MyClick
{
Add
{
Events. AddHandler (_ eventClick, value );
}
Remove
{
Events. RemoveHandler (_ eventClick, value );
}
// AsyncCallback
// Activator
}
# Endregion
# Region "Private method"
Private void MyOnClick (EventArgs e)
{
EventHandler handler = (EventHandler) base. Events [_ eventClick];
If (handler! = Null)
{
Handler (this, e );
}
}
Private void WmMouseUp (ref Message m, System. Windows. Forms. MouseButtons button, int clicks)
{
// Verify the status and process incoming messages as event parameters
//...
MouseEventArgs args = new MouseEventArgs (button, clicks, SignedLOWORD (m. LParam), SignedHIWORD (m. LParam), 0 );
This. MyOnClick (args );
}
Private int SignedLOWORD (IntPtr n)
{
Return (short) (int) (long) n) & 0 xffff );
}
Private int SignedHIWORD (IntPtr n)
{
Return (short) (int) (long) n)> 0x10) & 0 xffff );
}
# Endregion
# Region "common method"
Protected override void WndProc (ref Message m)
{
Base. WndProc (ref m );
Switch (m. Msg)
{
Case WM_LBUTTONUP:
This. WmMouseUp (ref m, System. Windows. Forms. MouseButtons. Left, 1 );
Break;
}
}
# Endregion
}
// The actual processing of MyButton. MyClick is as follows:
// First, a MyClick method variable is published externally. The add and remove operations are supported for this variable.
// When the Add operation (that is, when the operation is performed from outside + =), the incoming value is written into a list named event list.
// In the message processing process WndProc in MyButton, when the WM_LBUTTONUP message is intercepted, the WmMouseUp method is called for processing.
// Call the MyOnClick method in the WmMouseUp object.
// In the MyOnClick object, obtain the Method Instance handler from the event list and call the method.
// The working principle of MyButton. MyClick is different from that described in Example 4.
// 1. The method variable MyClick is not directly used to store external method instances, but is stored in a field _ myEvents as an attribute.
// 2. In the message processing process, WndProc does not call MyClick, but calls the Method Field in MyOnClick.
// In essence, WndProc still processes MyClick, but the implementation idea is quite different.
// It seems that one link is missing, and MyClick has not been instantiated internally. MyOnClick checks whether the method field is null.
// This indicates that the method variable does not need to be passed into the instance internally, as long as the internal call is performed without null judgment.
// The above research treats method variables as common variables.
// Combine delegate with message loop. This is the event we see.
// The effect of the event is that an object publishes its own method to others, and others can further improve this method.
// This goes back to the first example: leaders entrust their subordinates to do something!
// In the initial example, the delegate used an error and defined a variable for the subordinate method to call.
// Define a method variable in the lead object, which is implemented by the subordinates.
// The first example of reconstruction in the next example.
}