Найти высоту текста на панели - PullRequest
1 голос
/ 11 июня 2010

У меня есть панель, которую я настроил. Я использую его для отображения текста. Но иногда этот текст слишком длинный и переносится на следующую строку. Есть ли какой-нибудь способ автоматического изменения размера панели для отображения всего текста?

Я использую C # и Visual Studio 2008 и компактный каркас.


Вот код, для которого я хочу настроить размер:
(Примечание: HintBox - это мой собственный класс, который наследуется от панели. Поэтому я могу изменить его при необходимости. )

public void DataItemClicked(ShipmentData shipmentData)
{
    // Setup the HintBox
    if (_dataItemHintBox == null)
        _dataItemHintBox = HintBox.GetHintBox(ShipmentForm.AsAnObjectThatCanOwn(),
                                             _dataShipSelectedPoint,
                                             new Size(135, 50), shipmentData.LongDesc,
                                             Color.LightSteelBlue);


    _dataItemHintBox.Location = new Point(_dataShipSelectedPoint.X - 100,
                                          _dataShipSelectedPoint.Y - 50);
    _dataItemHintBox.MessageText = shipmentData.LongDesc;
    // It would be nice to set the size right here
    _dataItemHintBox.Size = _dataItemHintBox.MethodToResizeTheHeightToShowTheWholeString()
    _dataItemHintBox.Show();

}

Я собираюсь дать ответ Уиллу Маркуиллеру, потому что его пример кода был ближе всего к тому, что мне было нужно (и, похоже, он будет работать). Тем не менее, вот что я буду использовать:

public static class CFMeasureString
{
    private struct Rect
    {
        public readonly int Left, Top, Right, Bottom;
        public Rect(Rectangle r)
        {
            this.Left = r.Left;
            this.Top = r.Top;
            this.Bottom = r.Bottom;
            this.Right = r.Right;
        }
    }

    [DllImport("coredll.dll")]
    static extern int DrawText(IntPtr hdc, string lpStr, int nCount, 
                               ref Rect lpRect, int wFormat);
    private const int DT_CALCRECT = 0x00000400;
    private const int DT_WORDBREAK = 0x00000010;
    private const int DT_EDITCONTROL = 0x00002000;

    static public Size MeasureString(this Graphics gr, string text, Rectangle rect, 
                                     bool textboxControl)
    {
        Rect bounds = new Rect(rect);
        IntPtr hdc = gr.GetHdc();
        int flags = DT_CALCRECT | DT_WORDBREAK;
        if (textboxControl) flags |= DT_EDITCONTROL;
        DrawText(hdc, text, text.Length, ref bounds, flags);
        gr.ReleaseHdc(hdc);
        return new Size(bounds.Right - bounds.Left, bounds.Bottom - bounds.Top + 
                        (textboxControl ? 6 : 0));
    }
}

Используется вызов уровня os для рисования текста. С помощью P-Invoking я могу получить необходимую мне функциональность (многострочный перенос). Обратите внимание, что этот метод не включает в себя поля. Просто фактическое пространство, занимаемое текстом.

Я не писал этот код. Я получил это от http://www.mobilepractices.com/2007/12/multi-line-graphicsmeasurestring.html. В этом посте была моя точная проблема и это исправление. (Хотя я сделал небольшую настройку, чтобы сделать это методом расширения.)

Ответы [ 2 ]

4 голосов
/ 11 июня 2010

Вы можете использовать метод Graphics.MeasureString().

С примером кода вашего текстового назначения на вашей панели я, возможно, смогу предоставить пример кода с использованием метода MeasureString(),если вам это нужно.

У меня нет возможности узнать, является ли метод Graphics.MeasureString() частью Компактной платформы, как это не сказано на странице, на которую я ссылался.РЕДАКТИРОВАТЬ # 1

Вот ссылка , где я ответил на другой вопрос, связанный с размером текста, в то время как я ищу для вас пример.=)

EDIT # 2

Вот еще одна ссылка, связанная с вашим вопросом.(Следующее редактирование - пример кода. = P)

РЕДАКТИРОВАТЬ # 3

public void DataItemClicked(ShipmentData shipmentData) { 
    // Setup the HintBox 
    if (_dataItemHintBox == null) 
        _dataItemHintBox = HintBox.GetHintBox(ShipmentForm.AsAnObjectThatCanOwn(), 
                                             _dataShipSelectedPoint, 
                                             new Size(135, 50), shipmentData.LongDesc, 
                                             Color.LightSteelBlue); 

    // Beginning to measure the size of the string shipmentData.LongDesc here.

    // Assuming that the initial font size should be 30pt.
    Single fontSize = 30.0F;
    Font f = new Font("fontFamily", fontSize, FontStyle.Regular);

    // The Panel.CreateGraphics method provides the instance of Graphics object 
    // that shall be used to compare the string size against.
    using (Graphics g = _dataItemHintBox.CreateGraphics()) {
        while (g.MeasureString(shipmentData.LongDesc, f).Width > _dataItemHintBox.Size.Width - 5) {
            --fontSize;
            f = new Font("fontFamily", fontSize, FontStyle.Regular);
        }
    }

    // Font property inherited from Panel control.
    _dataItemHintBox.Font = f;

    // End of font resizing to fit the HintBox panel.

    _dataItemHintBox.Location = new Point(_dataShipSelectedPoint.X - 100, 
                                          _dataShipSelectedPoint.Y - 50); 
    _dataItemHintBox.MessageText = shipmentData.LongDesc; 
    // It would be nice to set the size right here 
    _dataItemHintBox.Size = _dataItemHintBox.MethodToResizeTheHeightToShowTheWholeString() 
    _dataItemHintBox.Show(); 
} 

Отказ от ответственности: Этот код не имеетбыл проверен и находится на вершине моей головы.Некоторые изменения могут быть обязательными для того, чтобы вы могли проверить это.Это обеспечивает руководство для достижения того, чего вы, кажется, хотите достичь.Возможно, есть лучший способ сделать это, но я знаю, что этот работает.Ну, алгоритм работает, как вы можете видеть в других моих ответах.

Вместо строки:

SizeF fontSize = 30.0F;

Вы также можете сделать следующее:

var fontSize = _dataItemHintBox.Font.Size;

Почему это так?

Поскольку Font.Size свойство только для чтения .Итак, вам нужно создавать новый экземпляр класса System.Drawing.Font каждый раз, когда Font.Size будет меняться.

В вашем сравнении вместо строки:

while (g.MeasureString(shipmentData.LongDesc, f)...)

Вы также можете иметь:

while (g.MeasureString(shipmentData.LongDesc, _dataItemHintBox.Font)...)

Это сведет на нет необходимость во втором Font экземпляре класса, то есть f .

Пожалуйстане стесняйтесь публиковать отзывы, так как я могу изменить свой образец, чтобы он соответствовал вашей реальности на основе полученных отзывов, чтобы они лучше помогали вам.=)

Надеюсь, это поможет!=)

2 голосов
/ 11 июня 2010

Вы можете использовать любую из перегрузок TextRenderer.MeasureText, которая подходит вам.Используя эту функцию, вы можете определить фактический размер отрисовки строки и соответственно отрегулировать размер панели.

Если вы пытаетесь измерить внутри события Paint, тогда вы можете использовать функцию MeasureStringна вашем e.Graphics объекте, но изменение размера внутри Paint не является разумным.Использование TextRenderer избавляет от необходимости создавать Graphics объект с CreateGraphics() и избавляться от него, когда вы закончите.

EDIT

, начиная с TextRenderer не поддерживается в компактной среде (я пропустил тег в первый раз, когда увидел вопрос), вам придется использовать функцию MeasureString() для объекта Graphics.Как то так:

public Size GetStringSize(string text)
{
    using(Graphics g = yourPanel.CreateGraphics())
    {
        return g.MeasureString(text, yourPanel.Font);
    }
}
...