Pregunta

Estoy tratando de implementar una vista de lista dibujada por el propietario porque el control base come el carácter de pestaña que necesito para alinear los valores dentro de una columna.

Usando un ejemplo de MSDN Como base pude acercarme. El único problema que todavía tengo es que los períodos de elipsis utilizados cuando el texto no cabe en la columna está mucho más espaciado que en la representación de texto predeterminada; el punto de que si la fuente es audaz, los períodos se ejecutan en un bajo.

El siguiente programa demuestra el problema. Tiene 4 Vistas de ListVis: los dos en la parte superior se dibujan utilizando la representación predeterminada. Los dos en la parte inferior son propietarios, y el par en el lado derecho está en negrita. Por razones de longitud, eliminé todo lo que no necesitaba para demostrar el problema, por lo que las vistas de ListDawn de propietarios no tienen encabezados de columna.

Mirando un zoom en captura de pantalla, los períodos de los ellipsis en el propietario dibujado ListViews están separados un píxel; Aquellos en el dibujo predeterminado tienen dos píxeles de espaciado. Cuando el negrita amplía los períodos a dos píxeles, el propietario dibujó los fusionados en una masa sólida que parece un bajo.

También hay otras diferencias menores en la representación de texto; Pero el elipsis es el único que es evidente sin zoom. Sin embargo, estas diferencias me hacen sospechar que el problema es un problema más general. ¿Posiblemente GDI vs GDI+ Rendering? Excepto que pensé que solo podía variar en el nivel de aplicación. Aparentemente no, alternando Application.SetCompatibleTextRenderingDefault() no afectó nada.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public class Form1 : Form
    {
        private void ListViewDrawSubItem(object sender, DrawListViewSubItemEventArgs e)
        {
            ListView listView = sender as ListView;
            using (StringFormat sf = new StringFormat())
            {
                // Draw the standard background.
                e.DrawBackground();
                sf.SetTabStops(0, new float[] {12, 12, 12, 12, 12});
                sf.FormatFlags = sf.FormatFlags | StringFormatFlags.NoWrap;
                sf.Trimming = StringTrimming.EllipsisCharacter;

                // Draw the header text.
                // passing the controls font directly causes an ArguementException);
                using (Font headerFont = new Font(listView.Font.Name, listView.Font.Size, listView.Font.Style))
                {
                    e.Graphics.DrawString(e.SubItem.Text, headerFont, Brushes.Black, e.Bounds, sf);
                }
            }
        }

        public Form1()
        {
            InitializeComponent();
            LoadData(listView1);
            LoadData(listView2);
            LoadData(listView3);
            LoadData(listView4);
        }

        private void LoadData(ListView listView)
        {
            listView.Columns.Add("first", 35);
            listView.Columns.Add("second", 75);

            for (int i = 0; i < 5; i++)
            {
                listView.Items.Add("test");
                listView.Items[i].SubItems.Add("test test test test");
            }
        }

        #region from Form1.Designer
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.listView1 = new System.Windows.Forms.ListView();
            this.listView2 = new System.Windows.Forms.ListView();
            this.listView3 = new System.Windows.Forms.ListView();
            this.listView4 = new System.Windows.Forms.ListView();
            this.SuspendLayout();
            // 
            // listView1
            // 
            this.listView1.Location = new System.Drawing.Point(12, 12);
            this.listView1.Name = "listView1";
            this.listView1.Size = new System.Drawing.Size(121, 116);
            this.listView1.TabIndex = 0;
            this.listView1.UseCompatibleStateImageBehavior = false;
            this.listView1.View = System.Windows.Forms.View.Details;
            // 
            // listView2
            // 
            this.listView2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.listView2.Location = new System.Drawing.Point(151, 12);
            this.listView2.Name = "listView2";
            this.listView2.Size = new System.Drawing.Size(121, 116);
            this.listView2.TabIndex = 1;
            this.listView2.UseCompatibleStateImageBehavior = false;
            this.listView2.View = System.Windows.Forms.View.Details;
            // 
            // listView3
            // 
            this.listView3.Location = new System.Drawing.Point(12, 134);
            this.listView3.Name = "listView3";
            this.listView3.OwnerDraw = true;
            this.listView3.Size = new System.Drawing.Size(121, 116);
            this.listView3.TabIndex = 2;
            this.listView3.UseCompatibleStateImageBehavior = false;
            this.listView3.View = System.Windows.Forms.View.Details;
            this.listView3.DrawSubItem += new System.Windows.Forms.DrawListViewSubItemEventHandler(this.ListViewDrawSubItem);
            // 
            // listView4
            // 
            this.listView4.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.listView4.Location = new System.Drawing.Point(151, 134);
            this.listView4.Name = "listView4";
            this.listView4.OwnerDraw = true;
            this.listView4.Size = new System.Drawing.Size(121, 116);
            this.listView4.TabIndex = 3;
            this.listView4.UseCompatibleStateImageBehavior = false;
            this.listView4.View = System.Windows.Forms.View.Details;
            this.listView4.DrawSubItem += new System.Windows.Forms.DrawListViewSubItemEventHandler(this.ListViewDrawSubItem);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 262);
            this.Controls.Add(this.listView4);
            this.Controls.Add(this.listView3);
            this.Controls.Add(this.listView2);
            this.Controls.Add(this.listView1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.ListView listView1;
        private System.Windows.Forms.ListView listView2;
        private System.Windows.Forms.ListView listView3;
        private System.Windows.Forms.ListView listView4;
        #endregion

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}
¿Fue útil?

Solución

Encontré una implementación contingente para el método Draw Subemem. Las principales advertencias que tengo son que el tamaño de la pestaña es fijo (aunque podría caer a Win32 si es necesario para cambiarlo); y que la combinación de banderas que necesito mientras trabajo en mi máquina se informa que es mutuamente incompatible en MSDN.

private void ListViewDrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    //toggle colors if the item is highlighted 
    if (e.Item.Selected && e.Item.ListView.Focused)
    {
        e.SubItem.BackColor = SystemColors.Highlight;
        e.SubItem.ForeColor = e.Item.ListView.BackColor;
    }
    else if (e.Item.Selected && !e.Item.ListView.Focused)
    {
        e.SubItem.BackColor = SystemColors.Control;
        e.SubItem.ForeColor = e.Item.ListView.ForeColor;
    }
    else
    {
        e.SubItem.BackColor = e.Item.ListView.BackColor;
        e.SubItem.ForeColor = e.Item.ListView.ForeColor;
    }

    // Draw the standard header background.
    e.DrawBackground();

    //add a 2 pixel buffer the match default behavior
    Rectangle rec = new Rectangle(e.Bounds.X + 2, e.Bounds.Y+2, e.Bounds.Width - 4, e.Bounds.Height-4);

    //TODO  Confirm combination of TextFormatFlags.EndEllipsis and TextFormatFlags.ExpandTabs works on all systems.  MSDN claims they're exclusive but on Win7-64 they work.
    TextFormatFlags flags = TextFormatFlags.Left | TextFormatFlags.EndEllipsis | TextFormatFlags.ExpandTabs | TextFormatFlags.SingleLine;

    //If a different tabstop than the default is needed, will have to p/invoke DrawTextEx from win32.
    TextRenderer.DrawText(e.Graphics, e.SubItem.Text, e.Item.ListView.Font, rec, e.SubItem.ForeColor, flags);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top