问题描述
如何处理列出的任何树视图通知 这里 在从 .NET TreeView 控件派生的 C# 类中?
How can I handle any of the tree view notifications listed here in a C# class that is derived from the .NET TreeView control?
我尝试处理点击通知,例如,像这样:
I tried to handle the click notification, for example, like this:
class ExtendedTreeView : TreeView
{
private const Int32 NM_FIRST = (Int32)(0U - 0U);
private const Int32 NM_CLICK = unchecked((Int32)((UInt32)NM_FIRST - 2U));
protected override void WndProc(ref Message m)
{
if (m.Msg == NM_CLICK)
{
MessageBox.Show("NM_CLICK");
}
base.WndProc(ref m);
}
}
但消息框从未显示.这是我第一次尝试使用 Win32 API 来修改 .NET 控件的行为,所以我不知道出了什么问题.
But the message box is never shown. This is the first time I try to use Win32 API to modify the behaviour of a .NET control, so I have no idea what goes wrong.
这是处理这些通知的正确方法吗?
Is this the correct approach to handle these notifications?
仅供参考:我知道 .NET TreeView 控件有一个单击事件.这只是第一次测试.稍后我想启用 TVS_EX_MULTISELECT
样式.由于启用 TVS_EX_MULTISELECT
时 .NET TreeView 控件不会触发任何 AfterSelect
事件,我想调查 TVN_SELCHANGED
和 的行为>TVN_ITEMCHANGED
稍后通知.
FYI: I know that the .NET TreeView control has a click event. This is just a first test. Later I want to enable the TVS_EX_MULTISELECT
style. Since the .NET TreeView control does not fire any AfterSelect
events when TVS_EX_MULTISELECT
is enabled, I want to investigate the behaviour of the TVN_SELCHANGED
and TVN_ITEMCHANGED
notifications later.
推荐答案
没那么简单.查看 MSDN 文章,NM_CLICK 通知作为 WM_NOTIFY 消息传递.它被发送到树视图的父.Winforms 有管道将其回显到原始控件,以允许消息由派生自 TreeView 的类处理并自定义事件处理.这是通过在消息中添加 0x2000 来完成的,即 Winforms 源代码中 WM_REFLECT 的值.
It is not that simple. Check the MSDN article, the NM_CLICK notification is delivered as a WM_NOTIFY message. And it is sent to the parent of the treeview. Winforms has plumbing in place to echo it back to the original control to allow the message to be handled by a class derived from TreeView and customize the event handling. That's done by adding 0x2000 to the message, the value of WM_REFLECT in the Winforms source code.
所以代码应该是这样的:
So the code should look like this:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class ExtendedTreeView : TreeView {
protected override void WndProc(ref Message m) {
if (m.Msg == WM_REFLECT + WM_NOFITY) {
var notify = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
if (notify.code == NM_CLICK) {
MessageBox.Show("yada");
m.Result = (IntPtr)1;
return;
}
}
base.WndProc(ref m);
}
private const int NM_FIRST = 0;
private const int NM_CLICK = NM_FIRST - 2;
private const int WM_REFLECT = 0x2000;
private const int WM_NOFITY = 0x004e;
[StructLayout(LayoutKind.Sequential)]
private struct NMHDR {
public IntPtr hwndFrom;
public IntPtr idFrom;
public int code;
}
}
请注意,TreeView 已经完成了所有这些操作,这就是 NodeMouseClick、Click 和 MouseClick 事件的生成方式.执行此操作的代码也适用于本机控件中的一些怪癖,因此请确保在提交使用它之前确实需要它.如果您想知道发生了什么,请查看参考源.
Beware that TreeView already does all this, that's how the NodeMouseClick, Click and MouseClick events get generated. The code that does this also works around some quirks in the native control so be sure you really need this before committing to use it. Review the Reference Source if you want to know what's going on.
这篇关于在派生的 C# 用户控件中处理 Windows 通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!