0

I am trying to resize evenly all the columns of a ListView and it works as it should, but the code I made is making the screen flash and blink too much...I wonder what may I fix on the code to make it run smoothly? Here is the code:

using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;

namespace Test_ListViews
{
    public partial class Form1 : Form
    {
        Double[] pesos;
        private bool resizing = false;
        private bool limpando = false; 

        public Form1()
        {
            InitializeComponent();

            int i = 0;

            float dx = 96;

            Graphics g = this.CreateGraphics();
            try
            {
                dx = g.DpiX;
            }
            finally
            {
                g.Dispose();
            }

            pesos = new Double[listView1.Columns.Count]; // usado para o resize das colunas da ListView ser proporcional.
            for (i = 0; i < listView1.Columns.Count; i++)
                pesos[i] = ((Double)listView1.Columns[i].Width * dx) / (listView1.Width * 96);
            _listView1_Resize();

            listView1.FullRowSelect = true;

            this.listView1.Resize += new System.EventHandler(this.listView1_Resize);
            this.listView1.ColumnWidthChanged += new System.Windows.Forms.ColumnWidthChangedEventHandler(this.listView1_ColumnWidthChanged);   
        }

        private void bntFill_Click(object sender, EventArgs e)
        {
            int i = 0;

            for (i = 0; i < 5; i++)
            {
                ListViewItem item = new ListViewItem("Test 1");
                item.SubItems.Add("Test 2");
                item.SubItems.Add("Test 3");
                item.SubItems.Add("Test 4");
                item.SubItems.Add("Test 5");
                item.SubItems.Add("Test 6");
                item.SubItems.Add("Test 7");
                item.SubItems.Add("Test 8");
                item.SubItems.Add("Test 9");
                listView1.Items.Add(item);
            }            

            SetWindowTheme(listView1.Handle, "Explorer", null);
        }

        [DllImport("uxtheme.dll")]
        public static extern int SetWindowTheme([In] IntPtr hwnd, [In, MarshalAs(UnmanagedType.LPWStr)] string pszSubAppName, [In, MarshalAs(UnmanagedType.LPWStr)] string pszSubIdList);

        private void btnDelete_Click(object sender, EventArgs e)
        {
            ArrayList list = new ArrayList();

            foreach(ListViewItem item in listView1.SelectedItems )
            {
                list.Add(item);
            }

            foreach (ListViewItem item in list)
            {
                listView1.Items.Remove(item);
            }
        }

        private void listView1_Resize(object sender, System.EventArgs e)
        {
            _listView1_Resize();
        }
        private void _listView1_Resize()
        {
            if (resizing == false && pesos != null)
            {
                resizing = true;

                Int32 largura = listView1.Width;
                int i = 0;


                for (i = 0; i < listView1.Columns.Count; i++)
                {
                    listView1.Columns[i].Width = Convert.ToInt32(pesos[i] * largura);
                }

                if (listView1.Controls.Count > 0)
                {
                    Int32 x = listView1.Items[0].SubItems[listView1.Items[0].SubItems.Count - 1].Bounds.Location.X + 3;//pegando a referencia da ultima coluna.

                    for (i = 0; i < listView1.Controls.Count; i++)
                    {
                        listView1.Controls[i].Location = new System.Drawing.Point(x, listView1.Controls[i].Location.Y);
                        listView1.Controls[i].Width = listView1.Columns[listView1.Columns.Count - 1].Width - 9;
                    }
                }

                if (listView1.Items.Count > 8)
                {
                    listView1.Columns[listView1.Columns.Count - 1].Width -= 10;
                }

                listView1.Scrollable = false;
                listView1.Scrollable = true;

                resizing = false;
            }

            SetWindowTheme(listView1.Handle, "Explorer", null);

        }

        private void listView1_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
        {
            _listView1_Resize();
            //int i = 0;
            //for (i = 0; i < listView1.Columns.Count; i++)
            //{
            //    if (listView1.Columns[i].Width < 20)
            //        listView1.Columns[i].Width = 20;
            //} 
        }

    }     
}

Thanks!!

Michel Feinstein
  • 13,416
  • 16
  • 91
  • 173

1 Answers1

1

At the start of the resizing operation call listView1.BeginUpdate() and then call listView1.EndUpdate() when you're finished

This way windows won't redraw the control every time a change is made to it, or any of it's children and will redraw them all once when you call EndUpdate()

Ben Stephens
  • 563
  • 3
  • 8
  • Woow! Much better, thank you Ben! It still has a little bit of blinking going on, but I guess its expected right? Or may I improve it even more? – Michel Feinstein Aug 12 '12 at 00:36
  • You're definitely calling those outside of any loops at the very beginning and end of any operations? It should only really be one blink and then it just looks like new... If you're still holding down the mouse and dragging and it's redrawing during the resize that'd look like blinking for each time the resize event gets called in the app I guess? Take a look at the following stack overflow question, specially around the SetStyle stuff, whether you enable double buffering or turn off drawing during resize though up to you – Ben Stephens Aug 12 '12 at 02:09
  • Yes, I am holding the mouse down and dragging the screen so the resize event is getting called...which "following stack overflow question" are you mentioning? – Michel Feinstein Aug 12 '12 at 03:44
  • http://stackoverflow.com/questions/4690426/why-do-my-winforms-controls-flicker-and-resize-slowly sorry forgot to paste :) – Ben Stephens Aug 12 '12 at 05:43
  • Is that the best way? I mean, it is better than the horrible lag, but it is still not optimal, because users cannot see if the texts are no longer clipped, which is necessary to determine how much they should resize the column. I cannot believe with all the CPU power and RAM of a modern computer, this stupid ListView cannot even resize a column of texts smoothly. – Damn Vegetables Mar 20 '19 at 06:32