Vb.net 如何将特定文件的资源管理器窗口设置为最顶层窗体的子窗口?

Vb.net 如何将特定文件的资源管理器窗口设置为最顶层窗体的子窗口?,vb.net,explorer,Vb.net,Explorer,我做了一些研究,但我找不到真正“有趣”的东西。我尽最大努力找到与我的案例最接近的任何类型的文档或问题,如下所示: 而且 我用来打开进程窗口的代码 Private Async Function ParentMethod() As Task Dim filePath As String = Await Task.Run( Function() Return Directory.EnumerateFiles(My.Settings

我做了一些研究,但我找不到真正“有趣”的东西。我尽最大努力找到与我的案例最接近的任何类型的文档或问题,如下所示:

而且

我用来打开进程窗口的代码

Private Async Function ParentMethod() As Task
       Dim filePath As String = Await Task.Run(
       Function()

           Return Directory.EnumerateFiles(My.Settings.Cartellasalvataggio, titolo & ".mp3",
                         SearchOption.AllDirectories).FirstOrDefault()
       End Function)
       If Not String.IsNullOrEmpty(filePath) Then
           LinkLabel1.Text = "File exist already"
           LinkLabel1.Visible = True
           PictureBox7.Visible = True
       Else
           MsgBox("it doesn't exist")

       End If

   End Function
和helper类

Imports System.IO
Imports System.Runtime.InteropServices

Public Class NativeMethods
   <DllImport("shell32.dll", SetLastError:=True)>
   Private Shared Function SHOpenFolderAndSelectItems(
           pidlFolder As IntPtr, cidl As UInteger,
           <[In], MarshalAs(UnmanagedType.LPArray)> apidl As IntPtr(),
           dwFlags As UInteger) As Integer
   End Function

   <DllImport("shell32.dll", SetLastError:=True)>
   Private Shared Sub SHParseDisplayName(
           <MarshalAs(UnmanagedType.LPWStr)> name As String,
           bindingContext As IntPtr, <Out> ByRef pidl As IntPtr,
           sfgaoIn As UInteger, <Out> ByRef psfgaoOut As UInteger)
   End Sub

   Public Shared Sub OpenFolderAndSelectFile(filePath As String)
       Dim dirPath As String = Path.GetDirectoryName(filePath)
       Dim fileName As String = Path.GetFileName(filePath)
       OpenFolderAndSelectFile(dirPath, fileName)
   End Sub

   Public Shared Sub OpenFolderAndSelectFile(dirPath As String, fileName As String)
       Dim nativeFolder As IntPtr
       Dim psfgaoOut As UInteger
       SHParseDisplayName(dirPath, IntPtr.Zero, nativeFolder, 0, psfgaoOut)

       If nativeFolder = IntPtr.Zero Then
           ' Log error, can't find folder
           Return
       End If

       Dim nativeFile As IntPtr
       SHParseDisplayName(Path.Combine(dirPath, fileName),
                          IntPtr.Zero, nativeFile, 0, psfgaoOut)

       Dim fileArray As IntPtr()
       If nativeFile = IntPtr.Zero Then
           ' Open the folder without the file selected if we can't find the file
           fileArray = New IntPtr(-1) {}
       Else
           fileArray = New IntPtr() {nativeFile}
       End If

       SHOpenFolderAndSelectItems(nativeFolder, CUInt(fileArray.Length), fileArray, 0)

       Marshal.FreeCoTaskMem(nativeFolder)
       If nativeFile <> IntPtr.Zero Then
           Marshal.FreeCoTaskMem(nativeFile)
       End If
   End Sub
End Class
由于我以这种方式打开流程,而不是使用process类,因此几乎所有的流程都不适合我的案例,因为它们中的许多都是指记事本,而我认为每个文件的资源管理器窗口标题和ID都会更改(很明显),而“记事本”流程保持“记事本”

我也尝试过BringToFront,但后者将一个控件移动到其他控件之前,但在本例中,Explorer不是控件,对吗

至少我想做的是 因为它会无缘无故地浪费内存和时间,因为我需要“过滤”进程以找到我的进程

希望我们能找到解决方案,提前谢谢。
Mattia

这是使用FindWindowW e SetWindowPos Api的解决方案。 它在最上面的窗体顶部显示资源管理器文件夹

   <DllImport("user32.dll", EntryPoint:="FindWindowW")>
   Public Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
   End Function
   <DllImport("user32.dll")>
   Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As UInteger) As Boolean
   End Function
Shared ReadOnly HWND_TOPMOST As IntPtr = New IntPtr(-1)
   Const SWP_NOSIZE As UInt32 = &H1
   Const SWP_NOMOVE As UInt32 = &H2
   Const SWP_SHOWWINDOW As UInt32 = &H40
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click


       Dim inptr = FindWindowW("CabinetWClass", Nothing)
       SetWindowPos(inptr, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_SHOWWINDOW)
   End Sub

公共共享函数FindWindowW(ByVal lpClassName作为字符串,ByVal lpWindowName作为字符串)作为IntPtr
端函数
共享函数SetWindowPos(ByVal hWnd作为IntPtr,ByVal hwninsertafter作为IntPtr,ByVal X作为整数,ByVal Y作为整数,ByVal cx作为整数,ByVal cy作为整数,ByVal uFlags作为UInteger)作为布尔值
端函数
共享只读HWND_最顶层为IntPtr=新IntPtr(-1)
Const SWP_NOSIZE为UInt32=&H1
Const SWP_NOMOVE As UInt32=&H2
常量SWP_显示窗口为UInt32=&H40
私有子按钮3\u单击(发送者作为对象,e作为事件参数)处理按钮3。单击
Dim inptr=FindWindowW(“橱柜类”,无)
设置窗口位置(inptr、HWND_最顶部、0、0、0、SWP_NOMOVE或SWP_NOSIZE或SWP_SHOWWINDOW)
端接头

首先,这是个坏主意。如果您的问题是资源管理器窗口位于最上面的表单后面,那么在调用
OpenFolderAndSelectfile()
之前,只需最小化表单(
Me.WindowState=FormWindowState.Minimized
)就足够了。旁注:
filePath
在上面的代码中已经包含了文件名和扩展名;您不需要
、文件名和“扩展名”
部分。在调用OpenFolderAndSelectFile()之前,我想将top设置为false,然后在用户鼠标再次位于窗体顶部时将其设置为true,但我不喜欢这种或那种解决方案。。我不想在调用表单之前最小化表单,也不想使用我的解决方案,因为一旦用户与资源管理器窗口交互,表单就会最小化。然后,创建自己的查看器,在表单(或子表单)上显示目录文件,而不是使用资源管理器。在我看来,最小化表单是一个简单得多的解决方案。用户知道在使用资源管理器窗口后如何恢复它。无论如何,如果你真的想(嵌入资源管理器或创建你自己的),你会在中找到一些资源,但这真的不值得。不要把事情过分复杂化,也不要试图解决一个不存在的问题。用户只需单击一次即可与资源管理器窗口交互。。在我看来,用户重新打开软件似乎是浪费时间,即使它是从托盘。我已经在表单上显示了文件的路径,因此使用此函数将非常有用。。另外,请注意,我正在尝试使用,以便用户在软件选项中选择设置top most true或false。。如果用户选择top most false,那么这甚至不是问题,但是如果用户选择top most true,那么我觉得我不尊重它的选择
   <DllImport("user32.dll", EntryPoint:="FindWindowW")>
   Public Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
   End Function
   <DllImport("user32.dll")>
   Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As UInteger) As Boolean
   End Function
Shared ReadOnly HWND_TOPMOST As IntPtr = New IntPtr(-1)
   Const SWP_NOSIZE As UInt32 = &H1
   Const SWP_NOMOVE As UInt32 = &H2
   Const SWP_SHOWWINDOW As UInt32 = &H40
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click


       Dim inptr = FindWindowW("CabinetWClass", Nothing)
       SetWindowPos(inptr, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_SHOWWINDOW)
   End Sub