设置树节点高度后,树视图滚动不正确

时间:2015-07-14 03:03:33

标签: c# winforms

    public Form2()
    {
        InitializeComponent();
    }

    private void Form2_Load(object sender, EventArgs e)
    {
        Dictionary<int, TreeNode> map = new Dictionary<int, TreeNode>();
        for (int i = 0; i < 100; i++)
        {
            TreeNode node = new TreeNode(i.ToString());
            if (i % 10 == 0)
                _tree.Nodes.Add(node);
            map.Add(i, node);
            if (i % 10 != 0)
            {
                map[Convert.ToInt32(Math.Floor(i / 10.0)) * 10].Nodes.Add(node);
                node.SetNodeHeight(2);
            }
        }
    }
}

public static class TreeViewExtendMethod
{
    [StructLayout(LayoutKind.Sequential)]
    struct TVITEMEX
    {
        public Mask mask;
        public IntPtr item;
        public uint state;
        public uint stateMask;
        public IntPtr pszText;
        public int cchTextMax;
        public int iImage;
        public int iSelectedImage;
        public int iChildren;
        public IntPtr lParam;
        public int iIntegral;

        // ... plus some windows 6+ crap
    }

    [Flags]
    enum Mask : uint
    {
        Text = 1,
        Image = 2,
        Param = 4,
        State = 8,
        Handle = 16,
        SelectedImage = 32,
        Children = 64,
        Integral = 128,
    }
    public static int GetNodeHeight(this TreeNode tn)
    {
        TVITEMEX tvix = new TVITEMEX();
        tvix.mask = Mask.Handle | Mask.Integral;
        tvix.item = tn.Handle;
        tvix.iIntegral = 0;
        IntPtr hParam=Marshal.AllocHGlobal(Marshal.SizeOf(tvix));
        Marshal.StructureToPtr(tvix, hParam, false);
        win32.SendMessage(tn.TreeView.Handle, win32.TVM_GETITEM, IntPtr.Zero, hParam);
        return tvix.iIntegral;
    }

    public static void SetNodeHeight(this TreeNode tn, int height)
    {
        TVITEMEX tvix = new TVITEMEX();
        tvix.mask = Mask.Handle | Mask.Integral;
        tvix.item = tn.Handle;
        tvix.iIntegral = height;
        IntPtr hParam=Marshal.AllocHGlobal(Marshal.SizeOf(tvix));
        Marshal.StructureToPtr(tvix, hParam, false);
        win32.SendMessage(tn.TreeView.Handle, win32.TVM_SETITEM, IntPtr.Zero, hParam);
    }
}

以上是示例代码,在使用PINV手动更改节点高度后,单击滚动条底部时,树形视图将滚动,因为只需单击一下就不会滚动。

首先,我认为它可能是由滚动条引起的,在我将滚动消息段(8)设置为结束滚动后,它没有按预期工作。最后,在捕获滚动消息(0x115)时,退出WndProc,然后它可以工作。我不知道发生了什么,因为我无法找到任何msg可以取消滚动,除了将wParam设置为8肯定不起作用。 enter image description here

1 个答案:

答案 0 :(得分:0)

我终于找到了一个解决方案,虽然并不优雅,但它应该有效。 这是解决方案,

        protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x115)
        {
            if (((int)m.WParam & 5) == (5) ||
                ((int)m.WParam & 4) == (4)
                )
            {
                int para = (int)m.WParam;
                int temp = (para - (para % 2 == 0 ? 4 : 5)) >> 16;

                // store the current position, if the position doesn't change, no need to handle
                if (temp == pos)
                    return;
                else
                    pos = temp;
            }
            if (((int)m.WParam & 8) == 8)
                return;

            //Debug.WriteLine(m.WParam);
            //if (DisableScroll)
            //    return;
            //    //m.WParam = (IntPtr)8;
            //SCROLLINFO si = new SCROLLINFO();
            //si.cbSize = Marshal.SizeOf(si);
            //si.fMask = (int)(ScrollInfoMask.SIF_POS | ScrollInfoMask.SIF_PAGE | ScrollInfoMask.SIF_RANGE | ScrollInfoMask.SIF_TRACKPOS);
            //GetScrollInfo(this.Handle, 1, ref si);
            ////Debug.WriteLine(string.Format("Max pos:{0}, Min pos: {1}", si.nMin, si.nMax));
            //Debug.WriteLine(string.Format("wParam:{0} hParam:{1}", m.WParam, m.LParam));
            //Debug.WriteLine(string.Format("It page size: {0}, position: {1}, range: {2}, track pos: {3}", si.nPage, si.nPos, si.nPage, si.nTrackPos));
            //if (si.nPage + Math.Max(si.nPos, si.nTrackPos) >= si.nMax)
            //{
            //    return;
            //}
        }
        base.WndProc(ref m);
    }