Handling windows notifications in derived C# user control

前端 未结 3 423
梦谈多话
梦谈多话 2021-01-27 04:07

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, f

3条回答
  •  说谎
    说谎 (楼主)
    2021-01-27 05:08

    There are 2 important things, which are mentioned in MSDN: 1) msg.lparam is pointer to NMHDR structure 2) notifications are send to parent control

    So the working code is (compile as console app - it will print messages there):

    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    class MyTreeView : TreeView
    {
        public TreeView RealTreeView;
        public MyTreeView()
        {
            RealTreeView = new TreeView();
            RealTreeView.Dock = DockStyle.Fill;
            Controls.Add(RealTreeView);
        }
        enum WM
        {
            NOTIFY = 78
        }
        enum NM : uint
        {
            FIRST = 0,
            NM_CLICK = unchecked(FIRST - 2),
            NM_CUSTOMDRAW = unchecked(FIRST - 12),
            NM_DBLCLK = unchecked(FIRST - 3),
            NM_KILLFOCUS = unchecked(FIRST - 8),
            NM_RCLICK = unchecked(FIRST - 5),
            NM_RDBLCLK = unchecked(FIRST - 6),
            NM_RETURN = unchecked(FIRST - 4),
            NM_SETCURSOR = unchecked(FIRST - 17),
            NM_SETFOCUS = unchecked(FIRST - 7)
        }
    
        [StructLayout(LayoutKind.Sequential)]
        struct NMHDR {
            public IntPtr hwndFrom;
            public UIntPtr idFrom;
            public uint code;
        }
    
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == (int)WM.NOTIFY)
            {
                uint code;
                unsafe
                {
                    var nmhdr = (NMHDR*)m.LParam.ToPointer();
                    code = nmhdr->code;
                }
                NM nmCode = (NM)code;
                Console.WriteLine("WM_NOTIFY " + nmCode);
            }
        }
    }
    
    public class MyGuiClass
    {
        public static void Main()
        {
            Form f = new Form();
            var tv = new MyTreeView();
            tv.RealTreeView.Nodes.Add("zero").Nodes.Add("sub-zero");
            tv.RealTreeView.Nodes.Add("one");
            tv.RealTreeView.Nodes.Add("two");
            tv.RealTreeView.Nodes.Add("three");
            tv.Dock = DockStyle.Fill;
            f.Controls.Add(tv);
            Application.Run(f);
        }
    }
    

    Edit: and don't forget to compile with /unsafe of course.

提交回复
热议问题