kkdxghlctlcxxtidyuum Ответов: 1

Сложная проблема - установка множества одних и тех же процессов на разные панели


Всем привет,

У меня есть 10 панелей (panel1, panel3, panel5, panel7... panel19) эти панели расположены на форме в точно таком же месте, точно такого же размера (поверх друг друга, все изначально задано как "Visible = False ()")
Все эти панели используются для размещения точно такого же процесса (как и ребенок).

Я создал своего рода нетрадиционный элемент управления вкладками, с помощью которого пользователь может "добавить" еще один из этих дочерних элементов (во-первых, сделав соответствующую панель видимой, во-вторых, переместив ее вперед, в-третьих, запустив процесс, В-четвертых, установив процесс как дочерний) Панель "добавлено", содержащая дочерний элемент, может быть просмотрена в раскрывающемся меню toolstripmenuitem (позже я добавлю способ навигации по панелям).

Вот код, который добавляет пункты меню, относящиеся к каждой панели, которая становится видимой при нажатии на кнопку:

Код:

Dim count As Integer = 1
    Private Sub AddProccess_Click(sender As Object, e As EventArgs) Handles AddProcessBtn.Click

        If count <= 10 Then ' This limits the amount of items that can be added to 10

            Dim item As New ToolStripMenuItem
            item.Name = "ChildWindow" & count & "ToolStripMenuItem"
            item.Text = "ChildWindow " & count

            count += 1

            ChildrenViewerToolStripMenuItem.DropDownItems.Add(item) ' This relates the the drop-down items that are added when the button is clicked
            Dim value1 As Integer = ChildrenViewerToolStripMenuItem.DropDownItems.Count
            ChildrenViewerToolStripMenuItem.Text = "ChildWindow (" & value1 & ")"

' This makes it so that if the item is added to the ViewerMenu, and there is 'x' of the item, then this will happen
            If count = 1 Then Panel1.Visible = True
            If count = 1 Then SetChildTimer1.Start()
            If count = 1 Then Panel1.BringToFront()
            If count = 1 Then Process.Start("FilePath of the process (hereby know as "^")")

            If count = 2 Then Panel3.Visible = True
            If count = 2 Then SetChildTimer2.Start()
            If count = 2 Then Panel3.BringToFront()
            If count = 2 Then Process.Start("^")

            If count = 3 Then Panel5.Visible = True
            If count = 3 Then SetChildTimer3.Start()
            If count = 3 Then Panel5.BringToFront()
            If count = 3 Then Process.Start("^")

            If count = 4 Then Panel7.Visible = True
            If count = 4 Then SetChildTimer4.Start()
            If count = 4 Then Panel7.BringToFront()
            If count = 4 Then Process.Start("^")

            If count = 5 Then Panel9.Visible = True
            If count = 5 Then SetChildTimer5.Start()
            If count = 5 Then Panel9.BringToFront()
            If count = 5 Then Process.Start("^")

            If count = 6 Then Panel11.Visible = True
            If count = 6 Then SetChildTimer6.Start()
            If count = 6 Then Panel11.BringToFront()
            If count = 6 Then Process.Start("^")

            If count = 7 Then Panel13.Visible = True
            If count = 7 Then SetChildTimer7.Start()
            If count = 7 Then Panel13.BringToFront()
            If count = 7 Then Process.Start("^")

            If count = 8 Then Panel15.Visible = True
            If count = 8 Then SetChildTimer8.Start()
            If count = 8 Then Panel15.BringToFront()
            If count = 8 Then Process.Start("^")

            If count = 9 Then Panel17.Visible = True
            If count = 9 Then SetChildTimer9.Start()
            If count = 9 Then Panel17.BringToFront()
            If count = 9 Then Process.Start("^")

            If count = 10 Then Panel19.Visible = True
            If count = 10 Then SetChildTimer10.Start()
            If count = 10 Then Panel19.BringToFront()
            If count = 10 Then Process.Start("^")

        End If

    End Sub


Итак, что же делают "SetChildTimer_"? Ну, приложение, которое я открываю, на самом деле довольно сложное в том смысле, что оно работает от двух процессов, первый из которых-это splashscreen (который, как вы увидите в коде ниже), я решил скрыть. Второй процесс, который "делает свое дело" после завершения splashscreen, - это главное окно, которое я хочу, которое я развернул, как только оно найдено (таймеры установлены на интервал 10 мс для поиска этих процессов и установки их как дочерних).

Вот код для установки дочерних окон:

Код:

' #1

Private Sub Win1SetChildLoader(sender As Object, e As EventArgs) Handles SetChildTimer1.Tick

        Dim LoaderProcess As Process = Process.GetProcessesByName("splashscreen").FirstOrDefault

        If LoaderProcess IsNot Nothing Then

            SetParent(LoaderProcess.MainWindowHandle, Panel1.Handle)
            ShowWindow(LoaderProcess.MainWindowHandle, SW_HIDE)

        End If

    End Sub

    Private p As Process = Nothing

    Private Sub WinSetChildMain(sender As Object, e As EventArgs) Handles SetChildTimer1.Tick

        p = Process.GetProcessesByName("mainwindow").FirstOrDefault

        Dim r As New RECT

        If p IsNot Nothing Then

            GetWindowRect(p.MainWindowHandle, r)
            SetParent(p.MainWindowHandle, Panel1.Handle)
            SendMessage(p.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)

        End If

    End Sub

    ' #2

    Private Sub Win2SetChildLoader(sender As Object, e As EventArgs) Handles SetChildTimer2.Tick

        Dim LoaderProcess2 As Process = Process.GetProcessesByName("splashscreen").FirstOrDefault

        If LoaderProcess2 IsNot Nothing Then

            SetParent(LoaderProcess2.MainWindowHandle, Panel3.Handle)
            ShowWindow(LoaderProcess2.MainWindowHandle, SW_HIDE)

        End If

    End Sub

    Private p2 As Process = Nothing

    Private Sub Win2SetChildMain(sender As Object, e As EventArgs) Handles SetChildTimer2.Tick

        p2 = Process.GetProcessesByName("mainwindow").FirstOrDefault

        Dim r2 As New RECT

        If p2 IsNot Nothing Then

            GetWindowRect(p2.MainWindowHandle, r2)
            SetParent(p2.MainWindowHandle, Panel3.Handle)
            SendMessage(p2.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)

        End If

    End Sub

' ^^ 8 more of these to make 10, I just haven't witten them yet


    ' Correct focusing - This ensures that the form remains in focus when interacting with the child, I think


    Protected Overrides Sub WndProc(ByRef m As Message)

        If m.Msg = WM_ACTIVATE Then

            SendMessageW(Me.Handle, WM_NCACTIVATE, 1, 0)

            If p IsNot Nothing AndAlso Not p.HasExited Then

                SendMessageW(p.MainWindowHandle, WM_NCACTIVATE, 1, 0)

            End If

            m.Result = CType(0, IntPtr)
            Return

        End If

        MyBase.WndProc(m)

    End Sub


Так в чем же моя проблема?
Ну а первое окно, которое я "добавляю" (делая счет 1, а значит активируя SetChildTimer1), работает отлично - оно запускается, таймер обнаруживает процесс "splashscreen" и затем устанавливает его как скрытый дочерний, как только запускается "mainwindow", который устанавливается как "развернутый" в панели.
Однако, когда дело доходит до открытия другого процесса (не забывайте, что это те же самые процессы), он не добавляется как дочерний (в то время как другой (граф 1) счастливо устанавливается как дочерний).

Я решил, что проблема заключается в том, что субподрядчик SetChildTimer запутывается в том, какой процесс добавить, поскольку другой уже запущен, и пытается добавить этот процесс. Но я не уверен.

Итак, как я могу сделать так, чтобы (я думаю) суб-таймер, который устанавливает процессы как дочерние, мог сказать, пытается ли он установить процесс как дочерний, который уже установлен как дочерний на предыдущей панели?

Я надеюсь, что это достаточно подробно, я всегда волнуюсь, что это не так. :P

Большое спасибо за вашу помощь, серьезно, спасибо вам миллион раз!
hellboyf2

Что я уже пробовал:

Все, что было в моих силах, задавая этот вопрос, было действительно моим последним средством.

Ralf Meier

Вы много писали, а иногда (по-моему) и чересчур много ...
Что я предполагаю (но я не уверен) : для каждого нового процесса, который вы хотите запустить, вы должны создать новый экземпляр своего процесса, а затем запустить его. Но я не нашел кодовую часть, где вы это делаете. Также отсутствует метод самого процесса, чтобы увидеть, что происходит внутри. Вся эта информация будет полезна ...

[no name]

Я не совсем понимаю, о чем вы говорите. В настоящее время я открываю процесс, нажав на кнопку "Добавить" новую панель. "Count" относится к числу элементов меню, которые находятся в раскрывающемся списке. Если счетчик равен "x", то процесс начинается, и панель становится видимой на форме и выводится на переднюю часть стопки панелей; см. код ниже:

Если count = 1, то процесс.Start("[вот путь к файлу для файла]") - Итак, если после нажатия на кнопку "Добавить" есть только 1 menustrip подпункты, то процесс запускается и, как вы можете видеть, таймеры, которые относятся к первому обрезанному коду, запускаются, и эти таймеры ищут, есть ли процесс или нет.

Я довольно новичок в этом языке и поэтому не совсем понимаю, что вы подразумеваете под "Для каждого нового процесса, который вы хотите запустить, вы должны создать новый экземпляр вашего процесса, а затем запустить его". Я знаю, что печатал много, но я просто чувствовал, что должен компенсировать неряшливый код.

Большое спасибо за вашу помощь, с уважением,
hbf2

[no name]

Еще один момент: как я могу ссылаться на дочерний процесс (после того, как он был установлен как дочерний для панели) с помощью оператора If?

Возможно, решение J может работать так:
Если [процесс установлен в панели], то
[установите вновь созданный процесс в другой соответствующей панели]
Конец, Если

Чтобы запретить пользователю открывать какие-либо новые процессы с помощью кнопки "Добавить", кнопка "Добавить" может быть включена = False.

Я просто понятия не имею, как программно определить, был ли этот процесс уже установлен как дочерний. Как я уже сказал, я пытался, но у меня это не очень хорошо получается, и мне нужна помощь.

Спасибо :)

Ralf Meier

Чтобы предотвратить недопонимание :
- Процесс обычно представляет собой что-то (возможно, EXE) вне вашего приложения.
- Задача-это метод как часть вашего приложения.
Вы действительно имеете в виду процесс ?.. или вы хотите иметь несколько задач ?

Если вы хотите иметь независимую функциональность, вы должны создать для каждой функциональности собственный экземпляр.
Я приведу вам пример с элементами управления в вашей форме :
- на вашей форме есть несколько кнопок. Каждая кнопка происходит от элемента управления с именем Button, но каждая кнопка является собственным независимым экземпляром этого исходного элемента управления. Чтобы они могли работать независимо, иметь разные свойства и так далее.

То же самое вы имеете с задачами или процессами ...
Ты меня понял ?

Ralf Meier

Внутри вашего 1-го фрагмента кода Вы всегда запускаете один и тот же процесс (именованный процесс). 2-й старт не имеет никакого значения.
Но... где вы приписываете что-то этому процессу-объекту ? В вашем фрагменте кода #2 у вас есть разные процессы (p1 ...), но где вы их используете (или запускаете)?

[no name]

(Что касается запроса на уточнение процесса и задачи) - я имею в виду процесс - внешнее приложение, которое я пытаюсь установить в качестве ребенка в своем собственном приложении (я понимаю, что есть некоторые проблемы, которые могут возникнуть из-за этого, однако с таким приложением, которое мои панели будут воспитывать, эти проблемы, вероятно, не имеют отношения ко мне.

Просто чтобы уточнить, несколько из этих же процессов будут установлены как дочерние внутри разных панелей (panel3, panel5, panel7 [вплоть до] panel19)

Я не слишком уверен, почему я объявил разные процессы по - разному (p1, p2 и т. д.) - Во время программирования этого, я, вероятно, думал, что это может вызвать ошибку, если я буду использовать "p" повсюду. Но все они относятся к одному и тому же процессу, который пользователь может открыть, нажав кнопку "Добавить".

Мне очень жаль, что я так плохо объясняю свою проблему, надеюсь, вы понимаете.

Просто чтобы прояснить, проблема заключается в том, что после установки первого окна процесса в качестве дочернего на моей панели, инициируя код снова, чтобы открыть и установить то же самое имя процесса в другую, отдельную панель, другую панель (чей связанный таймер все еще тикает, чтобы установить процесс внутри другой панели, а не панель, которая уже имеет окно, встроенное в качестве дочернего). Таким образом, по сути, мне просто нужно программно сказать таймеру остановиться, если процесс ("Mainwindow") был встроен, таким образом, встраивание того же процесса в другую панель не будет вмешиваться.

Я написал это в спешке и, вероятно, не связно, так что я понимаю, если вы все еще не понимаете. Сейчас я возвращаюсь домой, так что смогу объяснить более четко/связать скриншоты.

Серьезно, большое спасибо за ваше терпение. :-)

Ralf Meier

ОК... Давайте остановимся на самом главном.
Возможно, у нас есть проблема понимания ... но на это может быть несколько причин. Одна из них может заключаться в том, что мой английский не так хорош, как кажется ... :(

Итак ... еще раз - что вы хотите сделать ?
Вы запускаете "Блокнот" как процесс в панели 1 и запускаете "Блокнот" как процесс в панели 2. Что произойдет, если вы что-то отредактируете ? Должны ли обе панели иметь одинаковое содержание ... или по-другому ? Если я думаю, что вы хотите иметь другой, поэтому вам нужно создать 2-й независимый экземпляр Notepad (или MainWindow, или ...). Но на самом деле у вас есть только один процесс и один экземпляр процесса.



1 Ответов

Рейтинг:
1

Jaroslav Mitrovic

Привет, Хеллбой-2.

Я бы попытался запустить эти процессы с помощью Изменение панели

Если вы рассматриваете такой сценарий, как открытие окна командной строки, и хотите получить или установить вывод/ввод процесса, который является консолью, вам, возможно, понадобятся обработчики событий или дополнительные функции, которые управляют "вещами" внутри процесса-приложением/консолью и т. д.

Но главная причина, по которой я предлагаю это сделать, заключается в том, чтобы каким-то образом получить точный процесс в соответствии с панелями.

И с помощью ProcessStartInfo вы можете контролировать больше, например, закрыто ли оно или получить ProcessID для повторного обращения к нему.

Когда у вас есть информация (например, ProcessID), вы можете сохранить ее в свойстве MenuItemTag в MenuItem и сохранить там уникальные данные для процесса.



Другой подход состоял бы в том, чтобы создать "список(процессов)" процессов в вашем случае 10 и/или создать файл класса со свойствами, которые могут хранить процесс и меню, а также, возможно (я думаю, скорее нет!), иметь также свойство для панели.
Это будет использоваться только для создания элементов управления и добавления их в меню.

Класс Всем Привет :
Imports System.ComponentModel
Imports System.Windows.Forms

Public Class MyProcessIwanttoManage
    Private _process As Process

    Public Property Process As Process
        Get
            Return _process
        End Get
        Set
            _process = Value
        End Set
    End Property


    'I dontknow the ControllType atm, so ToolBarButton is wrong here!
    Private _menuItem As ToolBarButton

    Public Property MenuItem As ToolBarButton
        Get
            Return _menuItem
        End Get
        Set
            _menuItem = Value
        End Set
    End Property

    Private _additionalInfoIWantToManage As String

    Public Property AdditionalInfoIWantToManage As String
        Get
            Return _additionalInfoIWantToManage
        End Get
        Set
            _additionalInfoIWantToManage = Value
        End Set
    End Property

    Private _additionalInfoIWantToManageLikeTheProcessID As Integer

    Public Property AdditionalInfoIWantToManageLikeTheProcessID As Integer
        Get
            Return _additionalInfoIWantToManageLikeTheProcessID
        End Get
        Set
            _additionalInfoIWantToManageLikeTheProcessID = Value
        End Set
    End Property

End Class




Здесь рабочий пример использования ProcessInfoStart в CodeProject.



Может быть, это полезно для переосмысления процесса обработки.
Я также использовал ваш подход, когда начал использовать класс Process.
Очень скоро стало очевидно, что нужно использовать ProcessStarInfo-класс, прежде чем я начну процесс.

При этом мне удалось также контролировать положение и размеры всех дочерних окон (Process -> Window).

Также я получил контроль над "блокнотом"-окном (открытым, сфокусированным, закрытым и т. д.).

Что касается ваших панелей, то я не знаю, какой цели они служат.
Но я предполагаю, что вы используете панели, чтобы получить размер панели и (относительный) WindowPosition и отправьте их через PInvoke в "блокнот"-окно, чтобы переместить их на вашу панель.
Предположим, что панель не видна, почему бы не отправить состояние панели в соответствующее окно процесса (например, в окно "блокнот"), чтобы скрыть и показать и т. д.

Я использовал это для управления несколькими браузерами и Iteract с ними в VB6 лет назад, так что имейте в виду, что сейчас я не могу запомнить все obsticles, но это проверенный (по крайней мере, мной) способ управления приложениями вне собственного приложения.

c.u. Zui из Гамбурга