簡體   English   中英

如何從 Visual Studio 應用程序打開文件資源管理器 window 並設置 position 和大小?

[英]How can I open a File Explorer window from a Visual Studio app and set the position and size?

我有一個 VB.net 應用程序,它可以壓縮 JPG 文件、重命名它們並將它們從一個位置復制到另一個位置。 當最終用戶使用該程序時,他們將打開兩個文件瀏覽器 windows 以獲取源和目標位置並將它們拖到文本框上。

我添加了打開兩個文件資源管理器以設置位置的代碼,但我希望一個 windows 位於屏幕的左下方,另一個位於屏幕的右下方。 每個都將占據屏幕的 1/4。

我發現的大部分東西都很古老。 我發現有人說無法完成,其他人提供的代碼非常陳舊,似乎無法與 Visual Studio 2019 配合使用。

Private Sub btnOpenExplorer_Click(sender As Object, e As EventArgs) Handles btnOpenExplorer.Click

    Process.Start("explorer.exe", String.Format("/n, /e, {0}", "C:\Users\" & Environment.UserName & "\Box\Site Visit Photos"))
    Process.Start("explorer.exe", String.Format("/n, /e, {0}", "P:\"))

End Sub

上面的代碼運行良好。 我只需要添加尺寸和定位。

您可以在user32.dll中使用MoveWindow() window 句柄可以通過proc.MainWindowHandle獲得,其中procProcess.Start()返回的進程。

另外這對我很有效: https://www.codeproject.com/Tips/1057230/Windows-Resize-and-Move

解決方案 1

問題

我認為在調用程序btnOpenExplorer_Click中很難做到這一點,因為現在獲得一個分配了所有屬性的進程 object 還為時過早。 大多數情況下,解決此問題所需的ProcessMainWindowTitleProcess.MainWindowHandle屬性。 一個解決方法是讓調用者啟動進程和一個計時器來通過SetWindowPos function 進行定位和調整大小。

這是我的做法:

API 功能

<DllImport("user32.dll", EntryPoint:="SetWindowPos")>
Private 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 <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

<DllImport("user32.dll")>
Private Shared Function IsIconic(hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

<DllImport("user32.dll")>
Public Shared Function ShowWindow(hWnd As IntPtr, <MarshalAs(UnmanagedType.I4)> nCmdShow As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

Class 電平常數和變量

Private Const HWND_TOP As Integer = &H0
Private Const SW_SHOWNORMAL As Integer = &H1

Private dir1, dir2 As String
Private WithEvents Timer1 As New Timer With {.Interval = 250}

進程查找器

Private Function GetExplorerProcess(title As String) As Process
    Dim dirName As String = If(IO.Directory.Exists(title), New IO.DirectoryInfo(title).Name, title).ToLower

    Return Process.GetProcesses.Where(
        Function(a) a.ProcessName.ToLower.Equals("explorer") AndAlso
        a.MainWindowTitle.ToLower.Equals(dirName)
        ).FirstOrDefault
End Function

呼叫者,召集者

Private Sub btnOpenExplorer_Click(sender As Object, e As EventArgs) Handles btnOpenExplorer.Click
    Dim proc1 As Process = GetExplorerProcess(dir1)

    If proc1 Is Nothing Then
        Dim procInfo1 As New ProcessStartInfo With {
        .FileName = "explorer.exe",
        .Arguments = dir1,
        .WindowStyle = ProcessWindowStyle.Normal
        }

        Process.Start(procInfo1)
    End If

    Dim proc2 As Process = GetExplorerProcess(dir2)

    If proc2 Is Nothing Then
        Dim procInfo2 As New ProcessStartInfo With {
        .FileName = "explorer.exe",
        .Arguments = dir2,
        .WindowStyle = ProcessWindowStyle.Normal
        }

        Process.Start(procInfo2)
    End If

    Timer1.Start()
End Sub

計時器 - 激活 Windows,設置大小和位置

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Dim proc1 As Process = GetExplorerProcess(dir1)
    Dim proc2 As Process = GetExplorerProcess(dir2)

    If proc1 IsNot Nothing AndAlso proc2 IsNot Nothing Then
        Timer1.Stop()

        Dim R As Rectangle = Screen.PrimaryScreen.WorkingArea
        Dim R1 As New Rectangle(R.X, R.Height - (R.Height / 3), R.Width / 2, R.Height / 4)
        Dim R2 As New Rectangle(R1.Right, R1.Y, R1.Width, R1.Height)
        Dim hWnd1 As IntPtr = proc1.MainWindowHandle
        Dim hWnd2 As IntPtr = proc2.MainWindowHandle

        'Restore the first window if its minimized.
        If IsIconic(hWnd1) Then
            ShowWindow(hWnd1, SW_SHOWNORMAL)
        End If

        'Set the size and location of the first window.
        SetWindowPos(hWnd1, IntPtr.op_Explicit(HWND_TOP), R1.X, R1.Y, R1.Width, R1.Height, 0)

        'Restore the second window if its minimized.
        If IsIconic(hWnd2) Then
            ShowWindow(hWnd2, SW_SHOWNORMAL)
        End If

        'Set the size and location of the second window.
        SetWindowPos(hWnd2, IntPtr.op_Explicit(HWND_TOP), R2.X, R2.Y, R2.Width, R2.Height, 0)
    End If
End Sub

解決方案 2

在到處搜索之后,我通過使用Microsoft Internet Controls - SHDocVw 組件找到了一種更好的方法(我認為)。

首先,我們需要添加對 COM 組件的引用:

  • 在您的項目瀏覽器中,右鍵單擊References節點和 select Add Reference
  • 在參考管理器 Select 中的COM選項卡。
  • 查找並檢查Microsoft Internet Controls ,然后單擊確定。

我們只需要解決方案1 中的 API 和常量,以及一個新的 function 來獲取 IE window:

Private Function GetIE(dir As String) As SHDocVw.InternetExplorer
    Return (From ie In New SHDocVw.ShellWindows
            Where New Uri(DirectCast(ie, SHDocVw.InternetExplorer).LocationURL).LocalPath.Equals(dir, StringComparison.OrdinalIgnoreCase)
            Select DirectCast(ie, SHDocVw.InternetExplorer)).FirstOrDefault
End Function

最后,調用者:

Private Sub btnOpenExplorer_Click(sender As Object, e As EventArgs) Handles btnOpenExplorer.Click
    Dim dir1 As String = "FirstPath"
    Dim dir2 As String = "SecondPath"
    Dim ie1, ie2 As SHDocVw.InternetExplorer

    If Not IO.Path.GetPathRoot(dir1).Equals(dir1, StringComparison.OrdinalIgnoreCase) Then
        dir1 = dir1.TrimEnd(IO.Path.DirectorySeparatorChar)
    End If

    If Not IO.Path.GetPathRoot(dir2).Equals(dir2, StringComparison.OrdinalIgnoreCase) Then
        dir2 = dir2.TrimEnd(IO.Path.DirectorySeparatorChar)
    End If

    ie1 = GetIE(dir1)
    ie2 = GetIE(dir2)

    If ie1 Is Nothing OrElse ie2 Is Nothing Then
        Process.Start(dir1)
        Process.Start(dir2)
        Threading.Thread.Sleep(1000)
    End If

    If ie1 Is Nothing Then ie1 = GetIE(dir1)
    If ie2 Is Nothing Then ie2 = GetIE(dir2)

    If ie1 IsNot Nothing AndAlso ie2 IsNot Nothing Then
        Dim hWnd1 = IntPtr.op_Explicit(ie1.HWND)
        Dim hWnd2 = IntPtr.op_Explicit(ie2.HWND)
        Dim R As Rectangle = Screen.PrimaryScreen.WorkingArea
        Dim R1 As New Rectangle(R.X, R.Height - (R.Height \ 3), R.Width \ 2, R.Height \ 4)
        Dim R2 As New Rectangle(R1.Right, R1.Y, R1.Width, R1.Height)

        SetWindowPos(hWnd1, IntPtr.op_Explicit(HWND_TOP), R2.X, R2.Y, R2.Width, R2.Height, 0)
        SetWindowPos(hWnd2, IntPtr.op_Explicit(HWND_TOP), R1.X, R1.Y, R1.Width, R1.Height, 0)

        If IsIconic(hWnd1) Then
            ShowWindow(hWnd1, SW_SHOWNORMAL)
        End If

        If IsIconic(hWnd2) Then
            ShowWindow(hWnd2, SW_SHOWNORMAL)
        End If
    End If
End Sub

請注意,此解決方案也適用於驅動器(即: c:\ , d:\ ..etc.),而第一個不適用。

這是一個演示:

IEDemo

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM