2024年5月
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
無料ブログはココログ

 

« 今さらだけど、今期の新作アニメの感想 | トップページ | ブログネタ: 異性の仕草や言葉で、幻滅するものは何? »

2010年2月 7日 (日)

仮想ListViewでIconを表示できたけど・・・

前回「仮想ListViewでIconを表示させるのは諦めたらあかん!」の続き。
いろいろやってみて仮想モードでもIconを表示できたけど、問題山積みで解決できず力尽きた。
右が仮想リストビュー、左が通常のリストビュー。

Listviewtest1

でも、いくつも問題があって使い物にならない。

  • ちらつきが酷い
  • 一番下までスクロースさせると、最後の項目のさらに下に隙間ができると、そこにIconが表示されてしまう
  • スクロールバーの上下ボタン(▲▼)を押してスクロールすると、ずれたIconが表示されて消えない。
  • これらを何とかしようとすると、RetrieveVirtualItemイベントの中でListViewのItemsとかのプロパティ値を見たいのだけれど、そうするとRetrieveVirtualItemイベントが発生してしまい無限ループに・・・
  • カラムの高さが取得できない(取り方がわからん)ので、Iconの位置決めするのにマジックナンバー(固定値)を使用。うわー、恥ずかしい!
  • ListViewを継承したカスタムコントロールを作って、中で描画の管理をできるようにしようとしたのだが、Itemsプロパティをoverrideしても、仮想モードにすると「設定できない」例外が発生してしまう。ListViewItemCollectionクラスの所為か?

いずれにしてもListViewの継承しての改良では限界がある・・・。
テストプログラムはこちら

以下はソースの抜粋。listView1_RetrieveVirtualItem()で、ListViewのControlsプロパティにPictureBoxを追加することによりIconが表示される。



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace ListViewTEST1
{
    public partial class Form1 : Form
    {
        ListViewItem[] item_;
        PictureBox[] pict_;
        private const int itemCount = 100;

        public Form1()
        {
            InitializeComponent();

            button1.Click += new System.EventHandler(this.button1_Click);

            listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            new System.Windows.Forms.ColumnHeader(),
            new System.Windows.Forms.ColumnHeader()});

            listView1.CheckBoxes = true;
            listView1.VirtualMode = true;
            listView1.View = View.Details;
            listView1.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.listView1_RetrieveVirtualItem);
            listView1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseClick);
            listView1.LargeImageList = new ImageList();
            listView1.SmallImageList = new ImageList();
            
            Image image = (Image)ListViewTEST1.Properties.Resources.IMAGE_NOIMAGE;
            item_ = new ListViewItem[itemCount];
            pict_ = new PictureBox[itemCount];

            for (int index = 0; itemCount > index; index++)
            {
                item_[index] = new ListViewItem(new string[] { index.ToString(), "test" + index.ToString() }, 0);
                item_[index].Checked = true;
                item_[index].Checked = false;
                item_[index].ImageKey = "a" + index.ToString();

                listView1.LargeImageList.Images.Add("a" + index.ToString(), image);
                listView1.SmallImageList.Images.Add("a" + index.ToString(), image);

                pict_[index] = new PictureBox();
                pict_[index].Image = listView1.SmallImageList.Images["a" + index.ToString()];
                pict_[index].Size = new Size(17, 16);
            }

            listView1.VirtualListSize = itemCount;
        }

        private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            e.Item = item_[e.ItemIndex];
            e.Item.Name = e.ItemIndex.ToString();

            Rectangle rect = item_[e.ItemIndex].Bounds;

            Trace.WriteLine(
                    string.Format("RetrieveVirtualItem index={0} listView[VSize,Hight]=[{1},{2}] rect[X,Y,H,W]=[{3},{4},{5},{6}]",
                                    e.ItemIndex, listView1.VirtualListSize, listView1.Height, rect.X, rect.Y, rect.Height, rect.Width));

            if ( (rect.Y < 19) ||
                 ((listView1.Height - 19) < rect.Y) )
            {
                return;
            }

            pict_[e.ItemIndex].Location = new Point(19, rect.Y);
            listView1.Controls.Add(pict_[e.ItemIndex]);
        }

        private void listView1_MouseClick(object sender, MouseEventArgs e)
        {
            ListView lv = (ListView)sender;
            ListViewItem lvi = lv.GetItemAt(e.X, e.Y);
            if (lvi != null)
            {
                if (e.X < (lvi.Bounds.Left + 16))
                {
                    lvi.Checked = !lvi.Checked;
                    lv.Invalidate(lvi.Bounds);
                }
            }
        }
   }
}

« 今さらだけど、今期の新作アニメの感想 | トップページ | ブログネタ: 異性の仕草や言葉で、幻滅するものは何? »

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: 仮想ListViewでIconを表示できたけど・・・:

« 今さらだけど、今期の新作アニメの感想 | トップページ | ブログネタ: 異性の仕草や言葉で、幻滅するものは何? »