tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルListBox MultiExtended 選択行のIndex
記事No10776
投稿日: 2012/04/09(Mon) 18:32
投稿者じょば
OS : Windwos XP , Windows 7
言語:Visual Basic 2010 Express

ListBox にて、選択されている行のIndexを取得する方法について、
御質問があります。

ListBox は、 SelectionMode = MultiExtended を指定しています。

処理本体は、ListBoxでクリックされた行に設定しているJPEGファイル名
を取得して、対応する画像をPictureBoxに表示するという処理です。

一つずつクリックして表示する場合は、想定した動作を実現しています。

想定外の部分についてご説明します。
元々VB6で作成していたのですが、複数選択のListBoxでも、VB6では、
SelectedIndexで、フォーカスのあるIndex値を返してくれていましたが、
.NETでは、任意のIndexを返すようで、具体的にはSelectedIndexies(0)の
Indexを返すようです。

従いまして、VB6で作成していたプログラムでは、複数行選択して表示
される画像は、最後に選択された画像が表示されていましたが、.NETでは
SelectedIndexies(0)の画像が表示されるだけです。

≪現在の対処≫

ListBoxで選択された最後の行を調べて、似たような機能を実現できる
ように自作コードを書いています。

≪現在の問題点≫

キーボードで、Shift + 下矢印キー を使って複数行を選択する場合、
最後の行まで選択した時点で、SelectedIndexChanged イベントが発生
するのは当然ですが、最後の行まで選択されている状態で、もう一度
Shift + 下矢印キー を押すと、選択状態は変わらないのに、
SelectedIndexChanged イベントが発生してしまうので、自作コードが
想定どおりに動かない場合があります。

イベント発生は納得できないのですが、仕様であれば仕方がありません。

≪御質問内容≫

ListBox に SelectionMode = MultiExtended をしている場合、複数選択
した状態で、フォーカスのある行のIndexを取得する方法はありません
でしょうか?

色々調べてはみたのですが、現時点で見つけられていません。

これがあれば1行で済むのですが、不可能なら自作コードを改造します。

[ツリー表示へ]
タイトルRe: ListBox MultiExtended 選択行のIndex
記事No10777
投稿日: 2012/04/09(Mon) 19:28
投稿者魔界の仮面弁士
> .NETでは、任意のIndexを返すようで、具体的にはSelectedIndexies(0)の
> Indexを返すようです。
SelectionMode プロパティが単一選択モードのときには
LB_GETCURSEL をSendMessage して取得していますが、
複数選択時には、御推察通りの動きになっているようです。


> ListBoxで選択された最後の行を調べて、似たような機能を実現できる
> ように自作コードを書いています。

ListBox を継承して、LB_GETCURSEL を SendMessage するプロパティを用意するか、
あるいは NativeWindow クラス経由で LB_GETCURSEL してやれば良さそうです。

なお LB_GETCURSELは、VB6 の ListBox.ListIndex プロパティと同様に、
フォーカスのあるIndex値を選択されているかどうかに関係なく返します。

Public Class Form1
    Inherits System.Windows.Forms.Form
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Label1.Text = CStr(ListBox1.GetSelectedIndex()) _
           & vbCrLf & CStr(ListBox1.SelectedIndex)
    End Sub
End Class

Module ListBoxExtensions
    <System.Runtime.CompilerServices.Extension()> _
    Public Function GetSelectedIndex(lb As ListBox) As Integer
        Dim m As New Message()
        m.HWnd = lb.Handle
        m.Msg = &H188   'LB_GETCURSEL
        Dim n As New NativeWindow()
        n.AssignHandle(lb.Handle)
        n.DefWndProc(m)
        n.ReleaseHandle()
        Return m.Result
    End Function
End Module

[ツリー表示へ]
タイトルRe^2: ListBox MultiExtended 選択行のIndex
記事No10778
投稿日: 2012/04/09(Mon) 19:45
投稿者じょば
魔界の仮面弁士様、レスありがとうございます。

> ListBox を継承して、LB_GETCURSEL を SendMessage するプロパティを用意するか、
> あるいは NativeWindow クラス経由で LB_GETCURSEL してやれば良さそうです。

サンプルコードまで書いて頂き、ありがとうございます。
.NET初心者レベルではありますが、内容を吟味してテストして
みたいと思います。


> なお LB_GETCURSELは、VB6 の ListBox.ListIndex プロパティと同様に、
> フォーカスのあるIndex値を選択されているかどうかに関係なく返します。

あ、VB6のListIndexも、選択に関係ない値だったのですね。
すみません、ひょっとしたらVB6で作っていたプログラムは単純に、ListIndex
を使っていたので、別の所でバグがあるかもしれません。

クリックにより選択が追加されたときは問題ありませんが、クリックで
選択状態を解除した場合、選択されていないのに、ListIndexの値で画像を
表示するとマズイですね。

という事は、いずれにせよ何らかの制御が必要という事になりそうです。

まずは、魔界の仮面弁士様に書いて頂いたサンプルを参考にさせて頂き、
組み込んでテストしてみたいと思います。

[ツリー表示へ]
タイトルRe^2: ListBox MultiExtended 選択行のIndex
記事No10779
投稿日: 2012/04/10(Tue) 11:33
投稿者じょば
魔界の仮面弁士様

ご指導いただいたコードで、フォーカスのある行のIndexを
取得する事ができるようになりました。

後は、上のレスでも書きましたように、クリックによって、
選択されている状態が解除された場合を考慮した制御が、
別途必要になりますが、それは自作で書きます。

ありがとうございました m(_ _)m

[ツリー表示へ]