用于显示图像的 Windows 窗体文本框

Posted

技术标签:

【中文标题】用于显示图像的 Windows 窗体文本框【英文标题】:Windows Form TextBox to show images 【发布时间】:2013-04-28 01:36:50 【问题描述】:

我目前有一个 Windows 窗体项目,我在其中创建了一个简单的聊天应用程序。目前聊天输出到多行文本框,但是我现在想稍微增强一下并添加一些样式。随着时间的推移,我希望有一些图像,很好地格式化它,将来可能还有一些 html(尽管这并不重要)。我只是想知道我应该用什么来实现这一点。我确实想过更新一个 HTML 页面,然后用每条新消息重新加载它,但这不会提供很好的用户体验。我还查看了richtextbox 类,但这似乎对我所追求的有所限制。我希望有人可以为我指明使用什么的正确方向。

我正在尝试实现类似于我用红色突出显示的内容:

【问题讨论】:

使用RichTextBox。 用于winforms的HTML控件***.com/questions/3456787/… 从 WinForms 切换到 WPF 的众多令人信服的理由之一... 100% 同意@programmer93,忘记winforms 你可以在WPF 中使用简单的ListBox 和一些DataTemplates 来实现。检查this sample chat client 也许您可以创建自己的组件 - msdn.microsoft.com/en-us/library/ms228287(v=vs.90).aspx。我自己没用过。尝试***.com/questions/8861022/… 或程序员93 和HighCore 强烈建议您使用wpf。 【参考方案1】:

虽然其他一些 cmets 表明 WPF 非常适合此,但在现实世界中,切换并不总是可能或可取的。

一个普通的所有者绘制的列表框非常适合这个目的。

要创建一个,只需将列表框上的 DrawMode 设置为 OwnerDrawVariable,例如

list.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;

然后您只需要提供两个事件处理程序,第一个用于测量项目(告诉列表框项目的高度),另一个用于实际呈现它。例如

this.list.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.list_DrawItem);
this.list.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(this.list_MeasureItem);

使用 GDI+ DrawImage 将图像渲染到列表中相当简单(其中 g 是您的图形上下文_:

Bitmap bmp = Bitmap.FromFile("test.jpg");
Rectangle source = new Rectangle(0, 0, bmp.Width, bmp.Height);
Rectangle dest = source;
g.DrawImage(bmp, dest, source, GraphicsUnit.Pixel);

这是一个示例 Windows 窗体,它具有系统上所有字体的所有者绘制的列表框,生成可变高度的所有者绘制的列表项:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Font_Display

    public class Test : System.Windows.Forms.Form
    
        private Font head;
        private System.Windows.Forms.ListBox list;
        private System.ComponentModel.Container components = null;

        public Test()
        
            InitializeComponent();

            head = new Font("Arial", 10, GraphicsUnit.Pixel);
        

        protected override void Dispose(bool disposing)
        
            if (disposing) 
                if (components != null) 
                    components.Dispose();
                
            
            base.Dispose(disposing);
        

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        
            this.list = new System.Windows.Forms.ListBox();
            this.SuspendLayout();
            // 
            // list
            // 
            this.list.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
            this.list.IntegralHeight = false;
            this.list.Location = new System.Drawing.Point(12, 12);
            this.list.Name = "list";
            this.list.Size = new System.Drawing.Size(604, 323);
            this.list.TabIndex = 0;
            this.list.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.list_DrawItem);
            this.list.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(this.list_MeasureItem);
            // 
            // Test
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
            this.ClientSize = new System.Drawing.Size(520, 358);
            this.Controls.Add(this.list);
            this.Name = "Test";
            this.Text = "Display";
            this.Load += new System.EventHandler(this.Test_Load);
            this.Resize += new System.EventHandler(this.Display_Resize);
            this.ResumeLayout(false);

        
        #endregion

        [STAThread]
        static void Main()
        
            Application.Run(new Test());
        

        private void Test_Load(object sender, EventArgs e)
        
            try 
                // Loop all font families
                FontFamily[] families = FontFamily.Families;
                foreach (FontFamily family in families) 
                    try  list.Items.Add(new Font(family, 20, FontStyle.Regular, GraphicsUnit.Pixel)); continue; 
                    catch  
                

                Display_Resize(this, EventArgs.Empty);
            
            catch 
            
        

        private void Display_Resize(object sender, System.EventArgs e)
        
            Rectangle r = this.ClientRectangle;
            list.SetBounds(list.Left,
                list.Top,
                r.Width - (list.Left * 2),
                r.Height - (list.Top + list.Left));
        

        public string TextValue = "Example String";

        public StringFormat Format
        
            get
            
                StringFormat format = StringFormat.GenericTypographic;
                format.FormatFlags |= StringFormatFlags.NoWrap;
                return format;
            
        

        private void list_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
        
            Brush back = null;
            Brush fore = null;
            Brush htext = null;
            Rectangle r;

            try 
                Font font = (Font)list.Items[e.Index];

                // Loop
                if ((e.State & DrawItemState.Selected) != 0) 
                    back = new SolidBrush(Color.DarkBlue);
                    fore = new SolidBrush(Color.White);
                    htext = new SolidBrush(Color.Orange);
                
                else 
                    back = new SolidBrush(Color.White);
                    fore = new SolidBrush(Color.Black);
                    htext = new SolidBrush(Color.DarkRed);
                

                // Fill the rect
                e.Graphics.FillRectangle(back, e.Bounds);

                // Get the size of the header
                SizeF szHeader = e.Graphics.MeasureString(font.Name, head, int.MaxValue, Format);
                SizeF szText = e.Graphics.MeasureString(TextValue, font, int.MaxValue, Format);

                // Draw the string
                r = e.Bounds;
                r.Height = (int)szHeader.Height;
                e.Graphics.DrawString(font.Name, head, htext, r, Format);

                // Draw the string
                r = e.Bounds;
                r.Y = (int)(e.Bounds.Y + szHeader.Height);
                r.Height = (int)szText.Height;
                e.Graphics.DrawString(TextValue, font, fore, r, Format);
            
            catch 
            
            finally 
                if (fore != null) fore.Dispose();
                if (back != null) back.Dispose();
                if (htext != null) htext.Dispose();
            
        

        private void list_MeasureItem(object sender, System.Windows.Forms.MeasureItemEventArgs e)
        
            try 
                Font font = (Font)list.Items[e.Index];
                SizeF szHeader = e.Graphics.MeasureString(font.Name, head, int.MaxValue, Format);
                SizeF szText = e.Graphics.MeasureString(TextValue, font, int.MaxValue, Format);

                // Return it
                e.ItemHeight = (int)(szText.Height + szHeader.Height);
                e.ItemWidth = (int)Math.Max(szText.Width, szHeader.Width);
            
            catch 
            
        
    

【讨论】:

以上是关于用于显示图像的 Windows 窗体文本框的主要内容,如果未能解决你的问题,请参考以下文章

如何通过在 C# windows 窗体中的文本框中输入来更改图像的大小?

在 windows 窗体文本框中显示代码结果

将 Windows 窗体列表框保存到文本文件 C#

Windows 窗体按钮显示文本框并输入名称以创建新按钮 [关闭]

在 c# 中使用文本框中的数据库值打开特定的 Windows 窗体

C# windows窗体中的文本框到数组声明