自动缩放字体的文本框控件,使其尽可能地大,仍然适合于文本区域边界使其、缩放、适合于、边界

2023-09-03 00:16:52 作者:靠边站 别挡信号

我需要一个文本框或某些类型的多行Label控件,将自动调节字体大小,使其尽可能大,但有文本区域的边界内整个消息的选择。

I need a TextBox or some type of Multi-Line Label control which will automatically adjust the font-size to make it as large as possible and yet have the entire message fit inside the bounds of the text area.

我想看看是否有人开发自己之前已经实施了这样的用户控件。

I wanted to see if anyone had implemented a user control like this before developing my own.

应用举例:有一个文本框,这将是一半面积的Windows窗体上。发来的邮件中,是将大约100-500字它将把所有的文字在​​控制和设置字体尽可能大。它采用单声道的实现支持.NET库将是一个加号。

Example application: have a TextBox which will be half of the area on a windows form. When a message comes in which is will be approximately 100-500 characters it will put all the text in the control and set the font as large as possible. An implementation which uses Mono Supported .NET libraries would be a plus.

如果知道有一个已经实现的控制......如果有人知道如何测试一个给定的文本完全适合文本区域,这将是,如果我推出自己控制有用的内部。

If know one has implemented a control already... If someone knows how to test if a given text completely fits inside the text area that would be useful for if I roll my own control.

编辑:我最后写一个扩展RichTextBox的。我会后我的code不久,有一次,我已经验证所有的扭结制定。

I ended up writing an extension to RichTextBox. I will post my code shortly once i've verified that all the kinks are worked out.

推荐答案

我想出了解决的办法是写它扩展了标准的RichTextBox控制的控制。

The solution i came up with was to write a control which extends the standard RichTextBox control.

使用扩展控制以同样的方式将一个普通RichTextBox控件具有以下增强功能:

Use the extended control in the same way you would a regular RichTextBox control with the following enhancements:

调整或文字更改后调用ScaleFontToFit()方法。 水平对齐字段可用于居中对齐文本。 的字体属性在设计集将被用于整个区域。它是不能混合的字体,因为它们会改变,一旦ScaleFontToFit方法被调用。

本控制结合了多种技术来确定,如果文本还是它的范围内适合。如果文本区域是多行,它会检测是否滚动条是可见的。我发现了一个巧妙的方法来检测滚动条是否是可见的,而无需使用一个聪明的技术,我发现上的帕特里克Smacchia帖子。。当多行是不正确的,垂直滚动条不会出现,所以你需要使用不同的技术,它依赖于使用的图形对象呈现的文本。该图形渲染技术不适合用于多箱,因为你将不得不考虑自动换行。

This control combines several techniques to determine if the text still fits within it's bounds. If the text area is multiline, it detects if scrollbars are visible. I found a clever way to detect whether or not the scrollbars are visible without requiring any winapi calls using a clever technique I found on one of Patrick Smacchia's posts.. When multiline isn't true, vertical scrollbars never appear so you need to use a different technique which relies on rendering the text using a the Graphics object. The Graphic rendering technique isn't suitable for Multiline boxes because you would have to account for word wrapping.

下面是几个片段,显示它是如何工作(链接到源$ C ​​$ C下面提供)。这code很容易被用于扩展其他控件。

Here are a few snippets which shows how it works (link to source code is provided below). This code could easily be used to extend other controls.

    /// <summary>
    /// Sets the font size so the text is as large as possible while still fitting in the text
    /// area with out any scrollbars.
    /// </summary>
    public void ScaleFontToFit()
    {
        int fontSize = 10;
        const int incrementDelta = 5; // amount to increase font by each loop iter.
        const int decrementDelta = 1; // amount to decrease to fine tune.

        this.SuspendLayout();

        // First we set the font size to the minimum.  We assume at the minimum size no scrollbars will be visible.
        SetFontSize(MinimumFontSize);

        // Next, we increment font size until it doesn't fit (or max font size is reached).
        for (fontSize = MinFontSize; fontSize < MaxFontSize; fontSize += incrementDelta)
        {
            SetFontSize(fontSize);

            if (!DoesTextFit())
            {
                //Console.WriteLine("Text Doesn't fit at fontsize = " + fontSize);
                break;
            }
        }

        // Finally, we keep decreasing the font size until it fits again.
        for (; fontSize > MinFontSize && !DoesTextFit(); fontSize -= decrementDelta)
        {
            SetFontSize(fontSize);
        }

        this.ResumeLayout();
    }

    #region Private Methods
    private bool VScrollVisible
    {
        get
        {
            Rectangle clientRectangle = this.ClientRectangle;
            Size size = this.Size;
            return (size.Width - clientRectangle.Width) >= SystemInformation.VerticalScrollBarWidth;
        }
    }

    /**
     * returns true when the Text no longer fits in the bounds of this control without scrollbars.
    */
    private bool DoesTextFit()
    {
            if (VScrollVisible)
            {
                //Console.WriteLine("#1 Vscroll is visible");
                return false;
            }

            // Special logic to handle the single line case... When multiline is false, we cannot rely on scrollbars so alternate methods.
            if (this.Multiline == false)
            {
                Graphics graphics = this.CreateGraphics();
                Size stringSize = graphics.MeasureString(this.Text, this.SelectionFont).ToSize();

                //Console.WriteLine("String Width/Height: " + stringSize.Width + " " + stringSize.Height + "form... " + this.Width + " " + this.Height);

                if (stringSize.Width > this.Width)
                {
                    //Console.WriteLine("#2 Text Width is too big");
                    return false;
                }

                if (stringSize.Height > this.Height)
                {
                    //Console.WriteLine("#3 Text Height is too big");
                    return false;
                }

                if (this.Lines.Length > 1)
                {
                    //Console.WriteLine("#4 " + this.Lines[0] + " (2): " + this.Lines[1]); // I believe this condition could be removed.
                    return false;
                }
            }

            return true;
    }

    private void SetFontSize(int pFontSize)
    {
        SetFontSize((float)pFontSize);
    }

    private void SetFontSize(float pFontSize)
    {
        this.SelectAll();
        this.SelectionFont = new Font(this.SelectionFont.FontFamily, pFontSize, this.SelectionFont.Style);
        this.SelectionAlignment = HorizontalAlignment;
        this.Select(0, 0);
    }
    #endregion

ScaleFontToFit可以进行优化,以提高性能,但我一直是简单,所以它会很容易理解。

ScaleFontToFit could be optimized to improve performance but I kept it simple so it'd be easy to understand.

点击这里下载最新的源$ C ​​$ C。我还在积极努力,我开发的这种控制的项目,所以很可能我会在不久的将来加入一些其他的功能和增强功能。因此,检查网站的最新code。

Download the latest source code here. I am still actively working on the project which I developed this control for so it's likely i'll be adding a few other features and enhancements in the near future. So, check the site for the latest code.

我的目标是让使用单框架在Mac上这个控制工作。

My goal is to make this control work on Mac using the Mono framework.

 
精彩推荐
图片推荐