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

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

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

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

解決済

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

tada_tadaa
tada_tadaa

総合スコア100

VB.NET

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

1回答

0評価

0クリップ

351閲覧

投稿2022/01/10 09:04

編集2022/01/10 13:34

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

vb

Public Class Form1 Public imageDir As String = "C:\Users\user\Pictures" ' 画像ディレクトリ Public jpgFiles As String() = System.IO.Directory.GetFiles(imageDir, "*.jpg", IO.SearchOption.TopDirectoryOnly) Public thumbnail(jpgFiles.Length) As Image Public width1 As Integer = 100 Public height1 As Integer = 80 Public Imagelist1 As New ImageList Public index As Integer = 0 ' 幅w、高さhのImageオブジェクトを作成 Function createThumbnail(ByVal image As Image, ByVal w As Integer, ByVal h As Integer) As Image Dim canvas As New Bitmap(w, h) Dim g As Graphics = Graphics.FromImage(canvas) g.FillRectangle(New SolidBrush(Color.White), 0, 0, w, h) Dim fw As Double = CDbl(w) / CDbl(image.Width) Dim fh As Double = CDbl(h) / CDbl(image.Height) Dim scale As Double = Math.Min(fw, fh) Dim w2 As Integer = CInt(image.Width * scale) Dim h2 As Integer = CInt(image.Height * scale) g.DrawImage(image, (w - w2) \ 2, (h - h2) \ 2, w2, h2) g.Dispose() Return canvas End Function Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ListView1.Enabled = True ListView1.Visible = True ListView1.VirtualMode = True ListView1.OwnerDraw = True Imagelist1.ImageSize = New Size(width1, height1) ListView1.LargeImageList = Imagelist1 ListView1.VirtualListSize = jpgFiles.Length For i As Integer = 0 To jpgFiles.Count - 1 thumbnail(i) = Nothing Next End Sub Private Sub ListView1_RetrieveVirtualItem(sender As Object, e As RetrieveVirtualItemEventArgs) Handles ListView1.RetrieveVirtualItem e.Item = New ListViewItem(jpgFiles(e.ItemIndex), e.ItemIndex) End Sub Private Sub ListView1_DrawItem(sender As Object, e As DrawListViewItemEventArgs) Handles ListView1.DrawItem e.DrawDefault = False e.DrawBackground() If thumbnail(e.ItemIndex) Is Nothing Then Dim original As Image Try original = Bitmap.FromFile(jpgFiles(e.ItemIndex)) Catch original = My.Resources.Resource1._error End Try thumbnail(e.ItemIndex) = createThumbnail(original, Width, Height) End If Dim imagerect As New Rectangle(New Point(e.Bounds.X + ((e.Bounds.Width - width1) / 2), e.Bounds.Y), New Size(width1, height1)) e.Graphics.DrawImage(thumbnail(e.ItemIndex), imagerect) 'e.Item.ForeColor = Color.AliceBlue ' ←コメント状態を解除するとListView1が高速で点滅状態になる 'ListView1.Items(index).BackColor = Color.Aqua ' ←コメント状態を解除するとListView1が高速で点滅状態になる e.DrawFocusRectangle() ListView1.Items(index).Focused = True ListView1.Items(index).Selected = True ' ←選択状態の時の青い色にならない End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click index = index - 1 If index < 0 Then index = 0 ListView1.Items(index).Focused = True ListView1.Items(index).Selected = True ' ←選択状態の時の青い色にならない ListView1.Items(index).BackColor = Color.Aqua ' ←色が変わらない End Sub Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click index = index + 1 If index > ListView1.Items.Count - 1 Then index = ListView1.Items.Count - 1 ListView1.Items(index).Focused = True ListView1.Items(index).Selected = True ' ←選択状態の時の青い色にならない ListView1.Items(index).BackColor = Color.Aqua ' ←色が変わらない End Sub Private Sub ListView1_ItemActivate(sender As Object, e As EventArgs) Handles ListView1.ItemActivate ListView1.Items(index).BackColor = Color.Aqua ' ←色が変わらない End Sub Private Sub ListView1_VirtualItemsSelectionRangeChanged(sender As Object, e As ListViewVirtualItemsSelectionRangeChangedEventArgs) Handles ListView1.VirtualItemsSelectionRangeChanged ListView1.Items(e.EndIndex).BackColor = Color.Aqua ' ←色が変わらない End Sub End Class

フォームには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

Private Sub ListView1_DrawItem(sender As Object, e As DrawListViewItemEventArgs) Handles ListView1.DrawItem e.DrawDefault = False e.DrawBackground() If thumbnail(e.ItemIndex) Is Nothing Then Dim original As Image Try original = Bitmap.FromFile(jpgFiles(e.ItemIndex)) Catch original = My.Resources.Resource1._error End Try thumbnail(e.ItemIndex) = createThumbnail(original, Width, Height) End If 'ここから追加------------------------------------------------------- If (e.State And ListViewItemStates.Selected) <> 0 Then '選択されているので選択色(例で赤とする)で塗りつぶす e.Graphics.FillRectangle(Brushes.Red, e.Bounds) Else '選択されていないので通常色で塗りつぶす Using b = New SolidBrush(e.Item.BackColor) e.Graphics.FillRectangle(b, e.Bounds) End Using End If 'ここまで------------------------------------------------------------ Dim imagerect As New Rectangle(New Point(e.Bounds.X + ((e.Bounds.Width - width1) / 2), e.Bounds.Y), New Size(width1, height1)) e.Graphics.DrawImage(thumbnail(e.ItemIndex), imagerect) 'e.Item.ForeColor = Color.AliceBlue ' ←コメント状態を解除するとListView1が高速で点滅状態になる 'ListView1.Items(index).BackColor = Color.Aqua ' ←コメント状態を解除するとListView1が高速で点滅状態になる e.DrawFocusRectangle() 'ListView1.Items(index).Focused = True '←コメントにしました 'ListView1.Items(index).Selected = True '←コメントにしました ' ←選択状態の時の青い色にならない 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を使用すべきとの事です。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

VB.NET

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