DOBON.NET DOBON.NETプログラミング掲示板過去ログ

TreeViewのテキスト表示部分の右

分類:[.NET]

どうもです。

VB.NETで、TreeViewコントロールのTextプロパティの表示部分の後に
OutlookExpressの未読メールカウントのような
フォントの違う文字を表示するにはどうしたらよいのでしょうか?

受信トレイ (2)
↑この「受信トレイ」が普通(黒字)で、「(2)」が青太字みたいに表示したい


よろしくお願いします。
■No717に返信(edachoさんの記事)
> VB.NETで、TreeViewコントロールのTextプロパティの表示部分の後に
> OutlookExpressの未読メールカウントのような
> フォントの違う文字を表示するにはどうしたらよいのでしょうか?

TreeNodeのNodeFontでフォントを、ForeColorで色を指定できます。

試しにフォントを太字にしてみたところ、最後の文字が欠けるようです。ちゃんと表示させるためには、他に何らかの処理が必要かもしれません。(最悪、最後にスペースを入れるとか。)
■No727に返信(管理人さんの記事)
> ■No717に返信(edachoさんの記事)
>>VB.NETで、TreeViewコントロールのTextプロパティの表示部分の後に
>>OutlookExpressの未読メールカウントのような
>>フォントの違う文字を表示するにはどうしたらよいのでしょうか?

#質問内容を間違えて回答してしまったようで、失礼しました。

次のURLが参考になりそうです。

C# Help - Outlook Style Tree View
http://www.csharphelp.com/archives2/archive286.html
どうもです。

> 次のURLが参考になりそうです。
> C# Help - Outlook Style Tree View
> http://www.csharphelp.com/archives2/archive286.html
ありがとうございます。
このサンプルが目的としている動作そのものです。
C#のプログラムとしてきちんと動作も確認できました。
と、よろこんでいたのもつかのまでして、
VBのコードにうまく直せません。

定数宣言の部分を
Private WM_NOTIFY As System.UInt32 = 78
と書いてみたところ
「定数はclass、structure、または array型ではなく、組み込み型または列挙型でなければなりません。」
というエラーがでます。
どうも初級レベルでつまづいているようなのですが、
このあとには、WndProc関数内で使用しているポインタをどういう風に書けばいいのかわかりません、という悩みが発生しそうです。

どうしたらよいのでしょうか、括弧涙
2003/09/29(Mon) 23:22:34 編集(投稿者)

>>次のURLが参考になりそうです。
>>C# Help - Outlook Style Tree View
>>http://www.csharphelp.com/archives2/archive286.html
> ありがとうございます。
> このサンプルが目的としている動作そのものです。
> C#のプログラムとしてきちんと動作も確認できました。
> と、よろこんでいたのもつかのまでして、
> VBのコードにうまく直せません。

提示URLのC#コードから、ざっくりと修正してVB版を作成してみました。
かなりいい加減なのでひょっとすると落ちるかもしれません。
(2,3度動かした範囲ではC#版と同様の動きで動いていますが)

'------------------------------------------------------------
Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices

Namespace TB
    Public Class Form1
        Inherits System.Windows.Forms.Form

#Region " Windows フォーム デザイナで生成されたコード "

        Public Sub New()
            MyBase.New()

            ' この呼び出しは Windows フォーム デザイナで必要です。
            InitializeComponent()

            ' InitializeComponent() 呼び出しの後に初期化を追加します。

        End Sub

        ' Form は、コンポーネント一覧に後処理を実行するために dispose をオーバーライドします。
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                If Not (components Is Nothing) Then
                    components.Dispose()
                End If
            End If
            MyBase.Dispose(disposing)
        End Sub

        ' Windows フォーム デザイナで必要です。
        Private components As System.ComponentModel.IContainer

        ' メモ : 以下のプロシージャは、Windows フォーム デザイナで必要です。
        'Windows フォーム デザイナを使って変更してください。  
        ' コード エディタを使って変更しないでください。
        Friend WithEvents treeView1 As System.Windows.Forms.TreeView
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
            Me.treeView1 = New System.Windows.Forms.TreeView
            Me.SuspendLayout()
            '
            'treeView1
            '
            Me.treeView1.Dock = System.Windows.Forms.DockStyle.Fill
            Me.treeView1.ImageIndex = -1
            Me.treeView1.Location = New System.Drawing.Point(0, 0)
            Me.treeView1.Name = "treeView1"
            Me.treeView1.Nodes.AddRange( _ 
New System.Windows.Forms.TreeNode() { _ 
New System.Windows.Forms.TreeNode("My TreeView Today ", _ 
New System.Windows.Forms.TreeNode() { _ 
New System.Windows.Forms.TreeNode("Node1")}), _ 
New System.Windows.Forms.TreeNode("Node2"), _ 
New System.Windows.Forms.TreeNode("Node3"), _ 
New System.Windows.Forms.TreeNode("Node4", _ 
New System.Windows.Forms.TreeNode() { _
New System.Windows.Forms.TreeNode("Node5", _ 
New System.Windows.Forms.TreeNode() { _
New System.Windows.Forms.TreeNode("Node6", _ 
New System.Windows.Forms.TreeNode() { _
New System.Windows.Forms.TreeNode("Node7", _ 
New System.Windows.Forms.TreeNode() { _ 
New System.Windows.Forms.TreeNode("Node8")})})})})})
            Me.treeView1.SelectedImageIndex = -1
            Me.treeView1.Size = New System.Drawing.Size(152, 273)
            Me.treeView1.TabIndex = 1
            '
            'Form1
            '
            Me.AutoScaleBaseSize = New System.Drawing.Size(5, 12)
            Me.ClientSize = New System.Drawing.Size(152, 273)
            Me.Controls.Add(Me.treeView1)
            Me.Name = "Form1"
            Me.Text = "Form1"
            Me.ResumeLayout(False)

        End Sub

#End Region

        Private Const WM_NOTIFY As Integer = 78
        Private ReadOnly NM_CUSTOMDRAW As UInt32 = Convert.ToUInt32(4294967284)
        Private Const CDDS_ITEMPREPAINT As Integer = 65537
        Private Const CDRF_NOTIFYSUBITEMDRAW As Integer = 32

        Protected Overrides Sub WndProc(ByRef m As Message)
            Dim lp2 As NMCUSTOMDRAW
            Dim lp As NMHDR

            If (m.Msg = WM_NOTIFY) Then
                lp = Marshal.PtrToStructure(m.LParam, lp.GetType())

                If (lp.code.CompareTo(NM_CUSTOMDRAW) = 0) Then
                    lp2 = Marshal.PtrToStructure(m.LParam, lp2.GetType())

                    If (lp2.dwDrawStage = CDDS_ITEMPREPAINT) Then
                        MyBase.WndProc(m)
                        TreeViewPaint(m)
                        m.Result = IntPtr.Zero
                        Return
                    Else
                        m.Result = New IntPtr(CDRF_NOTIFYSUBITEMDRAW)
                    End If
                End If
            End If
            MyBase.WndProc(m)
        End Sub

        Public Sub TreeViewPaint(ByRef m As Message)
            Dim lp2 As NMCUSTOMDRAW
            Dim g As Graphics
            Dim node As TreeNode
            Dim strText As String   '//Text to draw
            Dim x1, y1 As Long      '//coordinates there we will paint 

            lp2 = Marshal.PtrToStructure(m.LParam, lp2.GetType())

            g = System.Drawing.Graphics.FromHwnd(Me.treeView1.Handle)
            node = Me.treeView1.GetNodeAt(CInt(lp2.x1) + 1, CInt(lp2.y1) + 1)

            x1 = lp2.x1 + node.Bounds.X + node.Bounds.Width + 5
            y1 = lp2.y1
            strText = "( " + node.Index.ToString() + " )"

            g.DrawString(strText, Me.treeView1.Font, System.Drawing.Brushes.DarkBlue, x1, y1, System.Drawing.StringFormat.GenericTypographic)
            Return
        End Sub

        <STAThread()> _
        Public Shared Sub Main()
            Application.Run(New Form1)
        End Sub
    End Class

    Public Structure NMHDR
        Public hwndFrom As IntPtr
        Public idFrom As Integer
        Public code As UInt32
    End Structure

    Public Structure NMLVCUSTOMDRAW
        Public hdr As NMCUSTOMDRAW
        Public clrText As Integer
        Public clrTextBk As Integer
        Public iSubItem As Integer
    End Structure

    Public Structure NMCUSTOMDRAW
        Public hdr As NMHDR
        Public dwDrawStage As Integer
        Public hdc As Integer
        Public x1 As Integer
        Public y1 As Integer
        Public x2 As Integer
        Public y2 As Integer
        Public dwItemSpec As Integer
        Public uItemState As Integer
        Public lItemlParam As Integer
    End Structure
End Namespace

'------------------------------------------------------------

> 定数宣言の部分を
> Private WM_NOTIFY As System.UInt32 = 78
> と書いてみたところ
> 「定数はclass、structure、または array型ではなく、組み込み型または列挙型でなければなりません。」
> というエラーがでます。

Constが抜けていますが、Const指定で定数にしようとしたんですよね?
VBのConstステートメントはVBの組み込み型しか型として使えないようなので、
UInt32の場合はConstステートメントは使えません。
ほとんどの場合はUInt32はIntegerで代用できます。
(どちらも32ビット整数で変数のサイズが同じでメモリ上でのイメージに違いがないためです)

定数NM_CUSTOMDRAWに関してはIntegerでは扱えない数値なので、
UInt32を使うためにConstのかわりにReadOnly指定を使ってみました。

> このあとには、WndProc関数内で使用しているポインタをどういう風に
> 書けばいいのかわかりません、という悩みが発生しそうです。

TreeViewのカスタムドローのときにWndProcメソッドのm.LParamで渡されるものは、
各構造体のポインタになっているので、ポインタから構造体への変換は、
MarshalクラスのPtrToStructureメソッドで行っています。
#MarshalクラスはSystem.Runtime.InteropServices名前空間のため
#Imports System.Runtime.InteropServicesを追加してます。

DOBON.NET | プログラミング道 | プログラミング掲示板