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