C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[13]: トラックバーの一部に色を付ける方法


(過去ログ 167 を表示中)

[トピック内 14 記事 (1 - 14 表示)]  << 0 >>

■96227 / inTopicNo.1)  トラックバーの一部に色を付ける方法
  
□投稿者/ 鮭 (1回)-(2020/11/03(Tue) 20:55:30)

分類:[.NET 全般] 

VB.NETを使っております。

標準のトラックバーと同じようなGUIで

https://image.shutterstock.com/image-vector/seekbar-seek-bar-progress-collection-260nw-340490279.jpg

この画像のように一部に色を付けたいと考えています。
恐らく、標準機能では付けられないので、
カスタムコントロールを作る必要があると思います。

Protected Overrides Sub OnPaint(e As PaintEventArgs)
を使えば良いと思うのですが、
どのようにして、バーの一部だけ色を変えることができますか?


引用返信 編集キー/
■96228 / inTopicNo.2)  Re[1]: トラックバーの一部に色を付ける方法
□投稿者/ 鮭 (2回)-(2020/11/03(Tue) 21:15:06)
もしかして
https://dobon.net/vb/dotnet/graphics/drawvisualcontrol.html

こういうコードを使って
ユーザーコントロールから作っていくのが定石でしょうか?
もっと良い方法があればお教えください。

引用返信 編集キー/
■96240 / inTopicNo.3)  Re[2]: トラックバーの一部に色を付ける方法
□投稿者/ KOZ (145回)-(2020/11/05(Thu) 08:57:18)
No96228 (鮭 さん) に返信
> もしかして
> https://dobon.net/vb/dotnet/graphics/drawvisualcontrol.html
> こういうコードを使って
> ユーザーコントロールから作っていくのが定石でしょうか?

標準の TrackBar を使うのであればそうでしょうけど、かなり面倒くさい処理になりそうです。

> もっと良い方法があればお教えください。

UserControl にいろんなコンポーネントを配置してデザインしたほうが楽かもしれません。

サンプルが CodeProject にあります。

「gTrackBar - A Custom TrackBar UserControl (VB.NET)」
https://www.codeproject.com/Articles/35104/gTrackBar-A-Custom-TrackBar-UserControl-VB-NET

これを参考にしてはいかがでしょうか。

引用返信 編集キー/
■96244 / inTopicNo.4)  Re[3]: トラックバーの一部に色を付ける方法
□投稿者/ KOZ (146回)-(2020/11/05(Thu) 14:49:53)
No96240 (KOZ) に返信

あーすみません、全部描画したほうが楽な気がしてきました。

Imports System.Runtime.InteropServices

Public Class TrackBarEx
    Inherits TrackBar

    Private Const WM_USER As Integer = &H400
    Private Const TBM_GETPOS As Integer = WM_USER               'スライダーの位置を取得
    Private Const TBM_GETRANGEMIN As Integer = WM_USER + 1      'スライダーの位置の最小位置の取得
    Private Const TBM_GETRANGEMAX As Integer = WM_USER + 2      'スライダーの位置の最大位置の取得
    Private Const TBM_GETTIC As Integer = WM_USER + 3           '特定のチックマークの位置を取得
    Private Const TBM_SETTIC As Integer = WM_USER + 4           '特定のチックマークの位置を設定
    Private Const TBM_SETPOS As Integer = WM_USER + 5           'スライダーの位置を設定
    Private Const TBM_SETRANGE As Integer = WM_USER + 6         'スライダー位置の可変範囲の設定
    Private Const TBM_SETRANGEMIN As Integer = WM_USER + 7      'スライダー位置の可変範囲の最小値の設定
    Private Const TBM_SETRANGEMAX As Integer = WM_USER + 8      'スライダー位置の可変範囲の最大値の設定
    Private Const TBM_CLEARTICS As Integer = WM_USER + 9        '現在のチックマークを削除
    Private Const TBM_SETSEL As Integer = WM_USER + 10          'チックマークの選択範囲の設定
    Private Const TBM_SETSELSTART As Integer = WM_USER + 11     'チックマークの選択範囲の終了値の設定
    Private Const TBM_SETSELEND As Integer = WM_USER + 12       'チックマークの選択範囲の開始値の設定
    Private Const TBM_GETPTICS As Integer = WM_USER + 14        'チックマーク位置を示す配列を指すポインタの取得
    Private Const TBM_GETTICPOS As Integer = WM_USER + 15       'チックマークの物理位置の取得
    Private Const TBM_GETNUMTICS As Integer = WM_USER + 16      'チックマークの数の取得
    Private Const TBM_GETSELSTART As Integer = WM_USER + 17     '選択範囲の開始位置の取得
    Private Const TBM_GETSELEND As Integer = WM_USER + 18       '選択範囲の終了位置の取得
    Private Const TBM_CLEARSEL As Integer = WM_USER + 19        '選択範囲の解除
    Private Const TBM_SETTICFREQ As Integer = WM_USER + 20      'チックマークの間隔の設定
    Private Const TBM_SETPAGESIZE As Integer = WM_USER + 21     'ページサイズの設定
    Private Const TBM_GETPAGESIZE As Integer = WM_USER + 22     'ページサイズの取得
    Private Const TBM_SETLINESIZE As Integer = WM_USER + 23     'ラインサイズの設定
    Private Const TBM_GETLINESIZE As Integer = WM_USER + 24     'ラインサイズの取得
    Private Const TBM_GETTHUMBRECT As Integer = WM_USER + 25    'つまみの境界矩形の取得
    Private Const TBM_GETCHANNELRECT As Integer = WM_USER + 26  'スライダーが動くチャンネルの境界矩形の取得
    Private Const TBM_SETTHUMBLENGTH As Integer = WM_USER + 27  'つまみの長さの設定
    Private Const TBM_GETTHUMBLENGTH As Integer = WM_USER + 28  'つまみの長さの取得

    Private Structure RECT
        Public left, top, right, bottom As Integer

        Public Shared Narrowing Operator CType(ByVal r As RECT) As Rectangle
            Return Rectangle.FromLTRB(r.left, r.top, r.right, r.bottom)
        End Operator

    End Structure

    <DllImport("user32.dll", CharSet:=CharSet.Auto)>
    Private Shared Function SendMessage(ByVal hWnd As IntPtr,
                                        ByVal Msg As Integer,
                                        ByVal wParam As IntPtr,
                                        ByRef rect As RECT) As IntPtr
    End Function

    Public Sub New()
        MyBase.New()
        SetStyle(ControlStyles.UserPaint, True)
        SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    End Sub

    Protected Overrides Sub OnValueChanged(e As EventArgs)
        MyBase.OnValueChanged(e)
        MyBase.Invalidate()
    End Sub

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        e.Graphics.FillRectangle(Brushes.DarkGray, ClientRectangle)

        Dim r As New RECT()
        SendMessage(Me.Handle, TBM_GETCHANNELRECT, IntPtr.Zero, r)
        Dim channel As Rectangle = r
        e.Graphics.FillRectangle(Brushes.Black, channel)

        SendMessage(Me.Handle, TBM_GETTHUMBRECT, IntPtr.Zero, r)
        Dim thumb As Rectangle = r
        If thumb.Left > channel.Left Then
            Dim leftchannel As New Rectangle(channel.Left, channel.Top, thumb.Left - channel.Left, channel.Height)
            e.Graphics.FillRectangle(Brushes.Red, leftchannel)
        End If
        e.Graphics.DrawRectangle(Pens.White, channel)

        e.Graphics.FillEllipse(Brushes.White, thumb)
    End Sub

End Class

引用返信 編集キー/
■96250 / inTopicNo.5)  Re[4]: トラックバーの一部に色を付ける方法
□投稿者/ 鮭 (3回)-(2020/11/05(Thu) 21:42:48)
ありがとうございます。

まさにこれが求めていた方法でした。

あと、チックを付けたいのですが、
地道に書くのなら


Dim trackBarTicksRect As Rectangle = Rectangle.FromLTRB(channel.Left, channel.Bottom + 10, channel.Right, channel.Bottom + 20)

TrackBarRenderer.DrawHorizontalTicks(g, trackBarTicksRect, 11,
System.Windows.Forms.VisualStyles.EdgeStyle.Raised)
こんな感じになると思いますが
標準の機能を使って描画するにはどのようにしたら良いですか?
TBM_GETNUMTICSなどの関数で取得したものとリンクさせたいのですが。


引用返信 編集キー/
■96251 / inTopicNo.6)  Re[5]: トラックバーの一部に色を付ける方法
□投稿者/ KOZ (147回)-(2020/11/06(Fri) 09:07:02)
2020/11/06(Fri) 09:10:02 編集(投稿者)
2020/11/06(Fri) 09:09:56 編集(投稿者)

No96250 (鮭 さん) に返信
> 標準の機能を使って描画するにはどのようにしたら良いですか?
> TBM_GETNUMTICSなどの関数で取得したものとリンクさせたいのですが。

オーナードローする以上、地道に描いていくしかありません。

TrackBar で動作するか未確認ですが、

「WM_PAINTでTextBoxがちらつく」
https://social.msdn.microsoft.com/Forums/ja-JP/d5ac1426-1082-43a1-a02f-677dad1ee3ca/wmpaint12391textbox1236412385124251238812367?forum=csharpgeneralja

のように、ビットマップから hdc を作成し、WM_PAINT の WPARAM にセットしてやるとコントロールが描画をしてくれるので、それを加工して表示する、といった方法が使えるかもしれません。

引用返信 編集キー/
■96254 / inTopicNo.7)  Re[6]: トラックバーの一部に色を付ける方法
□投稿者/ KOZ (148回)-(2020/11/06(Fri) 11:47:50)
No96251 (KOZ) に返信
> TrackBar で動作するか未確認ですが、
> 「WM_PAINTでTextBoxがちらつく」
> https://social.msdn.microsoft.com/Forums/ja-JP/d5ac1426-1082-43a1-a02f-677dad1ee3ca/wmpaint12391textbox1236412385124251238812367?forum=csharpgeneralja
> のように、ビットマップから hdc を作成し、WM_PAINT の WPARAM にセットしてやるとコントロールが描画をしてくれるので、それを加工して表示する、といった方法が使えるかもしれません。

うまくいったかも。

Imports System.Runtime.InteropServices

Public Class TrackBarEx
    Inherits TrackBar

    Private Const WM_PAINT As Integer = &HF
    Private Const WM_ERASEBKGND As Integer = &H14

    Private Const WM_USER As Integer = &H400
    Private Const TBM_GETPOS As Integer = WM_USER               'スライダーの位置を取得
    Private Const TBM_GETRANGEMIN As Integer = WM_USER + 1      'スライダーの位置の最小位置の取得
    Private Const TBM_GETRANGEMAX As Integer = WM_USER + 2      'スライダーの位置の最大位置の取得
    Private Const TBM_GETTIC As Integer = WM_USER + 3           '特定のチックマークの位置を取得
    Private Const TBM_SETTIC As Integer = WM_USER + 4           '特定のチックマークの位置を設定
    Private Const TBM_SETPOS As Integer = WM_USER + 5           'スライダーの位置を設定
    Private Const TBM_SETRANGE As Integer = WM_USER + 6         'スライダー位置の可変範囲の設定
    Private Const TBM_SETRANGEMIN As Integer = WM_USER + 7      'スライダー位置の可変範囲の最小値の設定
    Private Const TBM_SETRANGEMAX As Integer = WM_USER + 8      'スライダー位置の可変範囲の最大値の設定
    Private Const TBM_CLEARTICS As Integer = WM_USER + 9        '現在のチックマークを削除
    Private Const TBM_SETSEL As Integer = WM_USER + 10          'チックマークの選択範囲の設定
    Private Const TBM_SETSELSTART As Integer = WM_USER + 11     'チックマークの選択範囲の終了値の設定
    Private Const TBM_SETSELEND As Integer = WM_USER + 12       'チックマークの選択範囲の開始値の設定
    Private Const TBM_GETPTICS As Integer = WM_USER + 14        'チックマーク位置を示す配列を指すポインタの取得
    Private Const TBM_GETTICPOS As Integer = WM_USER + 15       'チックマークの物理位置の取得
    Private Const TBM_GETNUMTICS As Integer = WM_USER + 16      'チックマークの数の取得
    Private Const TBM_GETSELSTART As Integer = WM_USER + 17     '選択範囲の開始位置の取得
    Private Const TBM_GETSELEND As Integer = WM_USER + 18       '選択範囲の終了位置の取得
    Private Const TBM_CLEARSEL As Integer = WM_USER + 19        '選択範囲の解除
    Private Const TBM_SETTICFREQ As Integer = WM_USER + 20      'チックマークの間隔の設定
    Private Const TBM_SETPAGESIZE As Integer = WM_USER + 21     'ページサイズの設定
    Private Const TBM_GETPAGESIZE As Integer = WM_USER + 22     'ページサイズの取得
    Private Const TBM_SETLINESIZE As Integer = WM_USER + 23     'ラインサイズの設定
    Private Const TBM_GETLINESIZE As Integer = WM_USER + 24     'ラインサイズの取得
    Private Const TBM_GETTHUMBRECT As Integer = WM_USER + 25    'つまみの境界矩形の取得
    Private Const TBM_GETCHANNELRECT As Integer = WM_USER + 26  'スライダーが動くチャンネルの境界矩形の取得
    Private Const TBM_SETTHUMBLENGTH As Integer = WM_USER + 27  'つまみの長さの設定
    Private Const TBM_GETTHUMBLENGTH As Integer = WM_USER + 28  'つまみの長さの取得

    Private Structure RECT
        Public Left, Top, Right, Bottom As Integer

        Public ReadOnly Property Width As Integer
            Get
                Return Right - Left
            End Get
        End Property

        Public ReadOnly Property Height As Integer
            Get
                Return Bottom - Top
            End Get
        End Property

        Public Shared Widening Operator CType(ByVal r As RECT) As Rectangle
            Return Rectangle.FromLTRB(r.Left, r.Top, r.Right, r.Bottom)
        End Operator

    End Structure

    <StructLayout(LayoutKind.Sequential)>
    Private Structure PAINTSTRUCT
        Public hdc As IntPtr
        Public fErase As Boolean
        Public rcPaint As RECT
        Public fRestore As Boolean
        Public fIncUpdate As Boolean
        Public reserved1 As Integer
        Public reserved2 As Integer
        Public reserved3 As Integer
        Public reserved4 As Integer
        Public reserved5 As Integer
        Public reserved6 As Integer
        Public reserved7 As Integer
        Public reserved8 As Integer
    End Structure

    <DllImport("user32.dll")>
    Private Shared Function BeginPaint(ByVal hWnd As HandleRef,
                                       ByRef lpPaint As PAINTSTRUCT) As IntPtr
    End Function

    <DllImport("user32.dll")>
    Private Shared Function EndPaint(ByVal hWnd As HandleRef,
                                     ByRef lpPaint As PAINTSTRUCT) As Boolean
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto)>
    Private Shared Function SendMessage(ByVal hWnd As HandleRef,
                                        ByVal Msg As Integer,
                                        ByVal wParam As IntPtr,
                                        ByRef rect As RECT) As IntPtr
    End Function

    Protected Overrides Sub WndProc(ByRef m As Message)
        Select Case m.Msg
            Case WM_PAINT
                Using bmp As New Bitmap(ClientSize.Width, ClientSize.Height)
                    Using bmpGraphics = Graphics.FromImage(bmp)
                        Dim bmphdc = bmpGraphics.GetHdc()
                        Dim msg = Message.Create(m.HWnd, WM_PAINT, bmphdc, IntPtr.Zero)
                        MyBase.WndProc(msg)
                        bmpGraphics.ReleaseHdc()
                        Using pe As New PaintEventArgs(bmpGraphics, ClientRectangle)
                            CustomDraw(pe)
                        End Using
                    End Using
                    If m.WParam = IntPtr.Zero Then
                        Dim hWnd As New HandleRef(Me, m.HWnd)
                        Dim ps As New PAINTSTRUCT()
                        Dim controlHdc = BeginPaint(hWnd, ps)
                        Using controlGraphics = Graphics.FromHdc(controlHdc)
                            controlGraphics.DrawImage(bmp, 0, 0)
                        End Using
                        EndPaint(hWnd, ps)
                    Else
                        Using controlGraphics = Graphics.FromHdc(m.WParam)
                            controlGraphics.DrawImage(bmp, 0, 0)
                        End Using
                    End If
                End Using
            Case WM_ERASEBKGND
                '無視
            Case Else
                MyBase.WndProc(m)
        End Select
    End Sub

    Protected Overridable Sub CustomDraw(e As PaintEventArgs)
        'チャネルおよびつまみの領域を取得
        Dim channel As New RECT()
        Dim thumb As New RECT()
        Dim hWnd As New HandleRef(Me, Me.Handle)
        SendMessage(hWnd, TBM_GETCHANNELRECT, IntPtr.Zero, channel)
        SendMessage(hWnd, TBM_GETTHUMBRECT, IntPtr.Zero, thumb)

        ' チャネルおよびつまみの領域を背景色で塗りつぶす
        Using b As New SolidBrush(BackColor)
            e.Graphics.FillRectangle(b, New Rectangle(channel.Left, thumb.Top, channel.Width, thumb.Height))
        End Using

        'チャネルを描く
        e.Graphics.FillRectangle(Brushes.Black, channel)
        If thumb.Left > channel.Left Then
            'つまみの左側を塗りつぶす
            Dim leftchannel As New Rectangle(channel.Left, channel.Top, thumb.Left - channel.Left, channel.Height)
            e.Graphics.FillRectangle(Brushes.Red, leftchannel)
        End If
        e.Graphics.DrawRectangle(Pens.White, channel)

        'つまみを描く
        e.Graphics.FillEllipse(Brushes.White, thumb)
        e.Graphics.DrawEllipse(Pens.Black, thumb)
    End Sub

    Protected Overrides Sub OnValueChanged(e As EventArgs)
        MyBase.OnValueChanged(e)
        MyBase.Invalidate()
    End Sub

End Class

引用返信 編集キー/
■96255 / inTopicNo.8)  Re[7]: トラックバーの一部に色を付ける方法
□投稿者/ 鮭 (4回)-(2020/11/06(Fri) 18:00:26)
ありがとうございます。

あと、スライダーが最大と最小位置にある時の座標を知りたいのですが、

TBM_GETTICPOSでうまくいくかと思ったのですが、
なぜか少しずれた位置になってしまいます。

いま、トラックバーの最大値と最小値に10000と0が設定してあるのですが、


Dim hhh2 As Integer = CInt(SendMessage(Me.Handle, TBM_GETTICPOS, 0, Nothing))
は正常な位置が取得できるのですが、

Dim hhh As Integer = CInt(SendMessage(Me.Handle, TBM_GETTICPOS, 10000, Nothing))
とすると-1が出力されます。
Dim hhh As Integer = CInt(SendMessage(Me.Handle, TBM_GETTICPOS, 9998, Nothing))
とすると、366などの数値は出力されるのですが、
実際のスライダーが動ける最大位置よりも-2程度ずれた位置になっています。

どうすれば、正確な座標を取得することができますか?
引用返信 編集キー/
■96256 / inTopicNo.9)  Re[8]: トラックバーの一部に色を付ける方法
□投稿者/ 魔界の仮面弁士 (2900回)-(2020/11/06(Fri) 18:12:25)
2020/11/06(Fri) 18:51:33 編集(投稿者)

No96255 (鮭 さん) に返信
> TBM_GETTICPOSでうまくいくかと思ったのですが、
> 実際のスライダーが動ける最大位置よりも-2程度ずれた位置になっています。

両端部の目盛り位置が含まれないためです。
下記を参照してみてください。

https://docs.microsoft.com/ja-jp/windows/win32/controls/tbm-gettic?WT.mc_id=DT-MVP-8907#parameters

https://docs.microsoft.com/en-us/windows/win32/controls/tbm-getticpos?WT.mc_id=DT-MVP-8907#remarks

https://docs.microsoft.com/ja-jp/windows/win32/controls/tbm-getnumtics?WT.mc_id=DT-MVP-890#return-value
引用返信 編集キー/
■96257 / inTopicNo.10)  Re[9]: トラックバーの一部に色を付ける方法
□投稿者/ 鮭 (5回)-(2020/11/06(Fri) 22:47:59)
ありがとうございます。

つまり、最小値は
Dim hhh2 As Integer = CInt(SendMessage(Me.Handle, TBM_GETTICPOS, 0, Nothing))
で得られたものから-1するものが正しく、

最大値は、
Dim hhh As Integer = CInt(SendMessage(Me.Handle, TBM_GETTICPOS, 9998, Nothing))
で得られたものから+1するものが正しい
という意味でしょうか?

ただ、試してみると、最小値は正しく
最大値の方だけ-2する必要がある気がしますが、
これは何か確認ミスでしょうか?
引用返信 編集キー/
■96258 / inTopicNo.11)  Re[10]: トラックバーの一部に色を付ける方法
□投稿者/ 魔界の仮面弁士 (2901回)-(2020/11/07(Sat) 01:08:31)
2020/11/07(Sat) 01:15:58 編集(投稿者)

No96257 (鮭 さん) に返信
> という意味でしょうか?

たとえば
 Minimum = 1000
 Maximum = 9000
 TickFrequency = 500
だった場合、Value の取りうる範囲は 1000 以上 9000 以下ですが、
TBM_GETTICPOS に渡せる範囲は、0 以上 7998 以下となりますし、
TBM_GETNUMTICS で得られる値は 17 になります。

Maximum を 9001 に変更すれば、
TBM_GETTICPOS は、0 以上 7999 以下を受け付け、
TBM_GETNUMTICS の値が 18 となる換算。

引用返信 編集キー/
■96263 / inTopicNo.12)  Re[11]: トラックバーの一部に色を付ける方法
□投稿者/ 鮭 (6回)-(2020/11/07(Sat) 11:04:16)
ありがとうございます。

つまり、TBM_GETTICPOSでは最大位置と最小値を取得することができないという意味でしょうか?
webページを見てもそういう書き方になっているのが気になりました。

どうすれば、最大・最小位置を取得できますか?
そのようなメソッドは用意されていない、なんてことはないですよね?

引用返信 編集キー/
■96274 / inTopicNo.13)  Re[12]: トラックバーの一部に色を付ける方法
□投稿者/ KOZ (149回)-(2020/11/09(Mon) 09:13:50)
No96263 (鮭 さん) に返信
> どうすれば、最大・最小位置を取得できますか?
> そのようなメソッドは用意されていない、なんてことはないですよね?

TBM_GET 系をひととおり見てみましたが、なんだかなさそうです。

こんな話もあるようで・・・

「How to calculate WinForms TrackBar each tick position?」
https://stackoverflow.com/questions/54931501/how-to-calculate-winforms-trackbar-each-tick-position

引用返信 編集キー/
■96287 / inTopicNo.14)  Re[13]: トラックバーの一部に色を付ける方法
□投稿者/ 鮭 (7回)-(2020/11/09(Mon) 20:45:39)
需要ありそうなメソッドなのに用意されていないということもあるのですね。

どうもありがとうございます。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -