代码之家  ›  专栏  ›  技术社区  ›  AZDean

是否有一种简单的方法在弹出文本窗口中创建两列?

  •  1
  • AZDean  · 技术社区  · 16 年前

    这似乎是一件容易的事情。我只想弹出一个文本窗口,显示两列数据——左侧的描述和右侧显示的相应值。我对窗体没有太多的了解,所以我只抓取了第一个看起来合适的控件,一个文本框。我认为使用制表符是创建第二列的一种简单方法,但是我发现事情并没有那么好地工作。

    我尝试这样做的方式似乎有两个问题(见下文)。首先,我在许多网站上看到,由于字体的复杂程度,加上字距问题,测量功能并不十分精确。第二个问题是,我不知道文本框控件在下面使用什么作为其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 回复  |  直到 6 年前
        1
  •  0
  •   Matt Dawdy    16 年前

    如果需要,可以将此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语句添加到表单中:

    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);
    

    当要设置Tabstop时调用此方法:

        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";
        }
    
        2
  •  1
  •   AZDean    16 年前

    谢谢马特,你的解决方案对我很有用。这是我的代码版本…

    // 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);
    }
    
        3
  •  0
  •   Ken Wootton    16 年前

    如果你想要一个真正的表格,哈伦先生的回答是一个很好的答案。DataGridView将为您提供非常Excel电子表格类型的外观。

    如果您只需要一个两列布局(类似于HTML的表),那么可以尝试使用TableLayoutPanel。它将为您提供所需的布局,使您能够在每个表单元格中使用标准控件。

        4
  •  -1
  •   bruceatk    16 年前

    我认为唯一的方法是做一些类似于你正在做的事情,但是使用固定的字体,用空格填充自己的内容,这样你就不必担心选项卡的扩展。

        5
  •  -2
  •   Nicholas Mancuso    16 年前

    文本框不允许使用HTML吗?如果是这样,只需使用HTML将文本格式化为表格。否则,尝试将文本添加到DataGrid,然后将其添加到表单中。