none
ツリービュー オーナードロー時のHitTest判別について RRS feed

  • 全般的な情報交換

  • お世話になっております。
    .NET Framework 2.0 でフォームアプリケーションを作成しています。
    System.Windows.Forms.TreeView について DrawModeをOwnerDrawAllに設定して、ツリービューをオーナードローしています。

    オーナードローでは、チェックボックスやアイコンなどを横位置の変更を含めて独自に変更しています。
    それにあわせて、HitTestされた際のTreeViewHitTestLocationsの種別を返したいのですが
    HitTestの結果をカスタマイズする方法がありましたらご教示いただけますでしょうか?

    HitTest系のイベントがあるか否かやDrawNodeイベントの戻り引数などを調べてみましたが
    残念ながら自分で見つけることができませんでした。

    TreeViewクラスを継承してオーバーライドしたりしなくてはならないのでしょうか?

    情報をお持ちの方、宜しくお願い致します。

    • 種類を変更済み 山本春海 2012年3月28日 8:59 仕様変更により対処されたとのことなので、ステータスを変更させていただきました。
    2012年3月13日 9:41

すべての返信

  • 実際に試していないので参考です。

    TreeView.DrawNode Event

    に例があります。この例ではDrawNodeとMouseDownにEventHanderをセットしています。

            // Configure the TreeView control for owner-draw and add
            // a handler for the DrawNode event.
            myTreeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
            myTreeView.DrawNode += 
                new DrawTreeNodeEventHandler(myTreeView_DrawNode);
    
            // Add a handler for the MouseDown event so that a node can be 
            // selected by clicking the tag text as well as the node text.
            myTreeView.MouseDown += new MouseEventHandler(myTreeView_MouseDown);

    そしてそれぞれのEventHanderで処理を行っています。

    いろいろと独自に変更しているということなので、EventHanderの中でクリックしたところがどのエリア内なのかを調べてTreeViewHitTestLocationsを返す処理を行うことになると思います。

    すでにこの情報を見つけていたのでしたら、すみません。

    2012年3月13日 12:36
  • TreeViewを継承したクラスでのHitTestメソッドのオーバーライドは
    基底クラスでOverridable指定されていいないため出来ませんでした。

    そもそも、内蔵された動作のためにHitTestメソッドを呼び出しているか、疑問ではあります。

    • 編集済み koma_deko 2012年3月14日 7:02
    2012年3月14日 6:56
  • BlueSkyColors様

    ご教示いただきまして有難う御座います。
    MouseDownイベントをハンドルして、自力で操作をする方法ですね。
    ツリービュー内蔵の既定の動作(クリック時の展開/折り畳みや選択など)を止めることができれば、
    この方法を採用させていただきたいと思っています。

    MouseDownイベントでチェックボックスのON / OFF や ツリーノードの展開/折り畳みを制御した場合、
    そのあとで既定の動作が働いてしまって
    たとえば、オーナードローによって何も書かれなくなった位置であっても
    既定で本来+ / - のイメージが配置される位置をクリックされると
    自動でツリーノードが展開されてしまったりします。

    ツリービュー内蔵の既定の動作を止める方法があれば
    ご教示いただけますと助かります。

    宜しくお願い致します。




    • 編集済み koma_deko 2012年3月14日 7:00
    2012年3月14日 6:58
  • 実際にやりたいことは
    階層位置に応じて、ノードに2つ以上のアイコンイメージを並べて表示することです。

    -ノード1
     +□ノード2A
     -□ノード2B
      +▼■ノード3A
      +◇■ノード3B
      +  ノード3C
      +  ノード3D
      -◆■ノード3E
        ◎■ノード4A
        ○■ノード4B

    などと表示させて
    クリックしたアイコンに応じて処理を行うことを考えています。

    オーナードローではなく、内蔵された処理に任せてアイコン表示をさせた場合、
    上記のノード3と4のアイコンのために
    32×16ドットのビットマップをImageListに登録してみましたが、
    正方形(16×16ドット?)に圧縮されてしまいました。
    そのため、オーナードローでノードを描画しようと考えました。

    オーナードローをした場合
    アイコン領域の横幅分、テキストラベルの右側部分がクリックに反応しなくなり、
    ノードの展開/折り畳みに無反応になってしまいます。

    システムに描画を任せた場合にアイコンを正方形以外(イメージ本来の縦横比)で表示させる方法、
    ノードクリック時のツリービューの既定の動作を無効にする方法、
    もしくは、オーナードロー時にヒットテストの結果(領域の判断)をカスタマイズする方法
    など、ご教示いただけますと幸いです。

    宜しくお願い致します。

    2012年3月14日 8:49
  • これまた自分で試していないので申し訳ないのですが、

    private void treeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
    
    // 引数のDrawDefault をfalseにすることで、デフォルトの動作を停止させる。
    
    e.DrawDefault = false;
    で、期待した動作(ツリービュー内蔵の既定の動作が止まる)にはならないでしょうか。
    2012年3月14日 12:10
  • DrawDefault はデフォルトでfalseという記述を見つけましたので違いました。すみません。

    だとすると、TreeView.ExpandAll等の処理されては困るイベントも追加しないといけないのかもしれません。

    あと、この場合はOwnerDrawTextではなくOwnerDrawAllでした。

    2012年3月14日 13:47
  • BlueSkyColors様

    どうも有難う御座います。

    本題の課題は解決・克服できていないのですが、
    今回のソフトウエアは、仕様変更で対応することにしました。

    具体的には
    アイコンイメージをラベルの左側ではなく右側に配置することにしました。

    オーナードロー(OwnerDrawText)は生かしたまま
    DrawNodeイベントハンドラ内でラベル右側の位置へアイコンを描画し、
    e.DrawDefault = True
    によって残りのラベル部分の描画を既定の処理に任せることにしました。
    (e.DrawDefault = True によって DrawNode内の描画は上書き消去されませんでした)

    有難う御座いました。

    2012年3月15日 2:36