代码之家  ›  专栏  ›  技术社区  ›  WildCrustacean

在不使用子类化面板的情况下禁用onpaintbackground?

  •  3
  • WildCrustacean  · 技术社区  · 14 年前

    是否有任何方法可以在不使用子类化面板和覆盖paintbackground的情况下禁用面板的擦除?

    我试图在不使用子类面板的情况下实现双重缓冲效果。我知道这可能是一件很奇怪的事情,但我至少想知道我是否能做到。下面的代码示例说明了这一点:

    public partial class Form1 : Form
    {
        private Bitmap m_image;
    
        public Form1()
        {
            InitializeComponent();
    
            panel1.Paint += new PaintEventHandler(panel1_Paint);
            panel1.MouseMove += new MouseEventHandler(panel1_MouseMove);
    
            m_image = new Bitmap(panel1.Width, panel1.Height);
        }
    
        void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            using (Graphics g = Graphics.FromImage(m_image))
            {
                g.FillEllipse(Brushes.Black, new Rectangle(e.X, e.Y, 10, 10));
            }
            panel1.Invalidate();
        }
    
        void panel1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(m_image, 0, 0);
        }
    }
    

    这会导致闪烁,可能是因为它会在每个绘制周期中擦除面板。

    3 回复  |  直到 10 年前
        1
  •  4
  •   Hans Passant    14 年前

    您可以对paintbackground()进行黑客攻击,也可以对wndproc()进行黑客攻击。两者都需要派生自己的类。这是微不足道的,我只是不明白你为什么要回避它。长距离拍摄的是setWindowsHookEx()和一个wh-callWndProc钩子,真的太傻了。

        2
  •  0
  •   tshepang Arrie    11 年前

    只需添加:

    panel1.BackgroundImage = m_image;
    //on panel1_Paint() function.
    

    很简单,不是吗?

        3
  •  0
  •   sjh2014    10 年前

    使用反射设置受保护的DoubleBuffered属性:

    System.Reflection.PropertyInfo aProp =
             typeof(System.Windows.Forms.Control).GetProperty(
                   "DoubleBuffered",
                   System.Reflection.BindingFlags.NonPublic |
                   System.Reflection.BindingFlags.Instance);
    
    aProp.SetValue(panel1, true, null);
    

    您也可以通过只使更改的区域无效来提高效率(即使没有双缓冲,这几乎是无闪烁的):

    void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        Rectangle r = new Rectangle(e.X, e.Y, 10, 10);
        using (Graphics g = Graphics.FromImage(m_image))
        {
            g.FillEllipse(Brushes.Black, r);
        }
        panel1.Invalidate(r);
    }