うさ☆うさ日記 このページをアンテナに追加 RSSフィード

2006 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 05 | 06 |
2013 | 05 | 08 | 09 | 10 | 11 | 12 |
2014 | 08 |
2015 | 04 | 06 | 08 | 09 | 11 | 12 |
2016 | 01 | 02 | 04 | 05 | 09 | 11 | 12 |
2017 | 04 | 05 | 06 | 10 | 11 |
2018 | 03 | 04 |

2006-10-11

[].NET1.1のListViewでオーナードロー、オーナーデータ

.NET Framework 1.1のListViewで、オーナーデータをやりたいという要求とオーナードローをやりたいという要求が同じ日に自分の所にまわってきて。

そんな対応をしていた、今日はListViewの日(・∀・)


面倒なことに、.NET Framework 1.1だとどちらにも標準対応してないんですよね(´・ω・`)

.NET Framework 2.0ならVirtualModeプロパティやOwnerDrawプロパティがあるわけですが。


で、やるとしたらWin32的な処理でやるか、いっそ.NET 2.0にしてしまうか。


オーナーデータの方は、前に自分が作ったListView表示の簡易ツールで、大量のデータ*1を扱いたいと言う内容だったわけですけが。

最大でも数千件程度のデータを想定したテスト用のツールだったので、単純にListViewItemの追加*2

を行うだけの実装にしていたため、大量データだと何十秒も固まるという状況に(´Д`)


まあ、これは正規に顧客へリリースするプログラムでも無いし、内部で使うためのものなので、.NET 2.0化することで対応しちゃいました(゚∀゚)

前にMSDNかどこかで.NET 1.1用のListViewオーナーデータ拡張を見かけた気もするんですが、探すのも面倒だったし.NET 2.0化するほうが楽だと思ったりして。


で、もう一つの要求について。

オーナードローの方はというと、こっちは厄介なことに顧客へリリースするプログラムであって、要件を満たすためにはListViewのオーナードローが必要なものだったりして。

勿論、仕様の方を調整するとか、グリッド系のコンポーネントに切り替えるっていう手はあるわけですが。

ただ、顧客*3が変更管理に関してとってもお役所的な作業を必要とされるタイプということもあって、とりあえずListViewの設計のままでどうにかできないかというお話でした。


だから、推敲フェーズで技術リスクをちゃんと検証してないプロジェクトはダメなんだよ!*4

しかも細かいことに『だけ』五月蠅い顧客の案件で、実装スキルの無い人間が適当な設計書を書いているから、後になって実現できないとか騒ぐ事に(`ω´*)


で、環境も.NET 1.1用と決まっているモノだから2.0化して対応というわけにも行かず、とりあえずWin32的な対処方法を検討してみることにしたのでそのメモ。


まずは、CDDS_PREPAINTとかNM_CUSTOMDRAWとかCDRF_DODEFAULTのenumを定義。

RECT、NMHDR、NMCUSTOMDRAW、MEASUREITEMSTRUCTのstructなんかも定義。


あとは以下のようなCustomDrawHandlerと、そのイベントOnCustomDrawを持つListView派生クラスを作って、WndProcをoverrideすることでオーナードローに対応してみました。

// カスタムドロー用ハンドラ
public delegate int CustomDrawHandler(int idCtrl, ref NMCUSTOMDRAW nmcd);

// カスタムドロー対応ListView
public class CustomDrawListView : System.Windows.Forms.ListView
{
    public event CustomDrawHandler OnCustomDraw;

    private int itemHeight = 13;

    public int ItemHeight
    {
        get { return( this.itemHeight ); }
        set { this.itemHeight = value; }
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.Style |= LVS_OWNERDRAWFIXED;
            return( cp );
        }
    }

    protected override void WndProc(ref Message msg)
    {
        if ( msg.Msg == (int)OCM.OCM_MEASUREITEM )
        {
            unsafe
            {
                MEASUREITEMSTRUCT* pmis =  (MEASUREITEMSTRUCT*)msg.LParam.ToPointer();
                pmis->itemHeight = this.itemHeight;
            }
            return;
        }

        if ( OnCustomDraw != null )
        {
            if ( msg.Msg == (int)OCM.OCM_NOTIFY )
            {
                NMHDR hrd = (NMHDR)msg.GetLParam( typeof(NMHDR) );
                
                if ( hrd.code == (int)NM.NM_CUSTOMDRAW )
                {	
                    NMLVCUSTOMDRAW nmlvcd = (NMLVCUSTOMDRAW)msg.GetLParam( typeof(NMLVCUSTOMDRAW) );

                    msg.Result = (IntPtr)OnCustomDraw( (int)msg.WParam.ToInt32(), ref nmlvcd );

                    return;
                }
            }
        }

        base.WndProc(ref msg);
    }
}

1行にマルチラインの文字表示したいということで、行の高さも設定できるようにOCM_MEASUREITEMもハンドリングしています。


で、描画の詳細はイベントの実装先に委譲しちゃっていますが(´Д`;)

後は担当者が実装するということですが…、大丈夫かしら?

とりあえず「.NET 1.1におけるListViewでのオーナードローの仕組み」までは用意してみたわけですが、面倒なのはここからよね〜。


まあ、一般的にはこれから新規に.NET 1.1の開発ってことも無いだろうし、今更必要の無い情報でしたね(´ω`)

*1:10万行とか

*2:もちろnBeginUpdate()、EndUpdate()はしています

*3:っというかその前のコンサルの人達

*4:…って別にRUPしてるわけではないんですけどね(´ω`)

PAOPAO 2006/11/04 23:49 ListVIew には、itemHeight プロパティは、ないと思うのですが、
このロジックで、うまくいきますか?(^_^;)

PAOPAO 2006/11/05 00:00 参考にさせていただいております。
OnCustomDraw イベントもListView には、ないと思うのですが・・・
あくまでも、.NET 2.0 です。

PAOPAO 2006/11/05 01:11 成る程、その、OnCustomDraw 自体を実装するのが、
他の部隊ということなのですね。
何とか、ListView で、1行にマルチラインを実現したかったのですが・・・

machi_ponmachi_pon 2006/11/05 14:01 アレ?、っと思って見直してみたら、掲載したソースを省略しすぎていました(´Д`;)

すいません、コード部にちょっと追記しました。
itemHeightメンバもOnCustomDrawイベントも自前で定義しています。
で、とりあえずこのクラスとしてはOnCustomDrawを呼ぶんで、実際の描画内容についてはdelegateを用意する側でよろしく(・∀・)!、って感じにしています。

一応、自分とこでは.NET 1.1でもオーナードローは出来ています(もちろん複数行表示みたいな事も)。
まあ、実際はOnCustomDrawの中身を書いていくのがメンドクサイんですけどねぇ(´ω`)

PAOPAO 2006/11/06 00:10 すいません、どこに、追記したコードはああるのでしょうか?(^_^;)

あと・・・
もし、マルチライン実装してあるListViewコントロールがあれば、ソースごとただでください。(^_^;)
いつでもお待ちしてます。
mailto:pao@pao.ac
です。
よろしくお願いします。m(_ _;)m

PAOPAO 2006/11/06 14:58 あ、確かに付け足してありましたね。(^_^;)
itemHeight と、OnCustomDrow
すいません。m(;_ _)m

だけど、マルチライン実装のListView コントロールは・・・
ください。m(;_ _)mm(_ _;)m

machi_ponmachi_pon 2006/11/06 18:40 修正内容は分かりづらかったですね(´Д`;)
とりあえず11/06日の日記に補足を入れてみたので、参照してみてください(・∀・)

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/machi_pon/20061011/1160560256