public SubtitleManager(BarrageWindow parent, Rectangle rect, Configurations subtitleConf)
        {
            FontStyle fontStyle = FontStyle.Regular;
            if (subtitleConf.GetBoolean("Font-Bold", true))
                fontStyle |= FontStyle.Bold;
            if (subtitleConf.GetBoolean("Font-Italic", false))
                fontStyle |= FontStyle.Italic;
            Font = new Font(subtitleConf.GetString("Font-Family", "黑体"),
                subtitleConf.GetSingle("Font-Size", 30), fontStyle, GraphicsUnit.Pixel);
            Padding = subtitleConf.GetInt("Padding", 10);
            FillColor = subtitleConf.GetRgbColor("Fill-Color", Color.White);
            BorderColor = subtitleConf.GetRgbColor("Border-Color", Color.Black);
            BorderWidth = subtitleConf.GetSingle("Border-Width", 1.0f);

            current = -1;
            groups = new List<SubtitleGroup>();
            int n;
            var lycFiles = from pair in subtitleConf
                           where pair.Key.StartsWith("Lyc-File")
                            && Int32.TryParse(pair.Key.Substring("Lyc-File".Length), out n)
                           select new { Index = Int32.Parse(pair.Key.Substring("Lyc-File".Length)) - 1,
                               FileName = pair.Value };
            foreach (var lycFile in lycFiles.OrderBy(l => l.Index))
            {
                try
                {
                    groups.Add(new SubtitleGroup(this, new LyricFile(lycFile.FileName)));
                    Core.Debugger.Log("lyc loaded: " + lycFile.FileName);
                }
                catch (Exception exc)
                {
                    Core.Debugger.Log("lyc file load failed: " + lycFile.FileName + " (" + exc.Message + ")");
                }
            }
            if (groups.Count >= 0)
                current = 0;

            stopwatch = new Stopwatch();
            this.Rect = Rectangle.FromLTRB(rect.Left + Padding, rect.Top + Padding,
                rect.Right - Padding, rect.Bottom - Padding);

            GlobalKeyHook.Instance.SetProcessor(
                subtitleConf.GetKeys("Start-Key", Keys.Control | Keys.Alt | Keys.D1),
                k =>
                {
                    if (StartSubtitle())
                        parent.ShowNotice("字幕开始");
                    return true;
                }
            );

            GlobalKeyHook.Instance.SetProcessor(
                subtitleConf.GetKeys("End-Key", Keys.Control | Keys.Alt | Keys.D2),
                k =>
                {
                    if (StopSubtitle())
                        parent.ShowNotice("字幕停止");
                    return true;
                }
            );

            GlobalKeyHook.Instance.SetProcessor(
                subtitleConf.GetKeys("Prev-Key", Keys.Control | Keys.Alt | Keys.PageUp),
                k =>
                {
                    PrevSubtitle();
                    return true;
                }
            );

            GlobalKeyHook.Instance.SetProcessor(
                subtitleConf.GetKeys("Next-Key", Keys.Control | Keys.Alt | Keys.PageDown),
                k =>
                {
                    NextSubtitle();
                    return true;
                }
            );

            GlobalKeyHook.Instance.SetProcessor(
                subtitleConf.GetKeys("Prev-Lrc", Keys.Control | Keys.Alt | Keys.D3),
                k =>
                {
                    if (PrevGroup())
                        parent.ShowNotice("字幕:" + CurrentGroup.Title);
                    return true;
                }
            );

            GlobalKeyHook.Instance.SetProcessor(
                subtitleConf.GetKeys("Next-Lrc", Keys.Control | Keys.Alt | Keys.D4),
                k =>
                {
                    if (NextGroup())
                        parent.ShowNotice("字幕:" + CurrentGroup.Title);
                    return true;
                }
            );
        }
        public BarrageManager(BarrageWindow parent, Size size, Configurations styleConf, Configurations actionConf)
        {
            renderer = new BarrageRenderer(styleConf);

            GlobalKeyHook.Instance.SetProcessor(
                styleConf.GetKeys("ReverseColor-Key", Keys.Control | Keys.Alt | Keys.W),
                k =>
                {
                    reverseColor = !reverseColor;
                    renderer.BorderColor = Color.FromArgb(
                        255 - renderer.BorderColor.R,
                        255 - renderer.BorderColor.G,
                        255 - renderer.BorderColor.B);
                    renderer.FillColor = Color.FromArgb(
                        255 - renderer.FillColor.R,
                        255 - renderer.FillColor.G,
                        255 - renderer.FillColor.B);

                    parent.ShowNotice(reverseColor ? "颜色:反色" : "颜色:正常");
                    return true;
                }
            );

            GlobalKeyHook.Instance.SetProcessor(
                styleConf.GetKeys("IncreaseAlpha-Key", Keys.Control | Keys.Alt | Keys.Oemplus),
                k =>
                {
                    float value = (float)Math.Round(renderer.Transparency + 0.1f, 1);
                    if (value > 1.0f)
                        value = 1.0f;
                    renderer.Transparency = value;
                    parent.ShowNotice("透明度:" + (renderer.Transparency * 100).ToString() + "%");
                    return true;
                }
            );

            GlobalKeyHook.Instance.SetProcessor(
                styleConf.GetKeys("DecreaseAlpha-Key", Keys.Control | Keys.Alt | Keys.OemMinus),
                k =>
                {
                    float value = (float)Math.Round(renderer.Transparency - 0.1f, 1);
                    if (value < 0.0f)
                        value = 0.0f;
                    renderer.Transparency = value;
                    parent.ShowNotice("透明度:" + (renderer.Transparency * 100).ToString() + "%");
                    return true;
                }
            );

            string style = styleConf.GetString("Style", "border-blur");
            switch (style)
            {
                case "border-blur":
                    this.barrageStyle = BarrageStyle.BorderBlur;
                    break;
                case "border":
                    this.barrageStyle = BarrageStyle.Border;
                    break;
                default:
                    this.barrageStyle = BarrageStyle.Shadow;
                    break;
            }
            this.barrageHeight = styleConf.GetInt("Height", 40);
            this.speed = actionConf.GetInt("Speed", 5);
            this.maxTime = actionConf.GetInt("Max-Time", 560);
            this.maxWait = actionConf.GetInt("Max-Wait", 100);
            this.maxRenderWait = actionConf.GetInt("Max-RenderWait", 500);
            this.maxCount = actionConf.GetInt("Max-Count", 200);
            this.maxLength = actionConf.GetInt("Max-Length", 40);

            this.size = size;
            barrageLines = new BarrageLine[size.Height / barrageHeight];
            for (int i = 0; i < barrageLines.Length; i++)
                barrageLines[i] = new BarrageLine(this);

            Visible = true;
        }