在我所见到的关于C#/ .NET的所有书籍中,当他们谈论事件时, 他们谈论创建和消费事件。
我很想知道我们的代码背后是如何工作的 - 运行它的机制是什么。
我对Windows消息循环对于引发的事件的队列行为有所了解。
例如,WM_KEYDOWN
或WM_LBUTTONDOWN
等等。
但是会发生什么,例如,如果我创建了一个不继承class Control
的类,并且这个类引发了一个事件?
(另一个类,也没有继承class Control
,接收它)
引发的事件会通过消息循环吗?
听起来不那么逻辑。
(但假设该项目是一个Windows窗体项目,只有两个类 - 发送者和接收者根本不是GUI类,而是你写的简单类)
对我们代码背后机制的文章的任何解释或链接都将受到高度赞赏。
答案 0 :(得分:4)
我希望我能正确理解你的问题。我想我们正在谈论两件事。
首先 - C#中的事件如何工作 第二 - 用C#编写的WinForms应用程序如何知道你何时点击了一个按钮。
C#中的事件是他们自己独特的事情。你可以编写一个控制台应用程序,创建自己的事件,听取它,激活它,响应它等等......这一切都可行。您通过调用Add()订阅事件,并通过调用Remove()取消订阅。事件本身会跟踪哪些方法正在监听它以及何时引发它,调用所有这些方法。
Jon Skeet解释得更好: How do C# Events work behind the scenes?
但这些事件只是C#代码。与您提到的Win32消息相关但不同。在Winforms应用程序中,当用户单击按钮时,应用程序如何知道它?我们可以使用调试器(关闭“我的代码”https://msdn.microsoft.com/en-us/library/dn457346.aspx选项)并在点击事件中设置断点,您将能够看到正在发生的事情。
所以在Windows.Forms.Controls.ControlNativeWindow中有一个WndProc方法,它接受一个System.Windows.Forms.Message m。
之前是'debuggableCallback'方法。这反映了您对Win32API应用程序的期望。
/// <include file='doc\NativeWindow.uex' path='docs/doc[@for="NativeWindow.DebuggableCallback"]/*' />
/// <devdoc>
/// Window message callback method. Control arrives here when a window
/// message is sent to this Window. This method packages the window message
/// in a Message object and invokes the wndProc() method. A WM_NCDESTROY
/// message automatically causes the releaseHandle() method to be called.
/// </devdoc>
/// <internalonly/>
private IntPtr DebuggableCallback(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) {
// Note: if you change this code be sure to change the
// corresponding code in Callback above!
Message m = Message.Create(hWnd, msg, wparam, lparam);
try {
if (weakThisPtr.IsAlive && weakThisPtr.Target != null) {
WndProc(ref m);
}
else {
DefWndProc(ref m);
}
}
finally {
if (msg == NativeMethods.WM_NCDESTROY) ReleaseHandle(false);
if (msg == NativeMethods.WM_UIUNSUBCLASS) ReleaseHandle(true);
}
return m.Result;
}
因此,最终,如果您在Windows上运行,它会受到您期望的相同Win32 API消息的驱动。只是编写System.Windows.Forms类来封装大部分类。