Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Path of explorer file view from window handle 2

Status
Not open for further replies.

CubeE101

Programmer
Nov 19, 2002
1,492
US
Does anyone know a method to get the path of Explorer Window's file view from window handle...

Though I may not need to, if there is a way to do this through OLE Drag/Drop instead...

--------------------------------------------------------
-- Details ---------------------------------------------
--------------------------------------------------------

*Note: the code below is just for a reference so you can see what I am dealing with. I don't expect it to make perfect sense to everyone...

The reason for all of this is... I have a PDM system called Matrix that uses MQL (similar to SQL) to query the system...

To check a file out, you have to send a string such as...
Code:
"checkout bus ID format 'FORMAT' file 'FILE' 'Path'"

For examnple:
Code:
mqlCommand "checkout bus 12.34.56.78 format 'Text' file 'test.txt' 'c:\test\'"
Checks out test.txt from format Text in business object 12.34.56.78 and places it in "c:\test"

Currently, I have a program set up to query objects to get the checked in files' names and formats, and places them in a list...

I can double click them and check them out to a predefined folder (in a folder list box) and that works ok...

But I have the object structure set up in a treeview, and All I have to do to check a file into an object is drag it from explorer and it handles the rest with this simple code:

Code:
Private Sub TreeView1_OLEDragDrop(Data As MSComctlLib.DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, y As Single)
  Dim Node As MSComctlLib.Node, I As Integer, Msg as String
  Set Node = TreeView1.HitTest(X, y)
  If Not (Node Is Nothing) Then
    If Data.GetFormat(vbCFFiles) = True Then
      For I = 1 To Data.Files.Count
        Msg = Msg & Data.Files.item(I) & vbCrLf
      Next
      If MsgBox("check files: " & vbCrLf & Msg & " into object " & Node.Text, vbYesNo) = vbYes Then
        For I = 1 To Data.Files.Count
           [b]mqlCommand "checkin bus " & Node.Text & " append " & "'" & Data.Files.item(I) & "'"[/b]
        Next
      End If
    End If
  End If
End Sub

*FYI: The checkin string is:
"checkin bus ID append 'File'"

--------------------------------------------------------
-- Problem ---------------------------------------------
--------------------------------------------------------

I would like to do something similar to check files out...

Drag the file from the ListView onto an explorer window, and have it check the file out to that folder...

Any ideas?

Have Fun, Be Young... Code BASIC
-Josh

cubee101.gif


PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
Hmm... guess I get to answer my own question here then...

A while back, I made a few programs to do things such as "Drag a cursor over a window and set it's transparency and On Top flag" and "Modify Text in a NotePad window"

I took these 2 programs and merged them together in a way, and with the help of 'Microsoft Spy++' (comes with VC++ 6) I was able to get the class structure of an Explorer Window...

There are 2 types of Explorer Windows I have seen so far...
ExploreWClass and CabinetWClass

Both function the same, it more or less just depends how you start them up...

If you open explorer using Start>Programs or [WinKey]+E then you get the ExploreWClass class (Has Folder Tree View)

If you open a folder using a shortcut or RightClick>Open then you get the CabinetWClass class (No Tree View)

You can click the Folder button and toggle between the class layouts (even though the actual class does not change), so both classes function the same way...

Code:
[b]The way I have figured out, so far, is to:[/b]
1) select a class by dragging over it with [b]WindowFromPoint()[/b]

2) select the Class Root with [b]GetAncestor()[/b]

3) Check to see if the ClassName is [b]"ExploreWClass"[/b] Or [b]"CabinetWClass"[/b] with [b]GetClassName()[/b]

4) Drill down through the structure to get to the [b]"Edit"[/b] class of the Address Toolbar
   (shown in [b]Bold[/b] in the Class Structure Lists below) using a series of [b]FindWindowEx()[/b] calls

5) get the string length with [b]SendMessageLong()[/b]

6) get the actual string with [b]SendMessageByString()[/b]

You should now have the folder path of the window...

the exception is when you are in your My Documents folder and it just returns "My Documents" which I think was a retarded thing for them to do anyway, but it is easy to work around if it is for personal use...

ON THE OTHER HAND...

My program is not for personal use And I need to be able to return the "C:\Documents and Settings\...\My Documents" from "My Documents"...

ANY SUGGESTIONS?

this may turn into another post of it's own...

------
Here is the ExplorerW and CabinetW Class structures:
Code:
ExploreWClass ("Buttons")
 WorkerW
  ReBarWindow32
   ComboBoxEx32
    ToolbarWindow32
    ComboBox
     [b]Edit[/b]
   ToolbarWindow32
   WorkerW
   ToolbarWindow32
 WorkerW
 msctls__statusbar32
 BaseBar
  ReBarWindow32
   ToolbarWindow32
   SysTreeView32
 SHELLDLL_DefView
  DUIViewWndClassName
   DirectUIHWND
    CtrlNotifySink
     SysListView ("FolderView")

CabinetWClass ("Sldworks_Local")
 WorkerW
  ReBarWindow32
   ComboBoxEx32
    ToolbarWindow32
    ComboBox
     [b]Edit[/b]
   ToolbarWindow32
   WorkerW
   ToolbarWindow32
 WorkerW
 msctls__statusbar32
 SHELLDLL_DefView
  DUIViewWndClassName
   DirectUIHWND
    CtrlNotifySink
     SysListView ("FolderView")
      SysHeader32
The BOLD text is where the path is found

-------
Example Code:

Controls:
Form1 :: Form :: (duh)
Picture1 :: PictureBox :: Drag from this box to select Explorer Window
(I also drew a crosshair on mine)
Text1 :: TextBox :: Returns Window Title (if available)
Text2 :: TextBox :: Returns Class Name
Text3 :: TextBox :: Returns Folder Path (if available)

Code:
Private Type POINTAPI
  X As Long
  Y As Long
End Type

Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetAncestor Lib "user32" (ByVal hwnd As Long, ByVal gaFlags As Long) As Long
Const GA_PARENT = 1, GA_ROOT = 2, GA_ROOTOWNER = 3

'Get Text
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function SendMessageLong& Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long)
Private Declare Function SendMessageByString Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long

Const WM_GETTEXT = &HD
Const WM_GETTEXTLENGTH = &HE
Const WM_SETTEXT = &HC

Dim TargetHWND As Long

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  Dim p As POINTAPI, RetStr As String * 255
  If Button Then
    Screen.MousePointer = vbCrosshair
    p.X = X: p.Y = Y
    TargetHWND = GetAncestor(IIf(ClientToScreen(Picture1.hwnd, p), WindowFromPoint(p.X, p.Y), 0), GA_ROOT)
    Text1.Text = Left(RetStr, GetWindowText(TargetHWND, RetStr, 255))
    Text2.Text = Left(RetStr, GetClassName(TargetHWND, RetStr, 255))
    
    If Text2 = "ExploreWClass" Or Text2 = "CabinetWClass" Then
      Text3 = GetEditText(TargetHWND)
    Else
      Text3 = ""
    End If
  End If
End Sub

Function GetEditText(editx As Long) As String
  Dim hWorkerW As Long
  Dim hReBarWindow32 As Long
  Dim hComboBoxEx32 As Long
  Dim hComboBox As Long
  Dim hEdit As Long

  hWorkerW = FindWindowEx(editx, 0&, "WorkerW", vbNullString)
  hReBarWindow32 = FindWindowEx(hWorkerW, 0&, "ReBarWindow32", vbNullString)
  hComboBoxEx32 = FindWindowEx(hReBarWindow32, 0&, "ComboBoxEx32", vbNullString)
  hComboBox = FindWindowEx(hComboBoxEx32, 0&, "ComboBox", vbNullString)
  hEdit = FindWindowEx(hComboBox, 0&, "Edit", vbNullString)

  Dim TheText As String, TL As Long
  TL = SendMessageLong(hEdit, WM_GETTEXTLENGTH, 0&, 0&)
  TheText = String(TL + 1, " ")
  Call SendMessageByString(hEdit, WM_GETTEXT, TL + 1, TheText)
  TheText = Left(TheText, TL)
  
  If Mid(TheText, 2, 2) <> ":\" Then TheText = "C:\Documents and Settings\[b]UserName[/b]\" & TheText
  GetEditText = TheText
End Function

Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  Screen.MousePointer = vbDefault
End Sub

-------

(too bad I can't give myself a star :p J/K)

Hope this help someone out there... maybe some day ;-)

Have Fun, Be Young... Code BASIC
-Josh

cubee101.gif


PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
Good work CubeE... here's a star from me for figuring out your own post... ;-)
 
Or, assuming that you know the hWnd:
Code:
[blue]' Requires reference to:
' Microsoft Shell Controls and Automation
' Microsoft Internet Controls
Private Function GetWindowsExplorerWindowFolder(hWnd As Long) As String
    Dim myShell As Shell
    Dim myExplorerWindow As WebBrowser
    Set myShell = New Shell
    
    For Each myExplorerWindow In myShell.Windows
    On Error Resume Next
        If myExplorerWindow.hWnd = hWnd Then
            If Err = 0 Then GetWindowsExplorerWindowFolder = myExplorerWindow.Document.Folder.Self.Path
        End If
    On Error GoTo 0
    Next

End Function[/blue]
 
LOL... Thanks bjd4jc :p

btw... I did Post post a new thread conserning the 'Special Folders'...

And it has been answered (Thanks SWI)

Here is an update to a few areas...

Module Code:
Code:
Option Explicit

'*** Select Window Declarations
Private Type POINTAPI
  X As Long
  Y As Long
End Type
Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
'Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetAncestor Lib "user32" (ByVal hwnd As Long, ByVal gaFlags As Long) As Long
Const GA_PARENT = 1, GA_ROOT = 2, GA_ROOTOWNER = 3

'*** Get Text Declarations
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function SendMessageLong& Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long)
Private Declare Function SendMessageByString Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long

Const WM_GETTEXT = &HD
Const WM_GETTEXTLENGTH = &HE

'*** Special Folder Declarations
Private Declare Function SHGetSpecialFolderLocation Lib "Shell32.dll" (ByVal hwndOwner As Long, ByVal nFolder As Long, pidl As ITEMIDLIST) As Long
Private Declare Function SHGetPathFromIDList Lib "Shell32.dll" Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long
Private Type SHITEMID
    cb As Long
    abID As Byte
End Type
Private Type ITEMIDLIST
    mkid As SHITEMID
End Type
Private Enum CSIDL_ENUM
  '* Real Folders
  CSIDL_PROGRAMS = 2&  '// Program Files
  CSIDL_DOCUMENTS = 5&  '// My Documents
  CSIDL_FAVORITES = 6&  '// Favourites
  CSIDL_STARTUP = 7&  '// Startup Folder
  CSIDL_RECENT = 8&  '// Recent Documents
  CSIDL_SENDTO = 9&  '// Send To Folder
  CSIDL_STARTMENU = 11&  '// Start Menu
  CSIDL_DESKTOPFOLDER = 16&  '// Desktop folder
  '* Virtual Folders
  CSIDL_DESKTOP = &H0& '// The Desktop - virtual folder
  CSIDL_CONTROLS = 3&  '// Control Panel - virtual folder
  CSIDL_PRINTERS = 4&  '// Printers - virtual folder
  CSIDL_BITBUCKET = 10&  '// Recycle Bin - virtual folder
  CSIDL_DRIVES = 17&  '// My Computer - virtual folder
  CSIDL_NETWORK = 18&  '// Network Neighbourhood - virtual folder
  CSIDL_NETHOOD = 19&  '// NetHood Folder
  CSIDL_FONTS = 20&  '// Fonts folder
  CSIDL_SHELLNEW = 21&  '// ShellNew folder
End Enum

Private Const MAX_PATH As Integer = 260

[b][COLOR=blue]Public Function SelectWinFolder(X As Single, Y As Single, Cntrl As Control)
  Dim TargetHWND As Long, Folder As String
  Dim p As POINTAPI, RetStr As String * 255
  p.X = X: p.Y = Y
  TargetHWND = GetAncestor(IIf(ClientToScreen(Cntrl.hwnd, p), WindowFromPoint(p.X, p.Y), 0), GA_ROOT)
  Select Case Left(RetStr, GetClassName(TargetHWND, RetStr, 255))
    Case "ExploreWClass", "CabinetWClass": Folder = [COLOR=orange][i]GetEditText(TargetHWND)[/i][/color]
    Case "Progman": Folder = [COLOR=red][i]GetSpecialFolder(CSIDL_DESKTOPFOLDER)[/i][/color]
    Case Else: Folder = ""
  End Select
  If Folder <> "" Then
    Screen.MouseIcon = Cntrl.MouseIcon
    Screen.MousePointer = vbCustom
  Else
    Screen.MousePointer = vbNoDrop
  End If
  SelectWinFolder = Folder
End Function[/color]

[COLOR=orange]Private Function GetEditText(editx As Long) As String
  Dim TheText As String, TL As Long
  Dim hWorkerW As Long, hReBarWindow32 As Long, hComboBoxEx32 As Long, hComboBox As Long, hEdit As Long
  hWorkerW = FindWindowEx(editx, 0&, "WorkerW", vbNullString)
  hReBarWindow32 = FindWindowEx(hWorkerW, 0&, "ReBarWindow32", vbNullString)
  hComboBoxEx32 = FindWindowEx(hReBarWindow32, 0&, "ComboBoxEx32", vbNullString)
  hComboBox = FindWindowEx(hComboBoxEx32, 0&, "ComboBox", vbNullString)
  hEdit = FindWindowEx(hComboBox, 0&, "Edit", vbNullString)
  TL = SendMessageLong(hEdit, WM_GETTEXTLENGTH, 0&, 0&)
  TheText = String(TL + 1, " ")
  Call SendMessageByString(hEdit, WM_GETTEXT, TL + 1, TheText)
  TheText = Left(TheText, TL)
  If Mid(TheText, 2, 2) <> ":\" Then
    Select Case TheText
    Case "My Documents"
      TheText = [COLOR=red][i]GetSpecialFolder(CSIDL_DOCUMENTS)[/i][/color]
    Case "Desktop"
      TheText = [COLOR=red][i]GetSpecialFolder(CSIDL_DESKTOPFOLDER)[/i][/color]
    Case Else
      TheText = ""
    End Select
  End If
  GetEditText = TheText
End Function[/color]

[COLOR=red]Private Function GetSpecialFolder(CSIDL As CSIDL_ENUM) As String
    Dim sPath As String
    Dim IDL As ITEMIDLIST
    GetSpecialFolder = ""
    If SHGetSpecialFolderLocation(0, CSIDL, IDL) = 0 Then
        sPath = Space$(MAX_PATH)
        If SHGetPathFromIDList(ByVal IDL.mkid.cb, ByVal sPath) Then
            GetSpecialFolder = Left$(sPath, InStr(sPath, vbNullChar) - 1) & ""
        End If
    End If
End Function[/color][/b]

Example (Form) Code:

Form1 - Form
Picture1 - PictureBox
Text1 - TextBox


Code:
'Calls the SelectWinFolder from the module and writes the path to Text1
Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  If Button Then
    Text1 = [COLOR=blue][i][b]SelectWinFolder(X, Y, Picture1)[/b][/i][/color]
  End If
End Sub

'Create a test file in drop directoty for verification
Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  If Text1 <> "" Then
    Open Text1 & "\Test Drop.txt" For Output As #1
    Print #1, "Test drop on folder: " & Text1
    Close
  End If
  Screen.MousePointer = vbDefault
End Sub

*Note, I created my own Icon for the drop OK (vbCustom) and placed it in the MouseIcon container for the control that you are dragging from...

You can change this if you want to...

Enjoy,
-Josh

Have Fun, Be Young... Code BASIC
-Josh

cubee101.gif


PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
strongm said:
Or, assuming that you know the hWnd:

Code:
' Requires reference to:
' Microsoft Shell Controls and Automation
' Microsoft Internet Controls
Private Function GetWindowsExplorerWindowFolder(hWnd As Long) As String
    Dim myShell As Shell
    Dim myExplorerWindow As WebBrowser
    Set myShell = New Shell
    
    For Each myExplorerWindow In myShell.Windows
    On Error Resume Next
        If myExplorerWindow.hWnd = hWnd Then
            If Err = 0 Then GetWindowsExplorerWindowFolder = myExplorerWindow.Document.Folder.Self.Path
        End If
    On Error GoTo 0
    Next

End Function

...

Show Off :p

Have Fun, Be Young... Code BASIC
-Josh

cubee101.gif


PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
OK...

With a little help from the AMAZING strongm ;-)

Here is the MUCH shorter version of the Module...

Use the Same Form Code from last posting...
Also, I forgot to mention above, the Control that you call the SelectWinFolder function from MUST HAVE ScaleMode SET TO PIXEL

Module Code:
Code:
Option Explicit
Private Type POINTAPI
  X As Long
  Y As Long
End Type
Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function GetAncestor Lib "user32" (ByVal hwnd As Long, ByVal gaFlags As Long) As Long
Const GA_PARENT = 1, GA_ROOT = 2, GA_ROOTOWNER = 3

'*** Note: Source Control must have Scale Mode set to Pixel (Default is Twip)
Public Function SelectWinFolder(X As Single, Y As Single, Cntrl As Control)
  Dim TargetHWND As Long, Folder As String
  Dim p As POINTAPI, RetStr As String * 255
  p.X = X: p.Y = Y
  TargetHWND = GetAncestor(IIf(ClientToScreen(Cntrl.hwnd, p), WindowFromPoint(p.X, p.Y), 0), GA_ROOT)
  Select Case Left(RetStr, GetClassName(TargetHWND, RetStr, 255))
    Case "ExploreWClass", "CabinetWClass": Folder = GetWindowsExplorerWindowFolder(TargetHWND)
    Case "Progman": Folder = GetSpecialPath("Desktop")
    Case Else: Folder = ""
  End Select
  If Mid(Folder, 2, 2) <> ":\" Then Folder = ""
  Screen.MousePointer = vbCustom
  If Folder <> "" Then Screen.MouseIcon = Cntrl.MouseIcon Else Screen.MousePointer = vbNoDrop
  SelectWinFolder = Folder
End Function

Private Function GetSpecialPath(vDir As String) As String
  Dim i As Integer, Path As String, Title As String
  On Error Resume Next
  With New Shell32.Shell
    Path = .NameSpace(vDir).Self.Path
    Err.Clear
    For i = 0 To 62
      If UCase(Title) = UCase(vDir) Or UCase(Path) = UCase(vDir) Then
        GetSpecialPath = Path
        Exit Function
      End If
      Path = .NameSpace(i).Self.Path
      Title = .NameSpace(i).Title
      Err.Clear
    Next
  End With
  On Error GoTo 0
End Function

Private Function GetWindowsExplorerWindowFolder(hwnd As Long) As String
  Dim myExplorerWindow As WebBrowser
  On Error Resume Next
  With New Shell32.Shell
    For Each myExplorerWindow In .Windows
      If myExplorerWindow.hwnd = hwnd Then If Err = 0 Then GetWindowsExplorerWindowFolder = myExplorerWindow.Document.Folder.Self.Path
    Next
  End With
  On Error GoTo 0
End Function

Have Fun, Be Young... Code BASIC
-Josh

cubee101.gif


PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top