0

我有下面的代码,它是选取框标签的实现。我希望选取框标签在计算机上以最有效的速度运行,同时在不同的计算机上保持恒定的速度。我希望最小化跳过的“帧”数量,以便程序充分利用正在运行的计算机。但与此同时,我不一定要消耗 100% 的 CPU(这些陈述是否相互矛盾?我不确定)。

目前,我为动画循环的每次迭代都睡了 10 毫秒。这对我来说感觉很浪费,而且似乎它可能会减慢可能需要额外 10 毫秒的较慢计算机上的动画。我不确定在 sleep 方法中使用的最佳价值是什么,或者我是否应该睡觉。我已经阅读了一些关于 Sleep(0) 和 Sleep(1) 以及 Yield 和 SpinWait 的内容,但我无法理解这一切。

过多地调用 Invalidate 也是一件坏事吗?我可以通过调用它来超载它吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Diagnostics;
using Timer = System.Timers.Timer;
using System.Threading;

namespace Scoreboard
{
    public class MarqueeLabel : Label
    {
        private float _marqueeOffset;
        private float _marqueeMeasurement;

        public MarqueeLabel()
        {
            UseCompatibleTextRendering = true;

            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.UserPaint, true);

            Thread t = new Thread(ThreadRun);
            t.IsBackground = true;
            t.Start();
        }

        public void ThreadRun()
        {
            long time = DateTime.Now.Ticks;
            long diff = 0;

            while (true)
            {
                float step = -((float)diff / (20 * TimeSpan.TicksPerMillisecond)); //change "frame" based on the elapsed time
                _marqueeOffset = _marqueeOffset >= -_marqueeMeasurement ? _marqueeOffset + step : Width;

                Invalidate();
                Thread.Sleep(10); // how long should i wait here?

                long temp = DateTime.Now.Ticks;
                diff = temp - time;
                time = temp;
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            StringFormat stringFormat = new StringFormat();
            stringFormat.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
            stringFormat.Trimming = StringTrimming.None;
            stringFormat.Alignment = StringAlignment.Near;

            Rectangle rect = ClientRectangle;
            rect.X += (int)_marqueeOffset;
            e.Graphics.DrawString(Text, Font, new SolidBrush(ForeColor), rect, stringFormat);
        }

        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            MeasureText();
        }

        protected override void OnFontChanged(EventArgs e)
        {
            base.OnFontChanged(e);
            MeasureText();
        }

        void MeasureText()
        {
            _marqueeMeasurement = CreateGraphics().MeasureString(Text, Font).Width;
        }
    }
}
4

0 回答 0