Есть ли простой способ создать два столбца во всплывающем текстовом окне? - PullRequest
1 голос
/ 16 сентября 2008

Это казалось легким делом. Я просто хотел открыть текстовое окно и отобразить два столбца данных - описание слева и соответствующее значение, отображаемое справа. Я не очень много работал с Forms, поэтому я просто взял первый элемент управления, который казался подходящим, TextBox. Я думал, что использование вкладок будет простым способом создания второго столбца, но я обнаружил, что вещи просто не работают так хорошо.

Кажется, есть две проблемы с тем, как я пытался это сделать (см. Ниже). Во-первых, я читал на многих веб-сайтах, что функция MeasureString не очень точна из-за сложности шрифтов, проблем с кернингом и всего остального. Во-вторых, я понятия не имею, что элемент управления TextBox использует в качестве своего StringFormat внизу.

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

    TextBox textBox    = new TextBox();
    textBox.Font       = new Font("Calibri", 11);
    textBox.Dock       = DockStyle.Fill;
    textBox.Multiline  = true;
    textBox.WordWrap   = false;
    textBox.ScrollBars = ScrollBars.Vertical;

    Form form            = new Form();
    form.Text            = "Recipe";
    form.Size            = new Size(400, 600);
    form.FormBorderStyle = FormBorderStyle.Sizable;
    form.StartPosition   = FormStartPosition.CenterScreen;
    form.Controls.Add(textBox);

    Graphics g = form.CreateGraphics();

    float targetWidth = 230;

    foreach (PropertyInfo property in properties)
    {
        string text = String.Format("{0}:\t", Description);

        while (g.MeasureString(text,textBox.Font).Width < targetWidth)
            text += "\t";

        textBox.AppendText(text + value.ToString() + "\n");
    }

    g.Dispose();
    form.ShowDialog();

Ответы [ 5 ]

1 голос
/ 16 сентября 2008

Спасибо, Мэтт, ваше решение отлично сработало для меня. Вот моя версия вашего кода ...

// This is a better way to pass in what tab stops I want...
SetTabStops(textBox, new int[] { 12,120 });

// And the code for the SetTabsStops method itself...
private const uint EM_SETTABSTOPS = 0x00CB;

[DllImport("User32.dll")]
private static extern uint SendMessage(IntPtr hWnd, uint wMsg, int wParam, int[] lParam);

public static void SetTabStops(TextBox textBox, int[] tabs)
{
    SendMessage(textBox.Handle, EM_SETTABSTOPS, tabs.Length, tabs);
}
0 голосов
/ 16 сентября 2008

Я считаю, что единственный способ - сделать что-то похожее на то, что вы делаете, но использовать фиксированный шрифт и выполнить собственный отступ с пробелами, чтобы вам не пришлось беспокоиться о расширении табуляции.

0 голосов
/ 16 сентября 2008

Если хотите, вы можете перевести этот код VB.Net на C #. Теория здесь заключается в том, что вы изменяете размер вкладки в элементе управления.

Private Declare Function SendMessage _
  Lib "user32" Alias "SendMessageA" _
  (ByVal handle As IntPtr, ByVal wMsg As Integer, _
  ByVal wParam As Integer, ByRef lParam As Integer) As Integer


Private Sub SetTabStops(ByVal ctlTextBox As TextBox)

  Const EM_SETTABSTOPS As Integer = &HCBS

  Dim tabs() As Integer = {20, 40, 80}

  SendMessage(ctlTextBox.Handle, EM_SETTABSTOPS, _
    tabs.Length, tabs(0))

End Sub

Я также конвертировал версию для C #. Протестировано и работает в VS2005.

Добавьте это, используя утверждение к вашей форме:

using System.Runtime.InteropServices;

Поместите это сразу после объявления класса:

    private const int EM_SETTABSTOPS = 0x00CB;
    [DllImport("User32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessage(IntPtr h, int msg, int wParam, int[] lParam);

Вызывайте этот метод, если вы хотите установить табуляторы:

    private void SetTabStops(TextBox ctlTextBox)
    {
        const int EM_SETTABSTOPS = 203;
        int[] tabs = { 100, 40, 80 };
        SendMessage(textBox1.Handle, EM_SETTABSTOPS, tabs.Length, tabs);
    }

Чтобы использовать это, вот все, что я сделал:

    private void Form1_Load(object sender, EventArgs e)
    {
        SetTabStops(textBox1);

        textBox1.Text = "Hi\tWorld";
    }
0 голосов
/ 16 сентября 2008

Если вы хотите что-то действительно табличное, ответ мистера Харена будет хорошим. DataGridView предоставит вам внешний вид электронных таблиц Excel.

Если вам просто нужен макет из двух столбцов (аналог таблицы HTML), попробуйте TableLayoutPanel. Это даст вам желаемый макет с возможностью использования стандартных элементов управления в каждой ячейке таблицы.

0 голосов
/ 16 сентября 2008

Разве текстовые поля не позволяют использовать HTML? Если это так, просто используйте HTML для форматирования текста в таблицу. В противном случае попробуйте добавить текст в таблицу данных, а затем добавить его в форму.

...