如何避免空白区域树视图节点点击?

时间:2017-01-11 10:08:03

标签: c# .net winforms outlook-addin

我正在使用常规的WinForm Outlook Addin并且我使用DrawNode事件创建了一个Treeview,树正在按预期工作但是节点点击有一个小故障,只有绿色区域可以点击而半个节点没有响应。 enter image description here

当我使用MouseDown事件时,整个区域都可以点击,包括节点旁边的空白区域。

但是要限制这个空白点击我在TreeViewHitTestLocations的帮助下使用逻辑我正在检查点击的位置是否为RightOfLabel然后不做任何事情,但不幸的是这不会给我一个精确的结果,它会以某种方式混淆并将标签的一半(节点)作为空格并且不会被点击。

注意:我认为这一切都发生了,因为我使用了DrawNode方法并且在保持标签和工作区图标之间的距离时,下面的应用程序假定标签在绿色部分内完成,因此红色部分留作空白区域。这只是我基于我对该方法所做的所有天真事情的假设。

如果有人可以指导我修复此问题,需要帮助来解决此问题。感谢

 void treeview_mousedown(object sender, MouseEventArgs e)
    {

        TreeNode nodeClicked;

        // if arrow up/down will be excluded from the mousedown event

        var hitTest = this.HitTest(e.Location);
        if (hitTest.Location == TreeViewHitTestLocations.PlusMinus)
            return;

        if (hitTest.Location == TreeViewHitTestLocations.RightOfLabel)
            return;

        // Get the node clicked on
        nodeClicked = this.GetNodeAt(e.X, e.Y);

        // Was the node clicked on?
        if (!(nodeClicked == null))
            this.SelectedNode = nodeClicked;       

    }

下面是我正在使用的treeview drawode方法:

void treeview_DrawNode(object sender, DrawTreeNodeEventArgs e)
    {
        Rectangle nodeRect = e.Node.Bounds;

        // below location is the expand and collapse icon location
        Point ptExpand = new Point(nodeRect.Location.X - 7, nodeRect.Location.Y + 5);

        Image expandImg = null;

        // check the below condition for nodes with child nodes and nodes without child nodes
        if ( e.Node.Nodes.Count < 1)
            expandImg = global::myresource.OfficeAddin.Controls.Resource.search;
        else if (e.Node.IsExpanded && e.Node.Nodes.Count > 1)
            expandImg = global::myresource.OfficeAddin.Controls.Resource.down_arrow_icon;
        else 
            expandImg = global::myresource.OfficeAddin.Controls.Resource.right_arrow_icon;

        Graphics g = Graphics.FromImage(expandImg);
        IntPtr imgPtr = g.GetHdc();
        g.ReleaseHdc();
        e.Graphics.DrawImage(expandImg, ptExpand);

        // draw node icon
        Point ptNodeIcon = new Point(nodeRect.Location.X - 4, nodeRect.Location.Y + 2);
        Image nodeImg = global::myresource.OfficeAddin.Controls.Resource.folder_icon_16px;
        g = Graphics.FromImage(nodeImg);
        imgPtr = g.GetHdc();
        g.ReleaseHdc();
        e.Graphics.DrawImage(nodeImg, ptNodeIcon);


        // draw node text
        Font nodeFont = e.Node.NodeFont;

        if (e.Node.NodeFont != null)
        {
            nodeFont = e.Node.NodeFont;
        } else {
            nodeFont = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        }

        // set the forecolor
        Color forecolor = e.Node.ForeColor;

        // color same as the font color
        string strSelectedColor = @"#505050";
        Color selectedColor = System.Drawing.ColorTranslator.FromHtml(strSelectedColor);
        SolidBrush selectedTreeBrush = new SolidBrush(selectedColor);


        //Inflate to not be cut
        Rectangle textRect = nodeRect;

        //below value controls the width of the text if given less then, long texts will come in multiple lines
        textRect.Width += 150;

        // below value controls the over all width of the node, if given less all the things will get sqeeze
        e.Graphics.DrawString(e.Node.Text, nodeFont, selectedTreeBrush , Rectangle.Inflate(textRect, -20, 0));

    }

1 个答案:

答案 0 :(得分:0)

您的假设是正确的,您可以通过在绘图上标记边界来检查它,例如:

TreeNodeStates state = e.State;
bool isFocused = (state & TreeNodeStates.Focused) == TreeNodeStates.Focused;
if (isFocused)
    ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, foreColor, backColor);

您的代码存在更多问题:

问题1:图片

如果您使用节点图标,请使用TreeView.ImageListTreeNode.ImageKey属性。否则,在绘图时不会为图像分配空间。在这种情况下,您可以使用TreeViewDrawMode.OwnerDrawText DrawMode

问题2:字体

请勿使用除节点或树的字体之外的其他字体,因为它可能具有意外的大小。如果此 SegoeUI 字体是默认字体,请在TreeView实例中使用它。然后,您可以获得所需的字体:

Font font = e.Node.NodeFont ?? e.Node.TreeView.Font;

问题3:文字

您使用Graphics.DrawString来绘制使用GDI +的文本。但是,从.NET 2.0开始,默认文本呈现方法是GDI,除非控件的CompatibleTextRendering属性为true。它们会产生略微不同的文字大小。

要使用GDI,计算标签的大小,请改用TextRenderer类:

TextRenderer.DrawText(e.Graphics, e.Node.Text, font, e.Bounds, foreColor, TextFormatFlags.GlyphOverhangPadding | TextFormatFlags.SingleLine | TextFormatFlags.EndEllipsis | TextFormatFlags.NoPrefix);