Rendering controls on glass: Solution found, needs double-buffering/perfecting

后端 未结 2 671
梦谈多话
梦谈多话 2021-01-30 05:16

I (finally!) found a way of rendering Windows.Forms controls on glass that doesn\'t seem to have any major drawback nor any big implementation time. It\'s inspired by this artic

相关标签:
2条回答
  • 2021-01-30 05:43

    I had a problem with flickering before (lots of controls on the form, user controls). Tried almost everything. This is what worked for me:

    Have you tried putting this in your form class?

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000; // WS_EX_COMPOSITED
                cp.ExStyle |= 0x00080000; // WS_EX_LAYERED
                return cp;
            }
        }
    

    And in your constructor you have to enable double buffering, otherwise it won't work:

    this.DoubleBuffered = true;
    this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    

    It only works when aero is enabled, if not it can make flickering even worse.

    and you can also add this

      protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
    
                    cp.ExStyle |= 0x02000000; // WS_EX_COMPOSITED
                return cp;
            }
        } 
    

    to your UserControls class.

    0 讨论(0)
  • 2021-01-30 05:56

    Here is a version with much less flickering, still not perfect though.

    public class GlassControlRenderer : NativeWindow
    {
        private Control Control;
        private Bitmap Bitmap;
        private Graphics ControlGraphics;
    
        private object Lock = new object();
    
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case 0x14: // WM_ERASEBKGND
                    this.CustomPaint();
                    break;
    
                case 0x0F: // WM_PAINT
                case 0x85: // WM_NCPAINT
    
                case 0x100: // WM_KEYDOWN
                case 0x101: // WM_KEYUP
                case 0x102: // WM_CHAR
    
                case 0x200: // WM_MOUSEMOVE
                case 0x2A1: // WM_MOUSEHOVER
                case 0x201: // WM_LBUTTONDOWN
                case 0x202: // WM_LBUTTONUP
                case 0x285: // WM_IME_SELECT
    
                case 0x300: // WM_CUT
                case 0x301: // WM_COPY
                case 0x302: // WM_PASTE
                case 0x303: // WM_CLEAR
                case 0x304: // WM_UNDO
                    base.WndProc(ref m);
                    this.CustomPaint();
                    break;
    
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
    
        private Point Offset { get; set; }
    
        public GlassControlRenderer(Control control, int xOffset, int yOffset)
        {
            this.Offset = new Point(xOffset, yOffset);
            this.Control = control;
            this.Bitmap = new Bitmap(this.Control.Width, this.Control.Height);
            this.ControlGraphics = Graphics.FromHwnd(this.Control.Handle);
            this.AssignHandle(this.Control.Handle);
        }
    
        public void CustomPaint()
        {
            this.Control.DrawToBitmap(this.Bitmap, new Rectangle(0, 0, this.Control.Width, this.Control.Height));
            this.ControlGraphics.DrawImageUnscaled(this.Bitmap, this.Offset); // -1, -1 for content controls (e.g. TextBox, ListBox)
        }
    }
    
    0 讨论(0)
提交回复
热议问题