Determining files selected from Explorer

I am looking for a way to determine what files have been selected from Windows Explorer.

For example, I would like to be able to select a range of files, right click, and from the Menu options, choose my application and fill a list box with the selected files.

Creating the context menu to launch my app is not a problem (by just making the appropriate "command" entry in the HKEY_CLASSES_ROOT registry key), but the problem is how do you know what is selected from Explorer?

If you do a drag and drop, you can just use the data object to iterate the files.  With no drag though, how can can you get this info out the operating system?

I think this might involve some serious APIs so how about 300 points?
carpbyteAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
wsh2Connect With a Mentor Commented:
1. Start a new Standard.Exe project
2. Copy and Paste the following into the Form1 code window.
3. Press F5 to run. A blank Form1 will appear on the screen. Open Windows Explorer and Copy some files to the clipboard. Click anywhere on Form1 and you will get a message as to how many Files are on the clipboard.. AND.. the IDE immediate window will be populated with the file names.
4. <smile>

<----- Code Begin ----->

Option Explicit

Private Const CF_HDROP = 15&
Private Declare Function CloseClipboard Lib "USER32" _
   () As Long
Private Declare Function DragQueryFile Lib "shell32.dll" Alias "DragQueryFileA" _
   (ByVal hDrop As Long, ByVal UINT As Long, ByVal lpStr As String, ByVal ch As Long) _
   As Long
Private Declare Function GetClipboardData Lib "USER32" _
   (ByVal wFormat As Long) _
   As Long
Private Declare Function IsClipboardFormatAvailable Lib "USER32" _
    (ByVal wFormat As Long) As Long
Private Declare Function OpenClipboard Lib "USER32" _
   (ByVal hWnd As Long) As Long

Private Sub Form_Click()

   Dim lngFileCount As Long
   Dim strFileNames() As String
   Dim lngIndex As Long
   If xGetClipboardFileList(strFileNames(), lngFileCount) _
   Then
      MsgBox (lngFileCount & " Files are on the Clipboard")
      For lngIndex = LBound(strFileNames) To UBound(strFileNames)
         Debug.Print strFileNames(lngIndex)
      Next lngIndex
   Else
      MsgBox ("No files are on the clipboard")
   End If
   
End Sub

Public Function xGetClipboardFileList _
(ByRef strFileNames() As String, _
ByRef lngFileCount As Long) _
As Boolean

   Dim strFileName As String
   Dim lngIndex As Long
   Dim lngNull As Long
   Dim lngReturn As Long
   
'  Is data available
   lngReturn = IsClipboardFormatAvailable(CF_HDROP)
   If lngReturn = 0 _
   Then
      Exit Function
   End If
   
'  Open the clipboard:
   lngReturn = OpenClipboard(0&)
   If lngReturn <= 0 _
   Then
      Exit Function
   End If
   
   ' Get handle to CF_HDROP if any:
   lngReturn = GetClipboardData(CF_HDROP)
   If lngReturn = 0 _
   Then
      GoTo Tag999
   End If
   
   lngFileCount = DragQueryFile(lngReturn, -1&, "", 0)
   If lngFileCount <= 0 _
   Then
      GoTo Tag999
   End If
   
   ' Allocate space for return and working variables.
   ReDim strFileNames(1 To lngFileCount) As String
   strFileName = String$(255, 0)
   
   ' Retrieve each filename in Dropped Filelist.
   For lngIndex = 1 To lngFileCount
      DragQueryFile lngReturn, lngIndex - 1, strFileName, Len(strFileName)
      lngNull = InStr(strFileName, vbNullChar)
      If (lngNull <> 0) Then
         strFileNames(lngIndex) = Left$(strFileName, lngNull - 1)
      Else
         strFileNames(lngIndex) = strFileName
      End If
   Next lngIndex
   
   xGetClipboardFileList = True
   
Tag999:
       
   CloseClipboard

End Function

<----- Code End ----->


0
 
TimCotteeHead of Software ServicesCommented:
Ok, this is both simple and complex.

The simple part:

The file name selected in explorer is passed as a parameter to the application you specify in your "command" entry. Therefore you can parse the Command() in VB to get the file name.

The complex part:

Depends on how you see it. If you select multiple files, an instance of your application is opened for each file, you would need to determine whether your app was already running using app.Previnstance and if so pass the filename received by this instance to the original one.

0
 
TimCotteeHead of Software ServicesCommented:
Try this, project and form file in text. Create executable TF.exe, this does as I described, if there is an existing instance of tf, it uses DDE to send the filename to the original instance leaving you with a list box containing the files selected in explorer.

TF.VBP

Type=Exe
Form=frmListFiles.frm
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINNT\System32\StdOle2.Tlb#OLE Automation
IconForm="frmListFiles"
Startup="frmListFiles"
HelpFile=""
Title="TF"
ExeName32="TF.exe"
Command32=""
Name="TF"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionCompanyName="TopCat"
VersionFileDescription="TF"
VersionProductName="TF"
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1

frmListFiles.frm

VERSION 5.00
Begin VB.Form frmListFiles
   Caption         =   "Form1"
   ClientHeight    =   3195
   ClientLeft      =   60
   ClientTop       =   345
   ClientWidth     =   4680
   LinkMode        =   1  'Source
   LinkTopic       =   "Master"
   ScaleHeight     =   3195
   ScaleWidth      =   4680
   StartUpPosition =   3  'Windows Default
   Begin VB.TextBox txtNewFile
      Height          =   495
      Left            =   2880
      LinkItem        =   "txtFile"
      LinkTopic       =   "TF|Master"
      TabIndex        =   2
      Text            =   "Text1"
      Top             =   1320
      Visible         =   0   'False
      Width           =   1575
   End
   Begin VB.TextBox txtFile
      Height          =   495
      Left            =   2880
      TabIndex        =   1
      Text            =   "Text1"
      Top             =   480
      Visible         =   0   'False
      Width           =   1575
   End
   Begin VB.ListBox List1
      Height          =   2790
      Left            =   240
      TabIndex        =   0
      Top             =   120
      Width           =   2415
   End
End
Attribute VB_Name = "frmListFiles"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Dim strCommand As String

Private Sub Form_Load()
    strCommand = Command()
    If App.PrevInstance Then
        LinkTopic = "NOTMASTER"
        PokeFileToPrev
        End
    End If
    List1.AddItem strCommand
End Sub

Private Sub txtFile_Change()
    List1.AddItem txtFile.Text
End Sub

Private Sub PokeFileToPrev()
    txtNewFile.Text = strCommand
    txtNewFile.LinkMode = vbLinkManual
    txtNewFile.LinkPoke
End Sub

Private Sub txtFile_LinkNotify()
    List1.AddItem txtFile.Text
End Sub


0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
wsh2Commented:
Tim:
If he doesn't have NT.. this could be a problem:

Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINNT\System32\StdOle2.Tlb#OLE Automation

0
 
TimCotteeHead of Software ServicesCommented:
True, but then just change the directory to the correct location for StdOle2.Tlb or remove this line before opening the project and add back the reference from the references dialog.

Thanks though for pointing it out, I didn't see that!
0
 
carpbyteAuthor Commented:
Combined, these two solutions are pretty much what I'm looking for.

Split the points?

0
 
wsh2Commented:
If TimCottee agrees, splitting points is fine by me.. <smile>.
0
 
wsh2Commented:
Just so you know, to split points..
Ask support to reduce the points on the current question, then allocate the additional points to a targeted Question to the party you want to receive them. (Eg. Question Subject = "For TimCottee" or "Wsh2".. <blush>). Here is the link for Customer Service.

http://www.experts-exchange.com/Customer_Service/Experts_Exchange/

0
 
carpbyteAuthor Commented:
Thanks for the info.

I'll award the points shortly.

CarpByte.
0
 
bhamiltoCommented:
There is a totally different solution using the Windows event hook and the Accessibility DLL (oleacc.dll) if you are interested.

1) Advantages:
- Uses the event hook so is totally assynchronous.  For example, a running VB program can detect when explorer files are selected or unselected and get file names using oleacc.dll.  This can be an invisible background process if you wish.
- The same approach can be used to detect/identify a broad range of events in any process or set of processes (e.g. focus changes, menu selection, etc., etc.)
- Works with Win 9x, NT4 or later

2) Disadvantages:
- Requires oleacc.dll (about 150K)

If you want to start an app with explorer file names as parameters then the wsh2/TimCottee solution is great.  I won't elaborate on this unless it suits your needs better than the solution offered.

Good luck - Bob Hamilton
0
 
wsh2Commented:
bhamilto:
OLEACC.DLL.. Hmmmm.. never looked at (or thought of) that before. From what I just briefly scanned on this.. it seems that MS has been quietly using OLEACC to add functionality to its products as well (ie. Office).

Welp.. thanks to you, I'll have plenty to read when I go to bed tonight.. THANK YOU for a very intriguing tip and then HEAVY (it needs a Redistribution kit.. <sheesh>) eyed sleep.. <smile>.
0
 
bhamiltoCommented:
wsh2

Its not that MS is keeping it secret.  The problem is that it comes under the "Accessibility" umbrella so who would think to look for this sort of functionallity there?  Somebody here on EE answered a similar question I had a few months back with this general solution.  It works great - you can do things that would otherwise require expensive 3rd party software like Desawares SpyWorks.

Most MS and a lot of 3rd party software supports it although you can't get much detail form VB5 apps.

The other disadvantage that I forgot to mention is that there is a lot to read (as you'll soon find out).  Its actually quite easy to use and the samples are easy to follow.  The VB samples use (the non-event driven) "AccessibleObjectFromPoint" API, but I had no problem converting a C sample to use the event hook and "AccessibleObjectFromEvent"

Happy dreams - Bob Hamilton
0
 
carpbyteAuthor Commented:
Thank you for the additional info. As I am always open to an education, if you have a workable code sample solution, I'll be more than happy to "rephrase" the question as a new one and thereby "open it".

As I have already agreed to the initial wsh2/TimCottee solutions I'd like to be sure they get their points first.

Thanks.

Carpbyte.

0
 
darinwCommented:
Community Support has reduced points from 300 to 150
0
 
darinwCommented:
Hi carpbyte,

I have reduced the points on this question to one half. Please accept one of the Experts comments as an answer. Remember, the Accept Comment as Answer button is in the header of the comment.

For the second Expert, post a question in this topic area. The new question title should be 'For ExpertName - 10330014'.

For your convenience, you can use this link to create the new question:

http://www.experts-exchange.com/bin/NewQForm?ta=31

darinw
Customer Service
0
 
carpbyteAuthor Commented:
Thanks for the code & splitting the points.

carpbyte.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.