Как я могу открыть окно проводника из приложения Visual Studio и установить его размер и размер? - PullRequest
0 голосов
/ 23 октября 2019

У меня есть приложение VB.net, которое уплотняет файлы JPG, переименовывает их и копирует их из одного места в другое. Когда конечный пользователь использует программу, он откроет два окна проводника файлов, чтобы получить исходные и конечные местоположения, и перетянет их в текстовые поля.

Я добавил код, который открывает два проводника файлов для определения местоположений, но я бы хотел, чтобы одно окно находилось в левом нижнем углу экрана, а другое - в правом нижнем. Каждый из них должен был занимать 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

Приведенный выше код работает хорошо. Мне просто нужно добавить размеры и расположение.

Ответы [ 2 ]

0 голосов
/ 06 ноября 2019

Проблема

Я думаю, что это трудно сделать в подпрограмме вызывающей стороны btnOpenExplorer_Click, поскольку будет слишком рано получать объект процесса со всеми назначенными ему свойствами. В основном это свойства ProcessMainWindowTitle и Process.MainWindowHandle , которые необходимы для решения этой проблемы. Чтобы обойти это, нужно, чтобы вызывающая сторона запускала процессы, а таймер - для позиционирования и изменения размера с помощью функции SetWindowPos .

Вот как я это сделаю:

Функции 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

Константы и переменные уровня класса

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}

Process Finder

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

Все готово к работе. Удачи.

Ссылки

Установить местоположение экрана дочернего окна внешнего приложения?
Функция SetWindowPos
Управление процессами в .NET
Как сделать окно активным в vb.net

0 голосов
/ 23 октября 2019

Вы можете использовать MoveWindow() в user32.dll. Дескриптор окна может быть получен с помощью proc.MainWindowHandle, где proc - это процесс, возвращаемый Process.Start().

. Кроме того, для меня это хорошо работает: https://www.codeproject.com/Tips/1057230/Windows-Resize-and-Move

...