【问题标题】:Rectangle will not clear in C# Forms矩形在 C# 表单中不会被清除
【发布时间】:2017-12-01 16:52:48
【问题描述】:

我正在尝试在 C# Forms 中构建一个自定义控件,让用户可以在控件上放置元素以直观地构建报表打印输出,但是我遇到了屏幕的一部分无法清除的问题,即使在绘制事件的顶部有明确的 e.Graphics.Clear 调用。

You can see here what happens when I maximize the window.

这是我的控件代码: 公共部分类 ReportBuilderControl : UserControl {

    #region Delegates

    public delegate void SelectedElementChangedHandler(object sender, SelectedElementChangedEventArgs e);

    #endregion Delegates

    #region Events

    public event SelectedElementChangedHandler SelectedElementChanged;

    #endregion Events

    #region Variables

    private float mZoom = 1;
    private PaperSize mPaperSize = new PaperSize("Paper", 850, 1100);
    private List<PrintElement> mElements = new List<PrintElement>();
    private int mPageCount = 1;


    #endregion Variables

    public int PageCount {
        get { return mPageCount; }
        set {
            mPageCount = value;
            UpdateScrollbarSize();
        }
    }

    /// <summary>
    /// The number of pixels each value of the scrollbar will move. Scaling does not affect this.
    /// </summary>
    public float ScrollSize {
        get { return 10f; }
    }

    public int PagePadding {
        get { return (int)(3 * ScrollSize * Zoom); }
    }

    public float Zoom {
        get { return mZoom; }
        set {
            mZoom = value;
            Invalidate();
            UpdateScrollbarSize();
        }
    }

    public int ScaledPageHeight {
        get {
            return (int)(mPaperSize.Height * Zoom);
        }
    }

    private void UpdateScrollbarSize() {
        VerticalScroll.Maximum = (int)Math.Ceiling(mPageCount * mPaperSize.Height / ScrollSize * Zoom + (PagePadding * (mPageCount + 1) / ScrollSize));
    }

    public ReportBuilderControl() {
        InitializeComponent();
        Paint += ReportBuilderControl_Paint;
    }

    private void ReportBuilderControl_Paint(object sender, PaintEventArgs e) {
        // At the very least, we need to fill the clip rectangle with the background color.
        e.Graphics.Clear(BackColor);

        // Determine which pages are visible.
        Rectangle vis = new Rectangle(0, 0, (int)(ClientRectangle.Width / Zoom), (int)(ClientRectangle.Height / Zoom));
        vis.Y = (int)(VerticalScroll.Value * ScrollSize);
        int pageHeight = (int)(mPaperSize.Height * Zoom),
            pageWidth = (int)(mPaperSize.Width * Zoom),
            startPage = vis.Y / pageHeight,
            endPage = (int)(Math.Ceiling(vis.Height / (double)pageHeight)) + startPage;

        // Bring the invalidated rectangle to "Page Space", meaning an unzoomed, regular sized page, i.e. 850x1100
        Rectangle clip = e.ClipRectangle;
        clip.X = (int)(clip.X / Zoom);
        clip.Y = (int)(clip.Y / Zoom);
        clip.Width = (int)(clip.Width / Zoom);
        clip.Height = (int)(clip.Height / Zoom);

        // Draw visible pages, if the unzoomed page rectangle intersects the clip rectangle.
        for (int i = startPage; i < endPage; ++i) {
            // Calculate page rectangle.
            int rectX = Math.Max((int)((ClientRectangle.Width - mPaperSize.Width) * 0.5), 0);
            int rectY = PagePadding * (i + 1) + mPaperSize.Height * i;
            Rectangle pageRect = new Rectangle(rectX, rectY, pageWidth, pageHeight);
            if(pageRect.IntersectsWith(e.ClipRectangle)) {
                Rectangle intersection = e.ClipRectangle;
                intersection.Intersect(pageRect);
                e.Graphics.FillRectangle(new SolidBrush(Color.WhiteSmoke), intersection);
            }
        }
    }
}

这是我创建表单并附加控件的测试代码:

        Form builder = new Form();
        ReportBuilderControl rpt = new ReportBuilderControl();
        rpt.BackColor = System.Drawing.Color.FromArgb(255, 14, 15, 15);
        rpt.ClientSize = builder.ClientSize;
        rpt.Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom | AnchorStyles.Left;
        builder.Controls.Add(rpt);
        builder.ShowDialog();

【问题讨论】:

  • 您应该发布代码以支持您的问题和/或问题。请更新您的问题并在您遇到问题的地方发布代码
  • 我建议调整大小后刷新窗口。
  • @HadiFooladiTalari 这行得通,但是当表单最大化时,剪辑矩形是全屏,我在整个剪辑矩形上尝试了 Graphics.Clear 和 Graphics.FillRectangle。当我应该在该区域上绘图时,为什么刷新表单会解决此问题?
  • @MethodMan 是的,在我将代码添加到问题中之前,我不小心在表单上按了 Enter,并立即对其进行了编辑。您的回复速度非常快!
  • 好吧@Zalerinian 我是Half man Half Amazing... LOL

标签: c# winforms


【解决方案1】:

调整大小后刷新窗口。因为当您最大化窗口时,它只会重绘隐藏的部分(不是所有窗口)。

将此代码Resize += (s, e) =&gt; Refresh(); 放入构造函数中,如下所示:

public ReportBuilderControl()
{
    InitializeComponent();
    Paint += ReportBuilderControl_Paint;
    Resize += (s, e) => Refresh();
}

【讨论】:

  • 只需在构造函数中添加this.ResizeRedraw = true;。 Form 类被视为一个容器控件,它使用一种优化,只重绘由调整大小暴露的控件部分。 ResizeRedraw 属性是抑制这种优化的一种简单方法。
  • 啊,这就解释了原因。感谢您的帮助!我有点希望避免每次调整大小时都重新绘制整个控件(最大化/恢复除外),但如果这是需要做的,那么我认为它工作得很好,它没有针对 C# Forms 进行更改.再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 2012-04-02
  • 1970-01-01
  • 2016-12-30
  • 2015-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多