【问题标题】:AutoScroll mode doesn't hide scrollbar properlyAutoScroll 模式无法正确隐藏滚动条
【发布时间】:2015-07-10 03:07:18
【问题描述】:

我有一个Panel,当我点击添加Button 时,我在其他添加的控件下添加了一个Control。当我单击另一个 Button 时,我会删除最后添加的 Control
这工作正常。在该面板上,我将AutoScroll 设置设置为True,当我添加更多控件时,它会正确显示并且我可以使用它。当我删除某些控件时,Panel 会正确隐藏 ScrollBar ,前提是 ScrollBar 上的“动画”当时没有运行。

  1. 如果ScrollBar 上没有动画正在运行,它会正确消失 - 是否有鼠标悬停都没关系。
  2. 如果您将鼠标悬停在ScrollBar 上并快速移到删除Button 上并在ScrollBars 动画完成之前单击,则Control 将被删除,但不活动的ScrollBar 仍然存在。在Buttons 单击处理程序中,我尝试通过Panel 调用InvalidateUpdateRefresh 方法,但没有任何效果。

我只在 Windows 7 上测试过这个。

如果你不明白我的意思,请尝试看这个短片(20s 没有声音):http://youtu.be/-0EfRXrGbuc

【问题讨论】:

    标签: c# winforms windows-7 scrollbar


    【解决方案1】:

    您忘记发帖mcve。所以这里是一个(添加面板和两个按钮):

        private void button1_Click(object sender, EventArgs e)
        {
            panel1.Controls.Add(new Button() { Top = panel1.Controls.Count * 30 });
        }
    
        private void button2_Click(object sender, EventArgs e)
        {
            if (panel1.Controls.Count > 0)
                panel1.Controls.RemoveAt(panel1.Controls.Count - 1);
            panel1.Refresh();
        }
    

    我能够重现问题

    这是 winforms,宝贝 (c)。

    可能的解决方法是使用例如调用Refresh() Timer 或一些鼠标事件(它不会阻止问题,但使用将很容易通过例如将鼠标移动到 panel1 中来修复它)或者您可以在 panel1.MouseLeave 之后将删除按钮本身的可能性推迟一小段时间。所有这些变通方法。

    【讨论】:

      【解决方案2】:

      我希望有更好的方法,但现在我没有看到,所以基于answer from Sinatr我决定使用Timer并结合检查像素Color来确定ScrollBar仍然可见。

      private Timer _timer = new Timer {Interval = 500};
      
      public Form1()
      {
          InitializeComponent();
          _timer.Tick += TimerOnTick;
      }
      
      private void button2_Click(object sender, EventArgs e)
      {
          if (panel1.Controls.Count > 0)
          {
              var wasVisible = panel1.VerticalScroll.Visible;
              panel1.Controls.RemoveAt(panel1.Controls.Count - 1);
              buttons.RemoveAt(buttons.Count - 1);
      
              if (wasVisible != panel1.VerticalScroll.Visible)
              {
                  _timer.Start();
              }
          }
      }
      
      private bool IsBackgroundColor()
      {
          var point = panel1.Location;
          point.Offset(panel1.Width - 9, panel1.Height - 11);
          point = PointToScreen(point);
      
          Image imgScreen = new Bitmap(1, 1);
          using (Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format32bppArgb))
          using (Graphics g = Graphics.FromImage(bmp))
          using (Graphics gr = Graphics.FromImage(imgScreen))
          {
              g.CopyFromScreen(point, new Point(0, 0), new Size(1, 1));
              gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
              gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
              gr.DrawImage(bmp, new Rectangle(0, 0, 1, 1));
      
              var color = bmp.GetPixel(0, 0);
              return color.R == panel1.BackColor.R && color.G == panel1.BackColor.G && color.B == panel1.BackColor.B;
          }
      }
      
      private void TimerOnTick(object sender, EventArgs eventArgs)
      {
          if (!IsBackgroundColor() && !panel1.VerticalScroll.Visible)
          {
              panel1.Refresh();
          }
          else
          {
              _timer.Stop();
          }
      }
      

      我无法使用Panel.DrawToBitmap,因为它不会绘制ScrollBars。我也只在ScrollBar 可见时才启动Timer,现在不应该。
      重要的是要提到像素 Color 仅当您知道 Color 时才可能进行检查,如果 ScrollBar 隐藏,则该像素应该存在。不必一定是Panel.BackColor

      【讨论】:

      • IsBackgroundColor 对我来说似乎有些矫枉过正。也许您可以确定滚动条是否可见 somehow 不同?
      • 很遗憾没有,因为Panel.VerticalScroll.Visible 设置正确,我使用该行为来检查ScrollBar 是否应该可见。
      猜你喜欢
      • 1970-01-01
      • 2015-10-29
      • 1970-01-01
      • 1970-01-01
      • 2020-04-25
      • 2013-03-01
      • 2014-04-07
      相关资源
      最近更新 更多