Newer
Older
JumpListUtil / ShortcutUtil / ListBoxButton.cs
@Mark Mark on 18 Aug 2020 3 KB Way less flicker
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ShortcutUtil
{
    public class ListBoxEx : ListBox
    {
        private bool designMode;
        public ListBoxEx() : base()
        {
            designMode = System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime;
        }
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                if (!designMode)
                {
                    cp.ExStyle |= 0x02000000;  // Turn on WS_EX_COMPOSITED
                    cp.Style &= ~0x040;  // Turn off CS_CLASSDC
                }
                return cp;
            }
        }
    }

    public interface IListBoxControl
    {
        void Hover();
        void Unhover();
    }

    public class ListBoxButton : Button, IListBoxControl
    {
        public void Hover()
        {
            OnMouseDown(new MouseEventArgs(MouseButtons.Left, 0, 1, 1, 0));
        }
        public void Unhover()
        {
            OnMouseUp(new MouseEventArgs(MouseButtons.Left, 0, 1, 1, 0));
        }
    }

    public class ListBoxControl<T> where T : Control, IListBoxControl, new()
    {
        public T Control { get; private set; }
        private ListBox listBox;

        public int? IndexOver { get; private set; }

        public ListBoxControl(T control, ListBox listBox)
        {
            Control = control;
            this.listBox = listBox;
            listBox.MouseMove += ListBoxMouseMove;
        }

        public Rectangle BoundsInList(int index)
        {
            Point offsetLoc = listBox.GetItemRectangle(index).Location;
            offsetLoc.Offset(Control.Location);
            return new Rectangle(offsetLoc, Control.Size);
        }

        private void ListBoxMouseMove(object sender, MouseEventArgs e)
        {
            int? nowIndexOver = null;
            for (int i = 0; i < listBox.Items.Count; i++)
            {
                if (BoundsInList(i).Contains(e.X, e.Y))
                {
                    nowIndexOver = i;
                    break;
                }
            }

            if (nowIndexOver != IndexOver)
            {
                IndexOver = nowIndexOver;
                listBox.Invalidate();
            }
        }

        public void RenderToItem(int index, Graphics g)
        {
            using (Bitmap b = new Bitmap(Control.Size.Width, Control.Size.Height))
            {
                if (index == IndexOver)
                {
                    Control.Hover();
                }
                Control.DrawToBitmap(b, new Rectangle(new Point(), Control.Size));
                g.DrawImage(b, Control.Location.X, Control.Location.Y);
                if (index == IndexOver)
                {
                    Control.Unhover();
                }
            }
        }

    }
}