質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

1回答

2367閲覧

VB.netでListViewを仮想モードでサムネイルを表示しているが、項目を選択しているときに選択状態の青い色にするか、もしくは項目の背景色を青い色にしたい

tada_tadaa

総合スコア111

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2022/01/10 09:04

編集2022/01/10 13:34

VB.netでListViewを仮想モードで開いてサムネイル(小さい画像の一覧)を表示しています。

vb

1Public Class Form1 2 Public imageDir As String = "C:\Users\user\Pictures" ' 画像ディレクトリ 3 Public jpgFiles As String() = System.IO.Directory.GetFiles(imageDir, "*.jpg", IO.SearchOption.TopDirectoryOnly) 4 Public thumbnail(jpgFiles.Length) As Image 5 Public width1 As Integer = 100 6 Public height1 As Integer = 80 7 Public Imagelist1 As New ImageList 8 Public index As Integer = 0 9 10 ' 幅w、高さhのImageオブジェクトを作成 11 Function createThumbnail(ByVal image As Image, ByVal w As Integer, ByVal h As Integer) As Image 12 Dim canvas As New Bitmap(w, h) 13 14 Dim g As Graphics = Graphics.FromImage(canvas) 15 g.FillRectangle(New SolidBrush(Color.White), 0, 0, w, h) 16 17 Dim fw As Double = CDbl(w) / CDbl(image.Width) 18 Dim fh As Double = CDbl(h) / CDbl(image.Height) 19 Dim scale As Double = Math.Min(fw, fh) 20 Dim w2 As Integer = CInt(image.Width * scale) 21 Dim h2 As Integer = CInt(image.Height * scale) 22 23 g.DrawImage(image, (w - w2) \ 2, (h - h2) \ 2, w2, h2) 24 g.Dispose() 25 26 Return canvas 27 End Function 28 29 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 30 ListView1.Enabled = True 31 ListView1.Visible = True 32 ListView1.VirtualMode = True 33 ListView1.OwnerDraw = True 34 35 Imagelist1.ImageSize = New Size(width1, height1) 36 ListView1.LargeImageList = Imagelist1 37 ListView1.VirtualListSize = jpgFiles.Length 38 39 For i As Integer = 0 To jpgFiles.Count - 1 40 thumbnail(i) = Nothing 41 Next 42 End Sub 43 44 Private Sub ListView1_RetrieveVirtualItem(sender As Object, e As RetrieveVirtualItemEventArgs) Handles ListView1.RetrieveVirtualItem 45 e.Item = New ListViewItem(jpgFiles(e.ItemIndex), e.ItemIndex) 46 End Sub 47 48 Private Sub ListView1_DrawItem(sender As Object, e As DrawListViewItemEventArgs) Handles ListView1.DrawItem 49 e.DrawDefault = False 50 e.DrawBackground() 51 52 If thumbnail(e.ItemIndex) Is Nothing Then 53 Dim original As Image 54 Try 55 original = Bitmap.FromFile(jpgFiles(e.ItemIndex)) 56 Catch 57 original = My.Resources.Resource1._error 58 End Try 59 thumbnail(e.ItemIndex) = createThumbnail(original, Width, Height) 60 End If 61 62 Dim imagerect As New Rectangle(New Point(e.Bounds.X + ((e.Bounds.Width - width1) / 2), e.Bounds.Y), New Size(width1, height1)) 63 e.Graphics.DrawImage(thumbnail(e.ItemIndex), imagerect) 64 'e.Item.ForeColor = Color.AliceBlue ' ←コメント状態を解除するとListView1が高速で点滅状態になる 65 'ListView1.Items(index).BackColor = Color.Aqua ' ←コメント状態を解除するとListView1が高速で点滅状態になる 66 67 e.DrawFocusRectangle() 68 ListView1.Items(index).Focused = True 69 ListView1.Items(index).Selected = True ' ←選択状態の時の青い色にならない 70 End Sub 71 72 Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click 73 index = index - 1 74 If index < 0 Then index = 0 75 76 ListView1.Items(index).Focused = True 77 ListView1.Items(index).Selected = True ' ←選択状態の時の青い色にならない 78 ListView1.Items(index).BackColor = Color.Aqua ' ←色が変わらない 79 End Sub 80 81 Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click 82 index = index + 1 83 If index > ListView1.Items.Count - 1 Then index = ListView1.Items.Count - 1 84 85 ListView1.Items(index).Focused = True 86 ListView1.Items(index).Selected = True ' ←選択状態の時の青い色にならない 87 ListView1.Items(index).BackColor = Color.Aqua ' ←色が変わらない 88 End Sub 89 90 Private Sub ListView1_ItemActivate(sender As Object, e As EventArgs) Handles ListView1.ItemActivate 91 ListView1.Items(index).BackColor = Color.Aqua ' ←色が変わらない 92 End Sub 93 94 Private Sub ListView1_VirtualItemsSelectionRangeChanged(sender As Object, e As ListViewVirtualItemsSelectionRangeChangedEventArgs) Handles ListView1.VirtualItemsSelectionRangeChanged 95 ListView1.Items(e.EndIndex).BackColor = Color.Aqua ' ←色が変わらない 96 End Sub 97End Class 98

フォームにはListViewの他にButton2とButton3が配置してあります。Button2で前の項目を、Button3で次の項目を選択状態にして項目の背景色を変えるコードを書いたつもりです。しかしButton2やButton3を押しても選択状態にならず背景色も変わりません。僕の勝手な推測ですが、

ListView1.OwnerDraw = True
を設定している事により、描画の必要性があるときに

** Private Sub ListView1_DrawItem(sender As Object, e As DrawListViewItemEventArgs) Handles ListView1.DrawItem**
が呼び出されて描画処理を行っているようなのですが、どうもいろんなタイミングでListView1_DrawItemが呼び出されているのではないかと思います。ListViewをスクロールした時や最初にサムネイル一覧を作成する時は呼び出される必要があると思いますが、その他のたいして呼び出す必要がなさそうな時、例えば

**ListView1.Items(index).Selected = True **
を実行した時や
ListView1.Items(index).BackColor = Color.Aqua
を実行した時なども呼び出されているっぽいです。
そしてListView1_DrawItemでの描画処理で上書きしてしまって何も変化がないように見えているのではないかと思います。

ListView1_DrawItemが呼び出されたときに、それがスクロール処理や一番最初のサムネイル作成以外で呼び出された事が分かれば処理を抜けるようにすれば上書きを防ぐことが出来るのではないかと思いますが、どういうイベントによって呼び出されたのかを知る方法が分かりません。

ListViewの選択された項目を選択状態の時の薄い青色の状態か、項目の背景色を目立つ色に変えたいのですが、どのようにすればいいでしょうか。


追記 1月10日20時19分

YAmaGNZ様が教えてくれたコードを
Dim imagerect As New Rectangle(New Point(e.Bounds.X + ((e.Bounds.Width - width1) / 2), e.Bounds.Y), New Size(width1, height1))
の直前に挿入したのですが、全部の項目が赤色になってしまいました。
また、Button2やButton3を押しても色が変わりません。(なんとなく該当の項目がちらついているようには見えます)
項目をマウスでクリックしても色が変わりません。予想では選択した項目だけ赤色でほかは無色になると思ってたのですが、そうはなっていないのでどこかがおかしいと思うのですがどこがおかしいのか分かりません。
プロパティの変更は
ListView1.MultiSelect = False
ぐらいしか変更してないと思います。コードの変更箇所だけ下に載せてみます

VB

1 Private Sub ListView1_DrawItem(sender As Object, e As DrawListViewItemEventArgs) Handles ListView1.DrawItem 2 e.DrawDefault = False 3 e.DrawBackground() 4 5 If thumbnail(e.ItemIndex) Is Nothing Then 6 Dim original As Image 7 Try 8 original = Bitmap.FromFile(jpgFiles(e.ItemIndex)) 9 Catch 10 original = My.Resources.Resource1._error 11 End Try 12 thumbnail(e.ItemIndex) = createThumbnail(original, Width, Height) 13 End If 14 15 'ここから追加------------------------------------------------------- 16 If (e.State And ListViewItemStates.Selected) <> 0 Then 17 '選択されているので選択色(例で赤とする)で塗りつぶす 18 e.Graphics.FillRectangle(Brushes.Red, e.Bounds) 19 Else 20 '選択されていないので通常色で塗りつぶす 21 Using b = New SolidBrush(e.Item.BackColor) 22 e.Graphics.FillRectangle(b, e.Bounds) 23 End Using 24 End If 25 'ここまで------------------------------------------------------------ 26 27 Dim imagerect As New Rectangle(New Point(e.Bounds.X + ((e.Bounds.Width - width1) / 2), e.Bounds.Y), New Size(width1, height1)) 28 e.Graphics.DrawImage(thumbnail(e.ItemIndex), imagerect) 29 'e.Item.ForeColor = Color.AliceBlue ' ←コメント状態を解除するとListView1が高速で点滅状態になる 30 'ListView1.Items(index).BackColor = Color.Aqua ' ←コメント状態を解除するとListView1が高速で点滅状態になる 31 32 e.DrawFocusRectangle() 33 'ListView1.Items(index).Focused = True '←コメントにしました 34 'ListView1.Items(index).Selected = True '←コメントにしました ' ←選択状態の時の青い色にならない 35 End Sub

再質問で申し訳ないのですがよろしくお願いいたします。


追記2 1月10日21時43分
Debug.WriteLine(e.State)
e.Stateの状態を調べた所、全部の項目が選択状態になっていました。なので全部赤色になってたわけです。なぜselectedになっているのかは分かりません。selectedの代わりにfocusで試してみた所focusは一つの項目だけ設定されてたので一つの項目だけが赤色になるようにできました。
If (e.State And ListViewItemStates.Selected) <> 0 Then

If (e.State And ListViewItemStates.Focused) <> 0 Then
あるいは
If e.ItemIndex = index Then
にすることでうまい具合に動作するようになりました。


追記3 1月10日22時06分
YAmaGNZ様がe.Item.Selectedの事を教えてくださり試してみた所うまく動作しました。
If (e.Item.Selected And ListViewItemStates.Selected) <> 0 Then
ありがとうございました。


追記4 1月10日22時29分
YAmaGNZ様のご指摘があり正しいのは
If e.Item.Selected Then
だとの事です。それと「選択されている」と判断するのであればFocusedやItemIndexではなく、Selectedを使用すべきとの事です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

OwnerDrawにするということは全て自分で描画しなくてはなりません。
なので背景の色を変えたいのであれば自分でその色に塗ることになります。

VBNET

1'アイテムの領域を黒で塗りつぶす 2e.Graphics.FillRectangle(Brushes.Black, e.Bounds)

その他のたいして呼び出す必要がなさそうな時、例えば

ListView1.Items(index).Selected = True
を実行した時や
ListView1.Items(index).BackColor = Color.Aqua
を実行した時なども呼び出されているっぽいです。

DrawItemイベントは再描画が必要な時に呼び出されます。
なのでSelected = Trueとしたときはそのアイテムが選択状態になります。
なので選択された状態を描画する必要があります。なのでDrawItemイベントが発生します。
また、BackColor = Color.Aquaと背景色を変更したのであれば、その背景色となるよう
描画する必要があります。なのでDrawItemイベントが発生します。

選択時に背景を変更するのであれば

VBNET

1If (e.State And ListViewItemStates.Selected) <> 0 Then 2 '選択されているので選択色(例で赤とする)で塗りつぶす 3 e.Graphics.FillRectangle(Brushes.Red, e.Bounds) 4Else 5 '選択されていないので通常色で塗りつぶす 6 Using b = New SolidBrush(e.Item.BackColor) 7 e.Graphics.FillRectangle(b, e.Bounds) 8 End Using 9End If

といった感じで自分で描画の処理を書いてください。

またDrawItemイベント内で
'e.Item.ForeColor = Color.AliceBlue ' ←コメント状態を解除するとListView1が高速で点滅状態になる
'ListView1.Items(index).BackColor = Color.Aqua ' ←コメント状態を解除するとListView1が高速で点滅状態になる
と再描画が必要になるようなプロパティを操作すると再度DrawItemが呼ばれることになります。
なのでそのような操作を行わないようにしましょう。

投稿2022/01/10 09:41

YAmaGNZ

総合スコア10294

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tada_tadaa

2022/01/10 11:29

YAmaGNZ様、回答ありがとうございます。 YAmaGNZ様の教えてくれたコードを試してみたのですが、うまくいかず分からなかったので質問欄に追記で変更箇所だけ載せてみました。再質問で申し訳ないのですが原因がお分かりになるのであれば教えていただけないでしょうか。
YAmaGNZ

2022/01/10 11:42

申し訳ありませんが、現在は動作を確認できない状況です。 なのでご自身でデバッガでステップ実行しながら各プロパティの値を確認しつつ、どのように動作しているかを確認してください。 また、リファレンスも確認するようにしてください。 コードに関しては https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.drawlistviewitemeventargs.state?view=netframework-4.8 などサンプルソースが載っていますのでそちらも参考にしてみてください。
tada_tadaa

2022/01/10 11:47

了解しました。各プロパティをよく確認する事にします。 分かりやすい回答をありがとうございました。
YAmaGNZ

2022/01/10 12:57

選択されているかの判断をe.Item.Selectedで判断してはどうですかね?
tada_tadaa

2022/01/10 13:05

回答をありがとうございます。 If (e.Item.Selected And ListViewItemStates.Selected) <> 0 Then で試してみた所うまく動作しました。質問欄に追記で ListViewItemStates.Focused を試したらうまくいったのでその方法を使う事にしたと書いたところでした。 また追記でe.Item.Selectedの事も書いておこうと思います。 とりあえず問題解決出来て良かったです。 ありがとうございました。
YAmaGNZ

2022/01/10 13:11

FocusedやItemIndex ですと意味が違いますので「選択されている」と判断するのであればSelectedを使用すべきかと思います。
tada_tadaa

2022/01/10 13:15

了解しました。選択を判断する場合はSelectedを使うようにします。
YAmaGNZ

2022/01/10 13:20

>If (e.Item.Selected And ListViewItemStates.Selected) <> 0 Then SelectedはBooleanなので If e.Item.Selected Then です
tada_tadaa

2022/01/10 13:28

了解しました。質問欄にも追記でその事を説明しておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問