File or folder selected in windows explorer

Just starting out? Need help? Post your questions and find answers here.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: File or folder selected in windows explorer

Post by RASHAD »

Hi KCC
- Select your Explorer files
- Drag & Drop
That is it

Texted with Windows 10 x64

Code: Select all


LoadFont(0,"Georgia",12)
If OpenWindow(0,0,0,600,400,"Get Selected Files",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  EditorGadget(1,10,10,580,330)
  SetGadgetFont(1,FontID(0)) 
  CanvasGadget(2,280,350,40,40)
  
  StartDrawing(CanvasOutput(2))
    Circle(20,20,20,$F65533)
    Circle(20,20,5,$69FDF9)
  StopDrawing()
  
  tx = TextGadget(#PB_Any,200,360,100,24,"Drop here")
  SetGadgetFont(tx,FontID(0))
  EnableGadgetDrop(2,#PB_Drop_Files, #PB_Drag_Copy)
  EnableGadgetDrop(2,#PB_Drop_Text, #PB_Drag_Copy)  

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
        
    Case #PB_Event_GadgetDrop       
        If EventDropType() = #PB_Drop_Files
          AddGadgetItem(1,-1,EventDropFiles())
        EndIf
        If EventGadget() = 2
          If EventDropType() = #PB_Drop_Text            
            AddGadgetItem(1,-1,EventDropText())
          EndIf
          If EventDropType() = #PB_Drop_Files
          EndIf
        EndIf
  EndSelect
Until Quit = 1
EndIf

Egypt my love
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: File or folder selected in windows explorer

Post by Kwai chang caine »

@JHPJHP
I have tested it and like BarryG it's a little bit long, but that works 8)
Thanks for your link and your works

@RASHAD
Thanks a lot for your code, it works 8)
But i search a way for detecting the path of the file or the directory selected, without do something
Just run the code and see what file is selected in each windows explorer open :wink:
At the first view that appears simple...but apparently it's very hard to do that in PB only :|

JHPJHP found a solution, but not really quick :| , based on LUIS code 8)
viewtopic.php?p=390974#p390974

Code: Select all

EnableExplicit

CompilerIf (#PB_Compiler_Unicode = 0)
 CompilerError "Turn on: Create Unicode executable"
CompilerEndIf

Macro DEFINE_GUID(Name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
  CompilerIf Defined(Name, #PB_Variable)
  If SizeOf(Name) = SizeOf(GUID)
    Name\Data1    = l
    Name\Data2    = w1
    Name\Data3    = w2
    Name\Data4[0] = b1
    Name\Data4[1] = b2
    Name\Data4[2] = b3
    Name\Data4[3] = b4
    Name\Data4[4] = b5
    Name\Data4[5] = b6
    Name\Data4[6] = b7
    Name\Data4[7] = b8
  EndIf
  CompilerEndIf
EndMacro

Global IID_IAccessible.GUID
DEFINE_GUID(IID_IAccessible, $618736e0, $3c3d, $11cf, $81, $0c, $00, $aa, $00, $38, $9b, $71)

Global IID_IEnumVARIANT.GUID ; 00020404-0000-0000-C000-000000000046
DEFINE_GUID(IID_IEnumVARIANT, $00020404, $0000, $0000, $c0, $00, $00, $00, $00, $00, $00, $46)
;http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.comtypes.ienumvariant.aspx


Prototype.l ProtoAccessibleObjectFromWindow(hwnd.i,dwObjectID.l, riid, *ppvObject)
Global AccessibleObjectFromWindow.ProtoAccessibleObjectFromWindow

Prototype.l ProtoAccessibleChildren(*paccContainer,iChildStart.l,cChildren.l,*rgvarChildren,*pcObtained)
Global AccessibleChildren.ProtoAccessibleChildren


Define hdll, hwnd
Define *Accessible.IAccessible

CoInitialize_(0)

hdll=OpenLibrary(#PB_Any,"Oleacc.dll")

AccessibleObjectFromWindow = GetFunction(hdll,"AccessibleObjectFromWindow")
AccessibleChildren = GetFunction(hdll,"AccessibleChildren")

#NAVDIR_DOWN = 2
#NAVDIR_FIRSTCHILD = 7
#NAVDIR_LASTCHILD = 8
#NAVDIR_LEFT = 3
#NAVDIR_NEXT = 5
#NAVDIR_PREVIOUS = 6
#NAVDIR_RIGHT = 4
#NAVDIR_UP = 1

#CHILDID_SELF = 0

;http://msdn.microsoft.com/en-us/library/windows/desktop/dd318474(v=vs.85).aspx
#SELFLAG_TAKEFOCUS = 1
#SELFLAG_TAKESELECTION = 2
     
Declare    ProcessChild (*aAccessible.IAccessible, aOffset$, *aChild.VARIANT)
Declare    DisplayInfo (*aAccessible.IAccessible, aOffset$ )

Procedure.s GetBSTR (*BSTR_wsText) ; needed to trap NULL BSTR (seem it's possible and valid)
  If *BSTR_wsText
    ProcedureReturn PeekS(*BSTR_wsText)
  EndIf
  ProcedureReturn ""
EndProcedure

Procedure ProcessChild (*aAccessible.IAccessible, aOffset$, *aChild.VARIANT)
 Protected *ChildAccessible.IAccessible
 Protected *ChildDispatch.IDispatch
 
 Select *aChild\vt
    Case #VT_I4 ; varInteger (was #VT_INT, wrong, see http://delphi.about.com/library/weekly/aa122104a.htm)
        *aAccessible\get_accChild(*aChild, @*ChildDispatch)
    Case #VT_DISPATCH ; varDispatch
        *ChildDispatch = *aChild\pdispVal
 EndSelect
 
 If *ChildDispatch <> #Null And *ChildDispatch\QueryInterface(@IID_IAccessible, @*ChildAccessible) = #S_OK
     DisplayInfo(*ChildAccessible, aOffset$ + " ")
 EndIf
EndProcedure

Procedure DisplayInfo (*aAccessible.IAccessible, aOffset$ )
 Protected count, iObtained
 Protected BSTR_wsText
 Protected vt.VARIANT, i, err
 Protected *enum.IEnumVARIANT
 
 vt\vt = #VT_I4
 vt\lVal = #CHILDID_SELF
 
 If *aAccessible
    ;;; allocation not needed, see post below by Josh
    ;;; BSTR_wsText = SysAllocString_("")
   
    If *aAccessible\get_accName(vt, @BSTR_wsText) = #S_OK
        Debug aOffset$ + "Name: " + GetBSTR(BSTR_wsText)
       
        If GetBSTR(BSTR_wsText) = "File"
          err = *aAccessible\accSelect(#SELFLAG_TAKEFOCUS | #SELFLAG_TAKESELECTION, vt)       
          Debug err
        EndIf           
       
        SysFreeString_(BSTR_wsText)
    Else
        Debug aOffset$ + "Name: Empty"
    EndIf

    If *aAccessible\get_AccValue(vt, @BSTR_wsText) = #S_OK
        Debug aOffset$ + " Value: " + GetBSTR(BSTR_wsText)
        SysFreeString_(BSTR_wsText)
    EndIf
   
    If *aAccessible\get_AccDescription(vt, @BSTR_wsText) = #S_OK
        Debug aOffset$ + " Description: " + GetBSTR(BSTR_wsText)
        SysFreeString_(BSTR_wsText)
    EndIf
   
    If *aAccessible\get_accChildCount(@count) = #S_OK And count > 0     
        aOffset$ + " " ; fix indenting
        Debug aOffset$ + "Children: " + Str(count)
           
        Dim ChildArray.VARIANT(count)
        Protected Child.VARIANT, CurrentChild.VARIANT
        Protected dwNum.l
       
        If AccessibleChildren(*aAccessible, 0, count, @ChildArray(0), @iObtained) = #S_OK   
            For i = 0 To iObtained - 1
                ProcessChild(*aAccessible, aOffset$, ChildArray(i))         
            Next
        ElseIf *aAccessible\QueryInterface(@IID_IEnumVARIANT, @*enum) = #S_OK
            ;
            ;*enum = *aAccessible ; this look definitely wrong, don't know how this did work in delphi
            ;         
            *enum\Reset() ; for good measure
           
            For i = 0 To count - 1               
                If *enum\Next(1, @Child, 0) = #S_OK
                    ProcessChild(*aAccessible, aOffset$, @Child)
                EndIf
            Next
        Else
            If *aAccessible\accNavigate(#NAVDIR_FIRSTCHILD, vt, @CurrentChild) = #S_OK
                Repeat
                    ProcessChild(*aAccessible, aOffset$, @CurrentChild)
                Until *aAccessible\accNavigate(#NAVDIR_NEXT, @CurrentChild, @CurrentChild) <> #S_OK
            EndIf               
       EndIf
    EndIf
   
   
   
    VariantClear_(vt)
   
 EndIf
EndProcedure


hwnd = FindWindow_( "CabinetWClass", 0)

If hwnd       
    SetForegroundWindow_(hwnd)
    If AccessibleObjectFromWindow(hwnd, 0, @IID_IAccessible, @*Accessible) = #S_OK     
        DisplayInfo(*Accessible, "")
    EndIf
EndIf
ImageThe happiness is a road...
Not a destination
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: File or folder selected in windows explorer

Post by BarryG »

JHPJHP wrote:This can definitely be resolved, but it requires more interest then I currently possess.
Love it! :lol: I know that feeling.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: File or folder selected in windows explorer

Post by JHPJHP »

Hi BarryG,

Boredom won out over my lack of interest :)

After a complete rewrite of the EnumWindowsProc Procedure with various other improvements the speed difference is noticeable. In addition, sources and procedures are now separate include files.

See the following posts (from this thread) for additional information:
- viewtopic.php?p=536662#p536662
- viewtopic.php?p=536669#p536669
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: File or folder selected in windows explorer

Post by Kwai chang caine »

Waoooouhh !!
Very Better, Shorter and Faster :shock:
Thanks a lot MASTER 8)
Tested on W10

Why there are the "Horizontal" word ?
And is it possible to have the full path of the element selected ?
ImageThe happiness is a road...
Not a destination
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: File or folder selected in windows explorer

Post by JHPJHP »

Hi Kwai chang caine,

I'm not seeing that... here is a an example of what is returned when executed from my system.

Windows 10 Pro (64-bit) / PureBasic 5.71 beta 1 LTS (x86)
---------------------------
Selected Items
---------------------------
Total Items: 43

● D:\PureBasic\Alternate_Console_WIN_SRC\
● D:\PureBasic\Applications\
● D:\PureBasic\Book_Viewer_Magnify_SRC\
● D:\PureBasic\Embed_JavaScript_LNX_SRC\
● D:\PureBasic\Embed_JavaScript_OSX_SRC\
● D:\PureBasic\Embed_JavaScript_WIN_SRC\
● D:\PureBasic\Network_Share_Management_WIN_SRC\
...
● D:\PureBasic\PB_Interface_7Zip_WIN_SRC.zip
● D:\PureBasic\PB_Interface_ImDisk_WIN_SRC.zip
● D:\PureBasic\PB_Interface_WinDivert_WIN_SRC.zip
● D:\PureBasic\PB_Interface_WinRAR_WIN_SRC.zip
● D:\PureBasic\Video_Windows_VfW_WIN_SRC.zip
● D:\PureBasic\Windows_Services_Other_Stuff_SRC.zip

---------------------------
OK
---------------------------
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: File or folder selected in windows explorer

Post by Kwai chang caine »

I don't understand :shock:
I run the "C:\Windows_Services_Other_Stuff_SRC\Other_Stuff\SelectedItems\SelectedItems.pb"
This is the little code

Code: Select all

IncludeFile "includes\sources.pbi"
IncludeFile "includes\procedures.pbi"

oleacc = OpenLibrary(#PB_Any, "oleacc.dll")

If IsLibrary(oleacc)
  AccessibleObjectFromWindow = GetFunction(oleacc, "AccessibleObjectFromWindow")
  AccessibleChildren = GetFunction(oleacc, "AccessibleChildren")
  GetStateText = GetFunction(oleacc, "GetStateTextW")
  CoInitialize_(0)
  EnumChildWindows_(GetDesktopWindow_(), @EnumWindowsProc(), 0)
  CoUninitialize_()
  CloseLibrary(oleacc)
  ArraySize = ArraySize(ItemList())

  If ArraySize
    For rtnCount = 0 To ArraySize - 1
      If FileSize(ItemList(rtnCount)) = -2
        If Right(ItemList(rtnCount), 1) <> #PS$ : ItemList(rtnCount) + #PS$ : EndIf
      EndIf
      ItemList$ + Chr($25CF) + " " + ItemList(rtnCount) + #LF$
    Next
    MessageRequester("Selected Items", "Total Items: " + Str(ArraySize) + #LF$ + #LF$ + ItemList$, #PB_MessageRequester_Info)
  Else
    MessageRequester("Selected Items", "No selected files or folders.", #PB_MessageRequester_Warning)
  EndIf
EndIf
And i have this MsgBox on W10 X64 v5.70 x86

Image
ImageThe happiness is a road...
Not a destination
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: File or folder selected in windows explorer

Post by JHPJHP »

Hi Kwai chang caine,

TESTED:
Windows 7 (64-bit) / PureBasic 5.70 LTS (x86)
Windows 10 (64-bit) / PureBasic 5.71 beta 1 LTS (x86)

Download the updated package; example includes additional optimizations:
- Windows Services & Other Stuff\Other_Stuff\SelectedItems\SelectedItems.pb
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: File or folder selected in windows explorer

Post by Kwai chang caine »

Excuse me for the later answer :oops:
Today i'm not ont the W10 X64 machine, but i test your new code on W7 X86 and it works perfectly 8)
Thanks a lot for your works, when i can test on W10, i do it :wink:

Have a very good day MASTER
ImageThe happiness is a road...
Not a destination
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: File or folder selected in windows explorer

Post by mk-soft »

Works fine on Window 7 and Window 10 with ActiveScript :wink:

Link: viewtopic.php?f=12&t=71399

Update
- VB Script

Code: Select all

;-TOP

; Comment   : Modul ActiveScript Example 9 - GetSelectedFiles

; Link to ActiveScript  : https://www.purebasic.fr/english/viewtopic.php?f=12&t=71399
; Link to SmartTags     : https://www.purebasic.fr/english/viewtopic.php?f=12&t=71399#p527089
; Link to VariantHelper : https://www.purebasic.fr/english/viewtopic.php?f=12&t=71399#p527090

; ***************************************************************************************

XIncludeFile "Modul_ActiveScript.pb"
XIncludeFile "Modul_SmartTags.pb"
XIncludeFile "VariantHelper.pb"

UseModule ActiveScript
UseModule ActiveSmartTags

; -------------------------------------------------------------------------------------

Global vbs.s

; Daten anlegen

; VB-Script schreiben
vbs + #LF$ + ~"Function GetSelectedFiles() 'Returns paths as array of strings"
vbs + #LF$ + ~"    Dim FileList, Window, SelectedItem"
vbs + #LF$ + ~"    'avoid duplicates by storing paths in dictionary keys"
vbs + #LF$ + ~"    Set FileList = CreateObject(\"Scripting.Dictionary\")"
vbs + #LF$ + ~""
vbs + #LF$ + ~"    With CreateObject(\"Shell.Application\")"
vbs + #LF$ + ~"        For Each Window In .Windows"
vbs + #LF$ + ~"            'skip IE Windows"
;vbs + #LF$ + ~"           If InStr(1, Window.FullName, \"iexplore.exe\", vbTextCompare) = 0 Then"
vbs + #LF$ + ~"            ' Document type IShellFolderViewDual3"
vbs + #LF$ + ~"            If InStr(1, typename(Window.Document),\"IShellFolderView\", 1) > 0 Then"
vbs + #LF$ + ~"                For Each SelectedItem In Window.Document.SelectedItems"
vbs + #LF$ + ~"                    FileList(SelectedItem.Path) = Null"
vbs + #LF$ + ~"                Next"
vbs + #LF$ + ~"            End If"
vbs + #LF$ + ~"        Next"
vbs + #LF$ + ~"    End With"
vbs + #LF$ + ~""
vbs + #LF$ + ~"    GetSelectedFiles = FileList.Keys 'array of paths"
vbs + #LF$ + ~"End Function"
vbs + #LF$ + ~""
vbs + #LF$ + ~"SmartTags(\"Result\") = GetSelectedFiles"
vbs + #LF$ + ~""

Debug "*** New ActiveScript ***"
*Script = NewActiveScript()
If *Script
  Debug "*** Add Object SmartTags ***"
  AddObject("SmartTags", NewSmartTags())
  Debug "*** Parse ScriptText ***"
  r1 = ParseScriptText(vbs)
  If r1 = #S_OK
    Debug "Code Ready."
  EndIf
  Debug "*** Free ActiveScript ***"
  FreeActiveScript()
  Debug "*** Finished ActiceScript ***"
EndIf

*psa = GetVariantSafeArray(SmartTags("Result"))
If *psa
  
  Debug "************************************************************"
  Debug "Dims = " + GetSafeArrayDims(*psa)
  Debug "************************************************************"
  
  For x = 0 To GetSafeArrayElements(*psa, 1) - 1
    Debug GetVariantString(GetSafeArrayElementPtr(*psa, x))
  Next
  ClearSmartTags("Result")
  Debug "************************************************************"
EndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: File or folder selected in windows explorer

Post by JHPJHP »

Hi mk-soft,

When I first saw that VBScript was posted as a solution I thought of your ActiveScript thread, but I was already looking into Microsoft Active Accessibility (MSAA) and believed it was also a viable solution.

I've used VBScript for 30+ years; Module ActiveScript for VB-Script with PB-Runtime Variables is an excellent piece of coding with unlimited potential.

Hi Kwai chang caine,

As I mentioned in a previous post concerning the use of MSAA "if a selected file or folder is scrolled off-screen it may not be listed"; the solution posted by mk-soft is your best option.
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: File or folder selected in windows explorer

Post by mk-soft »

Thanks JHPJHP :wink:

I extended the VariantHelper a bit to transfer simple arrays from the VBScript to PB.
See link viewtopic.php?f=12&t=71399&p=536890#p536890
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: File or folder selected in windows explorer

Post by BarryG »

JHPJHP wrote: Sun May 19, 2019 10:17 pmWindows Services & Other Stuff\Other_Stuff\SelectedItems\SelectedItems.pb
Hi JHPJHP, this isn't in the latest download of your archive? How can I get it? Thanks.
AZJIO
Addict
Addict
Posts: 1318
Joined: Sun May 14, 2017 1:48 am

Re: File or folder selected in windows explorer

Post by AZJIO »

Could not get the file name

Code: Select all

EnableExplicit

Define Pos.b

Procedure.s ProcessNameFromHwnd(hWnd)
	Protected PID, psapi_dll, Path$, GetModuleFileNameEx, hProcess
	psapi_dll = OpenLibrary(#PB_Any, "psapi.dll")
	If psapi_dll
		GetModuleFileNameEx = GetFunction(psapi_dll, "GetModuleFileNameExW")
		If GetModuleFileNameEx
			If GetWindowThreadProcessId_(hWnd, @PID)
				hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, #Null, PID)
				If hProcess
					Path$ = Space(#MAX_PATH)
					If Not CallFunctionFast(GetModuleFileNameEx, hProcess, #Null, @Path$, #MAX_PATH)
						Path$ = ""
					EndIf
					CloseHandle_(hProcess)
				EndIf
			EndIf
		EndIf
		CloseLibrary(psapi_dll)
	EndIf
	ProcedureReturn Path$
EndProcedure

Define hWnd, Path1$, Path2$, k, Name.String, LVITEM.LVITEM, Buffer$
Global hWnd_Find, classText.s = Space(256)


Procedure enumChildren(hwnd, k)
	If hwnd
		GetClassName_(hwnd, @classText, 256)
		If GetDlgCtrlID_(hwnd) = 1001 And classText = "ToolbarWindow32"
			hWnd_Find = hwnd
			ProcedureReturn 0
		EndIf
		ProcedureReturn 1
	EndIf
	ProcedureReturn 0
EndProcedure


Procedure enumChildren1(hwnd, k)
	If hwnd
		GetClassName_(hwnd, @classText, 256)
		If classText = "DirectUIHWND"
			hWnd_Find = hwnd
			ProcedureReturn 0
		EndIf
		ProcedureReturn 1
	EndIf
	ProcedureReturn 0
EndProcedure

Repeat
	hWnd = FindWindow_("CabinetWClass", 0)
	If hWnd ;And Right(ProcessNameFromHwnd(hWnd), 13) = "\explorer.exe"
		EnumChildWindows_(hWnd, @enumChildren(), k)
		If hWnd_Find
			Path1$ = Space(256)
			SendMessage_(hWnd_Find, #WM_GETTEXT, 256, @Path1$)
		EndIf
		hWnd_Find = 0
		EnumChildWindows_(hWnd, @enumChildren1(), k)
		If hWnd_Find
			Buffer$ = Space(4096)
			SendMessage_(hWnd_Find, #LVM_GETITEMTEXTW, 1, @Buffer$)
		EndIf
	EndIf
	
	Pos = FindString(Path1$, "\")
	If Pos
		Path1$ = Mid(Path1$, Pos - 2)
		If FileSize(Path1$) <> -1
			Debug Path1$
			Debug Buffer$
		EndIf
	EndIf
	Delay(500)
ForEver
Sometimes I look at how it's done in AutoIt3 (_GUICtrlListView_GetItemText). But in this case there are too many functions for working with memory (GetWindowThreadProcessId, OpenProcess, ReadProcessMemory, WriteProcessMemory, VirtualAllocEx). See AutoIt3\Include\GuiListView.au3 (+ \Memory.au3)
Post Reply