【问题标题】:How do I implement scrolling for a Custom Control?如何实现自定义控件的滚动?
【发布时间】:2014-12-06 23:14:34
【问题描述】:

如何为我的自定义控件实现滚动?我的控件是完全自定义绘制的,它的高度是可变的,并且控件的一部分包含一个菜单,所以如果控件中有很多项目,我需要能够在那里放置滚动条。我真的找不到任何关于如何做到这一点的线索。我确实看到了一些关于 ScrollableControl 的信息,但我仍然不确定这是否是我需要的。

另外,我的控件如何知道何时需要显示滚动条?因为我的控件是完全自定义绘制的,所以那里没有真正的“控件”,它只是绘制在它上面的一堆像素,所以我不能只将 AutoScroll 设置为 true,我无论如何也不能这样做,因为它不是需要滚动的控件的主要部分,它是控件上需要滚动条的特定位置。

【问题讨论】:

    标签: c# .net winforms gdi+ gdi


    【解决方案1】:

    您可以将PanelAutoScroll = true 一起使用。之后,如果您在其中放置任何控件,只要它们的大小大于面板的大小,面板就会自动显示滚动条。该技巧也可以用于任何自定义控件,只要您放置它位于 AutoScroll 面板中,并根据需要调整大小。

    【讨论】:

      【解决方案2】:

      你有两个选择。

      好消息是它是可能的,而且两者都不是很难。

      • 坏消息是,对于一个选项,您必须调整所有绘图代码:

      首先做你的控制,我用Panel,有Autoscroll=true;

      那你需要添加一个dummy控件,我用另一个Panel,大概是这样,足够右下方强制ScrollBars显示:

      public Form1()
      {
          InitializeComponent();
      
          Panel panelDummy = new Panel();
          panelDummy.Size = new Size(1,1);
          panelDummy.Location = new Point(yourMaxX,yourMaxY);
          panel1.Controls.Add(panelDummy);
      }
      

      然后你需要调整你的绘图代码。方法如下:

      private void panel1_Paint(object sender, PaintEventArgs e)
      {
          int xx = panel1.HorizontalScroll.Value;
          int yy = panel1.VerticalScroll.Value;
      
          e.Graphics.FillRectangle(Brushes.Wheat, new Rectangle(11 - xx, 22 - yy, 22, 311));
          e.Graphics.FillRectangle(Brushes.RosyBrown, new Rectangle(11 - xx, 280 - yy, 22, 3));
      }
      
      private void panel1_Scroll(object sender, ScrollEventArgs e)
      {
          panel1.Invalidate();
      }
      

      我在Scroll 事件中添加了Invalidate,以避免弄乱绘画结果。

      • 另一个选项更简单:使您的控件足够大以容纳所有绘制的控件并将其放在 内部 PanelAutoScroll=true; 这会将整个滚动业务委托给包含面板。

      【讨论】:

        【解决方案3】:

        如果你的自定义控件继承自Panel控件,你只需通过这个设置自己在自定义控件中设置内容的大小:

        this.AutoScrollMinSize = New Size(yourWidth, yourHeight);
        

        如果您的控件的 ClientSize.Height 大于 yourHeight,您将不会看到任何滚动条。如果它更少,那么你会得到一个滚动条。

        在您的绘画方法中,将其添加到开头:

        protected override void OnPaint(PaintEventArgs e) {
          e.Graphics.TranslateTransform(this.AutoScrollPosition.X,
                                        this.AutoScrollPosition.Y);
        

        现在您绘制的所有内容都会自动转换为滚动坐标。

        【讨论】:

        • 谢谢,但不是控件的整个大小需要滚动,只有大约四分之一的控件需要滚动条。 (想想一个带有按钮的面板控件;您单击按钮然后弹出一个可滚动菜单)但是使用您的解决方案,整个控件将滚动,对吗?
        • @jay_t55 我专注于你的陈述:My control is fully custom drawn... 滚动的部分需要有自己的容器。
        • 您的问题解决了吗?如果有任何答案有用,您可能想接受它。
        • 这个答案没有用。是的,我的控件是完全自定义绘制的,但是,只有控件的一部分需要滚动。想想一个带有 iframe 的网页。你有一个标题(div)主体(包含一个滚动的 iframe)和页脚。页眉和页脚不会滚动,但 iframe 会滚动,因为它有很多内容。
        • @SE13013 然后为页眉、正文和页脚创建不同的面板,然后滚动页脚。桌面应用程序和 Web 应用程序是不同的野兽。
        【解决方案4】:

        我通过创建一个从 Control 继承并完全在 OnPaint 中绘制的自定义控件,部分解决了这个问题。到目前为止,我的解决方案是使用 ScrollBarRenderer 来绘制滚动按钮,然后为可滚动区域定义一个 Rectangle。然后我创建一个图像来绘制我的可滚动内容,并在使用 DrawImage 绘制到我创建的可滚动内容矩形之前使用 TranslateTransform 将该图像滚动到位。它显示出希望,虽然我还没有完全工作,因为我必须自己处理所有的 MouseOver 和 Click 事件。

        【讨论】:

          猜你喜欢
          • 2013-08-12
          • 2019-07-23
          • 2023-03-07
          • 2020-10-02
          • 1970-01-01
          • 1970-01-01
          • 2016-07-23
          • 2011-03-21
          • 1970-01-01
          相关资源
          最近更新 更多