示例#1
0
        public static void HandleWmPaint(ref Message m, Control control, Action <PaintEventArgs> paint)
        {
            var  ps            = new WinApi.PAINTSTRUCT();
            bool needDisposeDc = false;

            try {
                Rectangle clip;
                IntPtr    dc;
                if (m.WParam == IntPtr.Zero)
                {
                    dc = WinApi.BeginPaint(new HandleRef(control, control.Handle), ref ps);
                    if (dc == IntPtr.Zero)
                    {
                        return;
                    }
                    needDisposeDc = true;
                    clip          = new Rectangle(ps.rcPaint_left, ps.rcPaint_top, ps.rcPaint_right - ps.rcPaint_left, ps.rcPaint_bottom - ps.rcPaint_top);
                }
                else
                {
                    dc   = m.WParam;
                    clip = control.ClientRectangle;
                }

                if (clip.Width > 0 && clip.Height > 0)
                {
                    try {
                        using (var bufferedGraphics = BufferedGraphicsManager.Current.Allocate(dc, control.ClientRectangle)) {
                            bufferedGraphics.Graphics.SetClip(clip);
                            using (var pevent = new PaintEventArgs(bufferedGraphics.Graphics, clip)) {
                                paint?.Invoke(pevent);
                            }
                            bufferedGraphics.Render();
                        }
                    } catch (Exception ex) {
                        // BufferContext.Allocate will throw out of memory exceptions
                        // when it fails to create a device dependent bitmap while trying to
                        // get information about the device we are painting on.
                        // That is not the same as a system running out of memory and there is a
                        // very good chance that we can continue to paint successfully. We cannot
                        // check whether double buffering is supported in this case, and we will disable it.
                        // We could set a specific string when throwing the exception and check for it here
                        // to distinguish between that case and real out of memory exceptions but we
                        // see no reasons justifying the additional complexity.
                        if (!(ex is OutOfMemoryException))
                        {
                            throw;
                        }
                    }
                }
            } finally {
                if (needDisposeDc)
                {
                    WinApi.EndPaint(new HandleRef(control, control.Handle), ref ps);
                }
            }
        }