Не могу сделать элементы в списке прямо вниз - PullRequest
0 голосов
/ 30 июня 2019

У меня следующая проблема со списком в c #.

Чтобы было легче понять, я просто немного его уточнил.

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            listBox1.Items.Add("xxxxxx" +"\t\t\t"+ "yyyyyyy");
            listBox1.Items.Add("xxxxxxx" + "\t\t\t" + "yyyyyyy");
            listBox1.Items.Add("xxxxxxxx" + "\t\t\t" + "yyyyyyy");
            listBox1.Items.Add("xxxxxxxxx" + "\t\t\t" + "yyyyyyy");
            listBox1.Items.Add("xxxxxxxxxx" + "\t\t\t" + "yyyyyyy");
        }
    }
}

От ряда 1 до 4 он идеально печатается прямыми рядами вниз.Но 5-я строка полностью отключена, когда я запускаю программу, хотя места достаточно.Может ли какое-нибудь тело помочь мне заставить все предметы располагаться прямыми рядами вниз?

Ответы [ 2 ]

3 голосов
/ 30 июня 2019

Вам нужно установить свойство CustomTabOffsets и свойство UseCustomTabOffsets , а затем вы можете уменьшить количество вкладок в строках до одной.

Например,

ListBox lb = new ListBox();
lb.Size = new Size(500, 200);
lb.CustomTabOffsets.Add(100);
lb.UseCustomTabOffsets = true;

lb.Items.Add("xxxxxx" + "\t" + "yyyyyyy");
lb.Items.Add("xxxxxxx" + "\t" + "yyyyyyy");
lb.Items.Add("xxxxxxxx" + "\t" + "yyyyyyy");
lb.Items.Add("xxxxxxxxx" + "\t" + "yyyyyyy");
lb.Items.Add("xxxxxxxxxx" + "\t" + "yyyyyyy");

Form f = new Form();
f.Controls.Add(lb);
f.Show();

Конечно, вы должны изменить эти 100 на нечто более совместимое с фактической максимальной длиной первой части ваших строк и шириной вашего ListBox

1 голос
/ 01 июля 2019

Стандартный ListBox поддерживает остановки табуляции (он создается в стиле LBS_USETABSTOPS ), но для настраиваемого таб-стопа должна быть включена настройка UseCustomTabOffsets= true, затем добавляется один или несколько значения, представляющие позиции табуляции, для CustomTabOffsets IntegerCollection .

Есть хитрость в расчете этих позиций ; как описано в Документах о сообщении LB_SETTABSTOPS :

(...) целые числа представляют количество четвертей среднего символа ширина для шрифта, который выбран в окне списка. Например, табуляция 4 помещается на 1,0 символьных единиц, а табуляция 6 - размещается на 1,5 средних символьных единиц. Однако, если список часть диалогового окна, целые числа находятся в единицах шаблона диалога. табуляция должна быть отсортирована по возрастанию (...)

Поскольку Font.ToLogFont () не возвращает средний размер символа в lfWidth элементе структуры LOGFONT , мы можем вычислить его (без PInvoking) из пикселей измеряется как:

([CurrentTextWidth] / [AverageCharWidth]) * [TabSize]

Где [CurrentTextWidth] - ширина строки в пикселях, рассчитанная с использованием TextRenderer.MeasureText ,
[AverageCharWidth] можно рассчитать, измеряя разницу между M и i,
и [TabSize] представляют четверти средней ширины символа (как описано в Документах, TabStop, равный 4, равен ширине среднего символа относительно выбранного в настоящий момент шрифта).

Пример теста для создания 3 столбцов из текстовых частей, разделенных '\t' в ListBox:

listBox1.Items.AddRange(new[] {
    "x\tyyyyyyy\teeeeee",
    "xxxx\tyyyyyyy\tmmmmmmm",
    "xxxxxx\tyyyyyyy\tlllllll",
    "AbcdEfgHilm\tyyyyyyy\tgggggggg",
    "xxxxxx\tyyyyyyy\tzzzzzzz",
    "XXaaMMiixxx\tyyyyyyy\tiiiiiiiiiiiiiiii"
});
SetListBoxTabs(listBox1);

Здесь я устанавливаю float tabSize = 4.2f вместо 4.0, потому что между частями текста, разделенными табуляцией, должно быть некоторое пространство, поэтому я добавляю часть базового значения, чтобы создать пространство между столбцами .
Это значение затем можно использовать для пропорциональной корректировки пространства между столбцами.

public void SetListBoxTabs(ListBox listBox)
{
    float tabSize = 4.2f;
    float currTabStop = 0;

    int tabs = listBox.GetItemText(listBox.Items[0]).Split('\t').Length - 1;
    if (tabs == 0) return;
    var tabStops = new List<int>(tabs);
    tabStops.AddRange(Enumerable.Repeat(0, tabs).ToArray());

    using (var g = Graphics.FromHwnd(listBox.Handle))
    {
        float average = GetFontAverageCharSize(g, listBox.Font);

        foreach (var item in listBox.Items)
        {
            string text = listBox.GetItemText(item);
            string[] parts = text.Split('\t');  // Use Substring(IndexOf()) here
            for (int i = 0; i < parts.Length - 1; i++)
            {
                float width = TextRenderer.MeasureText(g, parts[i], listBox.Font,
                    Size.Empty, TextFormatFlags.LeftAndRightPadding).Width;
                float tabWidth = (width / average) * tabSize;
                currTabStop += tabWidth;
                tabStops[i] = (int)Math.Max(currTabStop, tabStops[i]);
            }
            currTabStop = 0;
        }
    }

    listBox.UseTabStops = true;  // Just in case 1 ...
    listBox.UseCustomTabOffsets = true;
    var offsets = listBox.CustomTabOffsets;
    offsets.Clear(); // Just in case 2 ...
    foreach (int tab in tabStops) { offsets.Add(tab); }
}

public float GetFontAverageCharSize(Graphics g, Font font)
{
    string textMax = new string('M', 100);
    string textMin = new string('i', 100);
    float maxWidth = TextRenderer.MeasureText(g, textMax, listBox1.Font).Width;
    float minWidth = TextRenderer.MeasureText(g, textMin, listBox1.Font).Width;
    return (maxWidth + minWidth) / (2.0f * textMax.Length);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...