You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForms Panel内自定义ChatMessage控件被过度截断的问题求助

WinForms Panel内自定义ChatMessage控件被过度截断的问题求助

大家好,我遇到一个WinForms布局的棘手问题,想请各位前辈帮忙分析下:

我做了一个WinForms程序,布局结构是Form → TabControl.TabPage → Panel,平时布局都没什么问题,包括在Panel左边缘放置控件时都能正常显示。但不知道是Visual Studio设计器的bug,还是我自定义控件的代码有问题——当我把自己写的ChatMessage用户控件添加到Panel里时,控件总是被截断,只有很小一部分能显示出来。我特意修改了控件的背景色来确认,结果确实是被截断了,不是控件没绘制出来😂

(截图说明:自定义ChatMessage控件仅显示左上角小部分区域,大部分内容被父容器截断)

下面是我的ChatMessage自定义控件完整代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MessengerApp
{
    public partial class ChatMessage : UserControl
    {
        string textf = string.Empty;
        SizeF stringlänge;
        bool gedreht = false;
        int num = 0;

        public ChatMessage(string texte, int nummer)
        {
            InitializeComponent();
            Size = new Size(500, 500);
            num = nummer;
            textf = texte;
            Graphics g = CreateGraphics();
            stringlänge = g.MeasureString(texte, DefaultFont);
            Size = new Size((int)stringlänge.Width + 73, (int)stringlänge.Height + 33);
        }

        private void ChatMessage_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            SizeF größe = g.MeasureString(textf, DefaultFont);
            Size endgröße = new Size((int)größe.Width + 120, (int)größe.Height + 83);
            int f = 0;
            int y = (int)größe.Width;

            if (gedreht)
            {
                f = 20;
                y = (int)größe.Width + 73;
            }

            // Hauptrechteck der Sprechblase
            RectangleF rect = new RectangleF(1 + f, 1, größe.Width + 50, größe.Height + 30);
            float radius = 20f;
            Size = new Size(y, (int)rect.Height + 3);

            // Zeiger-Einstellungen
            bool zeigerLinks = gedreht;// Ändere zu false für rechte Seite
            PointF zeigerSpitze;
            PointF zeigerOben;
            PointF zeigerUnten;

            if (zeigerLinks)
            {
                zeigerSpitze = new PointF(rect.Left - 20, rect.Bottom);
                zeigerOben = new PointF(rect.Left, zeigerSpitze.Y - 20);
                zeigerUnten = new PointF(rect.Left, zeigerSpitze.Y);
            }
            else
            {
                zeigerSpitze = new PointF(rect.Right + 20, rect.Bottom);
                zeigerOben = new PointF(rect.Right, zeigerSpitze.Y - 20);
                zeigerUnten = new PointF(rect.Right, zeigerSpitze.Y);
            }

            // Erstelle Pfad mit abgerundetem Rechteck + Zeiger
            GraphicsPath path = new GraphicsPath();
            float d = radius * 2;

            if (zeigerLinks)
            {
                // Start oben links
                path.AddArc(rect.Left, rect.Top, d, d, 180, 90);
                path.AddLine(rect.Left + radius, rect.Top, rect.Right - radius, rect.Top);
                path.AddArc(rect.Right - d, rect.Top, d, d, 270, 90);
                path.AddLine(rect.Right, rect.Top + radius, rect.Right, rect.Bottom - radius);
                path.AddArc(rect.Right - d, rect.Bottom - d, d, d, 0, 90);
                PointF control = new PointF(zeigerOben.X, zeigerSpitze.Y - 10);
                PointF control2 = new PointF(zeigerSpitze.X + 10, zeigerSpitze.Y);
                PointF control4 = new PointF(zeigerOben.X - 10.01f, zeigerOben.Y + 10.01f);
                path.AddBezier(zeigerSpitze, control4, control, zeigerOben);
                // path.AddLine(zeigerSpitze.X, zeigerSpitze.Y, rect.Left, zeigerOben.Y);
                path.AddLine(rect.Left, zeigerOben.Y - 10, rect.Left, rect.Top + radius);
            }
            else
            {
                // Start oben links
                path.AddArc(rect.Left, rect.Top, d, d, 180, 90);
                path.AddLine(rect.Left + radius, rect.Top, rect.Right - radius, rect.Top);
                path.AddArc(rect.Right - d, rect.Top, d, d, 270, 90);
                path.AddLine(rect.Right, rect.Top + radius, rect.Right, rect.Bottom - radius);
                // path.AddLine(rect.Right - radius, rect.Bottom, rect.Left + radius, rect.Bottom);
                PointF control = new PointF(zeigerOben.X, zeigerSpitze.Y - 10);
                PointF control2 = new PointF(zeigerSpitze.X - 10, zeigerSpitze.Y);
                PointF control4 = new PointF(zeigerOben.X + 0.01f, zeigerOben.Y - 0.01f);
                path.AddBezier(zeigerOben, control4, control, zeigerSpitze);
                path.AddLine(rect.Right - radius, rect.Bottom, rect.Left + radius, rect.Bottom);
                path.AddArc(rect.Left, rect.Bottom - d, d, d, 90, 90);
                // path.AddLine(zeigerSpitze.X, zeigerSpitze.Y, rect.Left, zeigerOben.Y);
                // path.AddLine(rect.Left, rect.Bottom - 10, rect.Left, rect.Top + radius);
            }

            path.CloseFigure();

            // Füllen
            using (Brush b = new SolidBrush(Color.LightBlue))
            {
                g.FillPath(b, path);
            }

            // Umriss
            using (Pen p = new Pen(Color.DarkBlue, 2))
            {
                g.DrawPath(p, path);
            }

            // Text
            string text = textf;
            using (Font font = new Font("Segoe UI", 10))
            using (Brush tb = new SolidBrush(Color.Black))
            {
                RectangleF textRect = rect;
                g.DrawString(text, font, tb, textRect, new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
            }
        }

        public int number
        {
            get { return num; }
        }

        public bool drehen
        {
            get { return gedreht; }
            set { gedreht = value; }
        }
    }
}

我将控件添加到Panel的代码片段如下(未粘贴完整,关键逻辑是实例化ChatMessage后添加到panel1):

foreach ((int, string, string) strings in ns.GetList)
{
    if (!panel1.Controls.OfType<ChatMessage>...)
    {
        // 实例化ChatMessage并添加到panel1的逻辑
        var chatMsg = new ChatMessage(strings.Item2, strings.Item1);
        panel1.Controls.Add(chatMsg);
    }
}

我自己检查了自定义控件的代码:在构造函数和Paint事件里都根据文本长度调整了控件的Size,但还是出现截断的情况。想请教各位:

  • 会不会是Panel的AutoScroll或者AutoSize属性没设置对?
  • 自定义控件的Size调整逻辑有没有问题?比如在Paint事件里动态改Size会不会导致布局异常?
  • 有没有可能是TabPage/Panel的布局模式(比如Dock、Anchor)影响了控件的显示?

麻烦大家帮忙看看,谢谢啦!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 06:48:05