web-dev-qa-db-ja.com

C#リストビューのアイテム/行の高さを変更する

リストビューでアイテム/行の高さを変更したい。

私はあらゆる場所を検索しましたが、高さを変更するにはLBS_OWNERDRAWFIXEDまたはMeasureItemまたはそのようなもの。

問題は、私が何をすべきか、そしてそれをどのように使うのか正確に知らないことです.
誰かが私を助けてくれますか?

編集:
実際にSmallImageListを使用しており、ImageList画像サイズとは異なる行の高さが必要なため、ImageListハックを使用できません。

ありがとう!

20
Ron

これは、SmallImageListトリックを使用して実行できます。注意が必要です。 ObjectListView -標準.NETのオープンソースラッパーListView-そのトリックを使用してRowHeightプロパティを正常に実装します。

各行に32ピクセルが必要な場合は、ImageListを16x32(幅x高さ)に割り当て、各画像を32ピクセルの高さの垂直方向の中央に配置します。

次のスクリーンショットは、32ピクセルの行と、余分なスペースのために可能な折り返しを示しています。

enter image description here

ObjectListViewがすべての作業を行います。実際、ListViewで何かを実行しようとしている場合は、代わりにObjectListViewを使用することを真剣に検討する必要があります。これにより、多くの難しいこと(列の種類、カスタムツールチップなどによる並べ替え)が簡単になり、いくつかの不可能なこと(たとえば、オーバーレイ、仮想リスト上のグループ)が可能になります。

14
Grammarian

まだこれで苦労している人々のために、ここに私が使用するコードがあります:

private void SetHeight(ListView listView, int height)
{
    ImageList imgList = new ImageList();
    imgList.ImageSize = new Size(1, height);
    listView.SmallImageList = imgList;
}

これを使用するには、次のようにします。

SetHeight(lvConnections, 25);
25
Maarten Peels

あなたは少しハックを使わなければなりません。トリックは、StateImageListプロパティで画像リストを使用することです。 ListViewは、ImageListのImageSizeプロパティの高さに基づいて、アイテムの高さを調整します。アイテムの画像を指定する必要はありませんが、StateImageListを使用するだけでListViewが調整されます。以下の例では、画像リストのサイズを32x32に設定しているため、高さが32pxのListViewItemになります。

enter image description here

15
David Anderson

悲しいことに、ここ何年にもわたってLBS_OWNERDRAWFIXEDの使い方についての元の質問にだれも回答していません。

あなたが受け入れた答えは、巨大なプロジェクトを統合することです(デモとドキュメントを含む3,3MB)。しかし、ListViewの行の高さを設定するためだけに、これは誇張されています。

ここで提案されている他の回避策(ImageListの追加)は、行の高さをincreaseする場合にのみ機能します。ただし、画像の高さに関係なくRowHeightを実際に設定することはできません。また、デフォルトの行の高さはオペレーティングシステムによって異なります。たとえば、Windows 7では、行はXPよりもはるかに高くなります。あなたはそれらをより強くすることを選択することはできません、より高いだけです。

しかし、ほんの数行で、あなたはあなたが望むことをすることができます。次のクラスをコピーして貼り付けるだけです。

using System;
using System.Drawing;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ExtendedControls
{

public class ListViewEx : ListView
{
    #region Windows API

    /*
    struct MEASUREITEMSTRUCT 
    {
        public int    CtlType;     // Offset = 0
        public int    CtlID;       // Offset = 1
        public int    itemID;      // Offset = 2
        public int    itemWidth;   // Offset = 3
        public int    itemHeight;  // Offset = 4
        public IntPtr itemData;
    }
    */

    [StructLayout(LayoutKind.Sequential)]
    struct DRAWITEMSTRUCT
    {
        public int    ctlType;
        public int    ctlID;
        public int    itemID;
        public int    itemAction;
        public int    itemState;
        public IntPtr hWndItem;
        public IntPtr hDC;
        public int    rcLeft;
        public int    rcTop;
        public int    rcRight;
        public int    rcBottom;
        public IntPtr itemData;
    }

    // LVS_OWNERDRAWFIXED: The owner window can Paint ListView items in report view. 
    // The ListView control sends a WM_DRAWITEM message to Paint each item. It does not send separate messages for each subitem. 
    const int LVS_OWNERDRAWFIXED = 0x0400;
    const int WM_SHOWWINDOW      = 0x0018;
    const int WM_DRAWITEM        = 0x002B;
    const int WM_MEASUREITEM     = 0x002C;
    const int WM_REFLECT         = 0x2000;

    #endregion

    bool mb_Measured = false;
    int  ms32_RowHeight = 14;

    /// <summary>
    /// Constructor
    /// </summary>
    public ListViewEx()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
    }

    /// <summary>
    /// Sets the row height in Details view
    /// This property appears in the Visual Studio Form Designer
    /// </summary>
    [Category("Appearance")]  
    [Description("Sets the height of the ListView rows in Details view in pixels.")] 
    public int RowHeight
    {
        get { return ms32_RowHeight; }
        set 
        { 
            if (!DesignMode) Debug.Assert(mb_Measured == false, "RowHeight must be set before ListViewEx is created.");
            ms32_RowHeight = value; 
        }
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams k_Params = base.CreateParams;
            k_Params.Style |= LVS_OWNERDRAWFIXED;
            return k_Params;
        }
    }

    /// <summary>
    /// The messages WM_MEASUREITEM and WM_DRAWITEM are sent to the parent control rather than to the ListView itself.
    /// They come here as WM_REFLECT + WM_MEASUREITEM and WM_REFLECT + WM_DRAWITEM
    /// They are sent from Control.WmOwnerDraw() --> Control.ReflectMessageInternal()
    /// </summary>
    protected override void WndProc(ref Message k_Msg)
    {
        base.WndProc(ref k_Msg); // FIRST

        switch (k_Msg.Msg)
        {
            case WM_SHOWWINDOW: // called when the ListView becomes visible
            {
                Debug.Assert(View == View.Details, "ListViewEx supports only Details view");
                Debug.Assert(OwnerDraw == false,   "In ListViewEx do not set OwnerDraw = true");
                break;
            }
            case WM_REFLECT + WM_MEASUREITEM: // called once when the ListView is created, but only in Details view
            {
                mb_Measured = true;

                // Overwrite itemHeight, which is the fifth integer in MEASUREITEMSTRUCT 
                Marshal.WriteInt32(k_Msg.LParam + 4 * sizeof(int), ms32_RowHeight);
                k_Msg.Result = (IntPtr)1;
                break;
            }
            case WM_REFLECT + WM_DRAWITEM: // called for each ListViewItem to be drawn
            {
                DRAWITEMSTRUCT k_Draw = (DRAWITEMSTRUCT) k_Msg.GetLParam(typeof(DRAWITEMSTRUCT));
                using (Graphics i_Graph = Graphics.FromHdc(k_Draw.hDC))
                {
                    ListViewItem i_Item = Items[k_Draw.itemID];

                    Color c_BackColor = i_Item.BackColor;
                    if (i_Item.Selected) c_BackColor = SystemColors.Highlight;
                    if (!Enabled)        c_BackColor = SystemColors.Control;

                    using (SolidBrush i_BackBrush = new SolidBrush(c_BackColor))
                    {
                        // Erase the background of the entire row
                        i_Graph.FillRectangle(i_BackBrush, i_Item.Bounds);
                    }

                    for (int S=0; S<i_Item.SubItems.Count; S++)
                    {
                        ListViewItem.ListViewSubItem i_SubItem = i_Item.SubItems[S];

                        // i_Item.SubItems[0].Bounds contains the entire row, rather than the first column only.
                        Rectangle k_Bounds = (S>0) ? i_SubItem.Bounds : i_Item.GetBounds(ItemBoundsPortion.Label);

                        // You can use i_Item.ForeColor instead of i_SubItem.ForeColor to get the same behaviour as without OwnerDraw
                        Color c_ForeColor = i_SubItem.ForeColor;
                        if (i_Item.Selected) c_ForeColor = SystemColors.HighlightText;
                        if (!Enabled)        c_ForeColor = SystemColors.ControlText;

                        TextFormatFlags e_Flags = TextFormatFlags.NoPrefix | TextFormatFlags.EndEllipsis | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine;
                        switch (Columns[S].TextAlign)
                        {
                            case HorizontalAlignment.Center: e_Flags |= TextFormatFlags.HorizontalCenter; break;
                            case HorizontalAlignment.Right:  e_Flags |= TextFormatFlags.Right; break;
                        }

                        TextRenderer.DrawText(i_Graph, i_SubItem.Text, i_SubItem.Font, k_Bounds, c_ForeColor, e_Flags);
                    }
                }
                break;
            }
        }
    }
} // class
} // namespace

ListViewExをフォームに追加すると、行の高さをピクセル単位で設定できる新しいプロパティがVisual Studioフォームデザイナに表示されます。

Setting RowHeight in a C# ListView

ここに入力する値は行の高さ(ピクセル単位)であり、すべてのオペレーティングシステムでそのまま尊重されます。 Windows XP、7、10でテストしました。

ListViewEx.RowHeight sample

さらに、私のクラスには、元のListViewよりも2つの利点があります。それはflicker-freeを描画し、ForeColorおよびFontListViewSubItemに設定され、元のMicrosoft ListViewでは無視されます。したがって、各セルを異なる色とフォントで描画できます。

重要:MSDNが言うように、LBS_OWNERDRAWFIXEDのみ設計されています詳細ビュー(レポートビュー)の場合。私のコードはこのモードでのみ機能します。これは、Microsoftがそのように設計したためです。

さらに、ListView.OwnerDraw = trueの設定はLVS_OWNERDRAWFIXEDの使用とはまったく異なることに注意してください。

描画iconsを実装しませんでした。必要ないからです。しかし、これは簡単に追加できます。

4
Elmue

ListView(レポートビューモード)のデフォルトの行の高さは、コントロールのフォントサイズに基づいて計算されます。

したがって、行の高さを選択するには、ListViewプロパティで適切な高さのフォントを選択します。たとえば、MS Sans Serif 18を選択します。

次に、すべてのアイテムで使用されるフォントを変更できます。新しいアイテムを挿入するときに、そのフォントプロパティを設定します。

フォントの割り当てを最適化するには、アイテムのフォントをフォームのプライベートメンバーとして宣言する必要があります。

Private Font stdfont = new Font( "Consolas", 9.0f, FontStyle.Regular );

次に、アイテムを追加するとき:

ListViewItem i = new ListViewItem( "some text" );
i.Font = stdfont;
MyListView.Items.Add( i );

このトリックは、行の高さを小さくできる唯一の簡単な方法です;)i.E.コントロールのフォントサイズを7に設定し、アイテムのフォントサイズを10に設定します(VS 2008でテスト済み)

3
Plasmabubble

プラズマバブルは正しい考えを持っています。これはそれを拡張したものであり、私はアイテムに狭い線幅を使用するために使用しています。

ListViewの行間はListViewのフォントに依存しており、変更できません。ただし、ListViewの項目のフォントを、ListViewのフォントよりも大きい値に設定できます。

プロポーショナルにする場合は、アイテムのフォントに基づいてフォントを作成します。選択したフォントに関係なく、アイテムの高さを通常の90%にする必要があります。

リストを作成するときは、設定に保存されているフォントを使用しましたが、「Consolas」などのリテラルフォントを使用することもできます。

lvResults.Font = 
   new Font(Properties.Settings.Default.usrHookFont.FontFamily, 
      (float)(Properties.Settings.Default.usrHookFont.Size * .9));

foreach (HookSet item in resultSet)
   {
      ListViewItem lvi = new ListViewItem();
      lvi.Font = Properties.Settings.Default.usrHookFont;
      <dot><dot><dot>
}
1
Dana Bell