Home All Groups Group Topic Archive Search About

Can I loop through only SELECTED items in a multi-select FileListBox?

Author
13 Mar 2009 10:39 AM
MM
At present I'm looping through all files and testing if
File1.Selected(i)

But if only a few files are selected, that's a lot of redundant
testing wasted.

It would be much better if I could loop through ONLY the selected
files, ignoring all the non-selected ones.

One way would be to transfer the selected subset to a hidden listbox,
array, or collection, then loop through that. Maybe there's an API
call that copies only selected items?

MM

Author
13 Mar 2009 1:16 PM
MikeD
Show quote Hide quote
"MM" <kylix***@yahoo.co.uk> wrote in message news:cgdkr49okp0vupp1ksftamjmhh9nbpueab@4ax.com...
> At present I'm looping through all files and testing if
> File1.Selected(i)
>
> But if only a few files are selected, that's a lot of redundant
> testing wasted.
>
> It would be much better if I could loop through ONLY the selected
> files, ignoring all the non-selected ones.
>
> One way would be to transfer the selected subset to a hidden listbox,
> array, or collection, then loop through that. Maybe there's an API
> call that copies only selected items?


VB does not provide a way to do this.  You have to loop through all items and check each one's Selected property.

But yes, there is an API message you can send: LB_GETSELITEMS.  This will fill a buffer, pointed to by lParam, with the item numbers
of the selected items.

At least I THINK this message should work with a FileListBox...not 100% positive about that though.

--
Mike
Author
13 Mar 2009 1:40 PM
MikeD
"MikeD" <nob***@nowhere.edu> wrote in message news:OrYa039oJHA.3572@TK2MSFTNGP05.phx.gbl...
>
> But yes, there is an API message you can send: LB_GETSELITEMS.  This will fill a buffer, pointed to by lParam, with the item
> numbers of the selected items.
>
> At least I THINK this message should work with a FileListBox...not 100% positive about that though.
>


I had a few minutes so I threw this together real quick.  Add a FileListBox and TextBox to a form.  Keep default names.  Copy and
paste this code:

Option Explicit

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Private Const LB_GETSELITEMS = &H191

Private Sub Form_Click()

    Dim Buffer()        As Long
    Dim lNumSel         As Long
    Dim sText           As String
    Dim Index           As Long

    'The array must be large enough for all possible selected items
    ReDim Buffer(0 To File1.ListCount -1)

    lNumSel = SendMessage(File1.hwnd, LB_GETSELITEMS, File1.ListCount, Buffer(0))

    For Index = 0 To lNumSel - 1
        sText = sText & File1.List(Buffer(Index)) & vbCrLf
    Next

    Text1.Text = sText

End Sub


Note that the buffer array MUST be of type Long.

--
Mike
Author
13 Mar 2009 4:14 PM
MM
Show quote Hide quote
On Fri, 13 Mar 2009 09:40:34 -0400, "MikeD" <nob***@nowhere.edu>
wrote:

>
>"MikeD" <nob***@nowhere.edu> wrote in message news:OrYa039oJHA.3572@TK2MSFTNGP05.phx.gbl...
>>
>> But yes, there is an API message you can send: LB_GETSELITEMS.  This will fill a buffer, pointed to by lParam, with the item
>> numbers of the selected items.
>>
>> At least I THINK this message should work with a FileListBox...not 100% positive about that though.
>>
>
>
>I had a few minutes so I threw this together real quick.  Add a FileListBox and TextBox to a form.  Keep default names.  Copy and
>paste this code:
>
>Option Explicit
>
>Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
>(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
>
>Private Const LB_GETSELITEMS = &H191
>
>Private Sub Form_Click()
>
>    Dim Buffer()        As Long
>    Dim lNumSel         As Long
>    Dim sText           As String
>    Dim Index           As Long
>
>    'The array must be large enough for all possible selected items
>    ReDim Buffer(0 To File1.ListCount -1)
>
>    lNumSel = SendMessage(File1.hwnd, LB_GETSELITEMS, File1.ListCount, Buffer(0))
>
>    For Index = 0 To lNumSel - 1
>        sText = sText & File1.List(Buffer(Index)) & vbCrLf
>    Next
>
>    Text1.Text = sText
>
>End Sub
>
>
>Note that the buffer array MUST be of type Long.

Pretty darned cool! Thanks, that did EXACTLY the kind of thing I'm
looking for.

MM
Author
13 Mar 2009 3:09 PM
mayayana
> At present I'm looping through all files and testing if
> File1.Selected(i)
>
> But if only a few files are selected, that's a lot of redundant
> testing wasted.
>

    What kind of selected items? You mean items
in Explorer? See here for sample code and explanation
that covers your options:
  www.jsware.net/jsware/vbcode.php5#shlop

  There are various pros and cons with the different
methods: Active Accessibility is tedious and complex.
The Shell object is hokey and undependable. ...Etc.
(Explained in the download.)

  But for most purposes you can use Shell. Get a Windows
collection from that, which reperesents all running instances
of IE and Explorer. (An idiocy left over from the Active Desktop
boondoggle.) Officially all objects in the collection are IE
instances, and you can use a limited set of IE properties. For
instance, you can use LocationURL as a way to find the folder
of interest. But an Explorer folder returns a ShellFolderView for
the IE.document, while an IE instance returns an actual document
object.

   Once you have the ShellFolderView the rest is fairly easy. The
SelectedItems property (they call it a "method") returns a collection
of FolderItem objects. Each of those has a number of properties.
(IsFolder, Name, Path, Size, etc.)

  Below is a simple version of the code, but be aware that
ShellFolderView doesn't always return all files. (Explained in download
linked above.)

Set a reference to Microsoft Shell Controls and Automation.
Set a reference to Microsoft Internet Controls (shdocvw)
In the Object Browser, right-click the list and select
"Show Hidden Members". (Otherwise you won't find IWebBrowserApp
in Intellisense.)

Private Sub Command1_Click()
  Dim SH As Shell
    '-- Shell seems to be an awkward mix of dual
    '-- and dispatch-only interfaces:
  Dim Wins As Object
  Dim IE As IWebBrowserApp
  Dim SV As ShellFolderView
  Dim fi As FolderItem
  Dim SI As Object 'selected items
  Dim sPath As String, ThisPath As String

  ThisPath = "C:\Windows"
  Set SH = New Shell
  Set Wins = SH.Windows
    For Each IE In Wins
      sPath = IE.LocationURL
        CleanPath sPath
        If UCase$(sPath) = UCase$(ThisPath) Then
           Set SV = IE.Document
           Set SI = SV.SelectedItems
              For Each fi In SI
                Debug.Print fi.Path
              Next
           Set SI = Nothing
           Set SV = Nothing
         Exit For
        End If
    Next
  Set Wins = Nothing
  Set SH = Nothing
End Sub

'-- In accordance with the ridiculous design of returning
'-- both folders and IE instances as IE objects, the folder
'-- path comes back as a URL! So this code below is needed.

Private Sub CleanPath(ByRef sPathIn As String)
  Dim Pt1 As Long
    sPathIn = Replace(sPathIn, "/", "\")
    sPathIn = Replace(sPathIn, "%20", " ")  '-- fix spaces.
    Pt1 = InStrRev(sPathIn, ":")
    If Pt1 > 2 Then sPathIn = Right$(sPathIn, (Len(sPathIn) - (Pt1 - 2)))
'-- clip "file///"
End Sub
Author
13 Mar 2009 3:15 PM
Jeff Johnson
"MM" <kylix***@yahoo.co.uk> wrote in message
news:cgdkr49okp0vupp1ksftamjmhh9nbpueab@4ax.com...

> At present I'm looping through all files and testing if
> File1.Selected(i)
>
> But if only a few files are selected, that's a lot of redundant
> testing wasted.

Have you timed it? Computers are really fast these days. Walking through a
list and testing a Boolean is not going to make your machine seem like it's
slogging through the La Brea tar pits....

Also, I just have to say it: The xxxListBox controls are ANCIENT technology
and should not be used in a modern application. Do you really want to give
your program that wonderful Windows 3.1 look and feel...?
Author
13 Mar 2009 7:52 PM
Rick Raisley
Are you suggesting a ListView, instead? (I've found them a pain to work
with, and most times don't really need their extra features). Anyhow, the
ListBox control doesn't look so bad with a Manifest file, IMHO.

--
Regards,

Rick Raisley
heavymetal-A-T-bellsouth-D-O-T-net

Show quoteHide quote
"Jeff Johnson" <i.get@enough.spam> wrote in message
news:O4hI75%23oJHA.3876@TK2MSFTNGP02.phx.gbl...
> "MM" <kylix***@yahoo.co.uk> wrote in message
> news:cgdkr49okp0vupp1ksftamjmhh9nbpueab@4ax.com...
>
>> At present I'm looping through all files and testing if
>> File1.Selected(i)
>>
>> But if only a few files are selected, that's a lot of redundant
>> testing wasted.
>
> Have you timed it? Computers are really fast these days. Walking through a
> list and testing a Boolean is not going to make your machine seem like
> it's slogging through the La Brea tar pits....
>
> Also, I just have to say it: The xxxListBox controls are ANCIENT
> technology and should not be used in a modern application. Do you really
> want to give your program that wonderful Windows 3.1 look and feel...?
>
Author
14 Mar 2009 12:33 AM
MikeD
"Jeff Johnson" <i.get@enough.spam> wrote in message
news:O4hI75%23oJHA.3876@TK2MSFTNGP02.phx.gbl...
>
> Also, I just have to say it: The xxxListBox controls are ANCIENT
> technology and should not be used in a modern application. Do you really
> want to give your program that wonderful Windows 3.1 look and feel...?


I was going to provide the same advice, but then I thought that maybe he was
using ONLY the FileListBox or it was for personal use only and the UI really
didn't matter.  IMO, it's the combination of the FileListBox, DriveListBox,
and DirListBox that makes an app look like a Win3.x app. If using those 3
controls, then yeah, I agree with you 100% (and you should instead use a
combination of the TreeView and ListView for the Explorer style).

--
Mike
Author
14 Mar 2009 9:02 AM
MM
Show quote Hide quote
On Fri, 13 Mar 2009 20:33:35 -0400, "MikeD" <nob***@nowhere.edu>
wrote:

>
>"Jeff Johnson" <i.get@enough.spam> wrote in message
>news:O4hI75%23oJHA.3876@TK2MSFTNGP02.phx.gbl...
>>
>> Also, I just have to say it: The xxxListBox controls are ANCIENT
>> technology and should not be used in a modern application. Do you really
>> want to give your program that wonderful Windows 3.1 look and feel...?
>
>
>I was going to provide the same advice, but then I thought that maybe he was
>using ONLY the FileListBox or it was for personal use only and the UI really
>didn't matter.  IMO, it's the combination of the FileListBox, DriveListBox,
>and DirListBox that makes an app look like a Win3.x app. If using those 3
>controls, then yeah, I agree with you 100% (and you should instead use a
>combination of the TreeView and ListView for the Explorer style).

Sadly, such "advice", as from Jeff, is often misconstrued as
admonishment. A bit like the Irish chap who responded in all
seriousness to an enquiry from a passing motorist as to how to get to
Dublin, "Well, if I were you, I wouldn't start from here!"

You, MikeD, on the other hand just took my request at face value and
came up with a solution. Bravo!

Taking a TreeView and ListView to a trivial application is like taking
a steam hammer to crack open a peanut. Yeah, the job can be done, but
hitting it with a shoe also works.

MM