bool IEquatable <BufferedPaintTransition <TState> > .Equals(BufferedPaintTransition <TState> other)
 {
     return(Object.Equals(this.FromState, other.FromState) && Object.Equals(this.ToState, other.ToState));
 }
        void Control_Paint(object sender, PaintEventArgs e)
        {
            if (BufferedPaintSupported && Enabled)
            {
                bool stateChanged = !Object.Equals(_currentState, _newState);

                IntPtr hdc = e.Graphics.GetHdc();
                if (hdc != IntPtr.Zero)
                {
                    // see if this paint was generated by a soft-fade animation
                    if (!Interop.BufferedPaintRenderAnimation(Control.Handle, hdc))
                    {
                        Interop.BP_ANIMATIONPARAMS animParams = new Interop.BP_ANIMATIONPARAMS();
                        animParams.cbSize = Marshal.SizeOf(animParams);
                        animParams.style  = Interop.BP_ANIMATIONSTYLE.BPAS_LINEAR;

                        // get appropriate animation time depending on state transition (or 0 if unchanged)
                        animParams.dwDuration = 0;
                        if (stateChanged)
                        {
                            BufferedPaintTransition <TState> transition = Transitions.Where(x => Object.Equals(x.FromState, _currentState) && Object.Equals(x.ToState, _newState)).SingleOrDefault();
                            animParams.dwDuration = (transition != null) ? transition.Duration : DefaultDuration;
                        }

                        Rectangle rc = Control.ClientRectangle;
                        IntPtr    hdcFrom, hdcTo;
                        IntPtr    hbpAnimation = Interop.BeginBufferedAnimation(Control.Handle, hdc, ref rc, Interop.BP_BUFFERFORMAT.BPBF_COMPATIBLEBITMAP, IntPtr.Zero, ref animParams, out hdcFrom, out hdcTo);
                        if (hbpAnimation != IntPtr.Zero)
                        {
                            if (hdcFrom != IntPtr.Zero)
                            {
                                using (Graphics g = Graphics.FromHdc(hdcFrom)) {
                                    OnPaintVisualState(new BufferedPaintEventArgs <TState>(_currentState, g));
                                }
                            }
                            if (hdcTo != IntPtr.Zero)
                            {
                                using (Graphics g = Graphics.FromHdc(hdcTo)) {
                                    OnPaintVisualState(new BufferedPaintEventArgs <TState>(_newState, g));
                                }
                            }

                            _currentState = _newState;
                            Interop.EndBufferedAnimation(hbpAnimation, true);
                        }
                        else
                        {
                            OnPaintVisualState(new BufferedPaintEventArgs <TState>(_currentState, e.Graphics));
                        }
                    }

                    e.Graphics.ReleaseHdc(hdc);
                }
            }
            else
            {
                // buffered painting not supported, just paint using the current state
                _currentState = _newState;
                OnPaintVisualState(new BufferedPaintEventArgs <TState>(_currentState, e.Graphics));
            }
        }