Окно стыковки внутри другого окна - PullRequest
10 голосов
/ 29 апреля 2011

У меня есть приложение winform (.NET 2.0 C #).Из этого приложения я хочу запустить другой процесс (другое приложение winform) и прикрепить его к моему окну (или, по крайней мере, сделать так, чтобы он был прикреплен).Пока что я могу найти информацию только об элементах управления стыковкой, а не о окнах в отдельных процессах.Моя первая мысль - получить ручку окна и использовать неуправляемые системные вызовы, чтобы установить высоту / ширину и положение окна в моей области стыковки.Но прежде чем начать, я хотел проверить, не делал ли кто-нибудь из вас, хороших людей, что-то подобное.У меня есть доступ к исходному коду приложения, которое я хочу закрепить, но я бы не стал вносить какие-либо изменения, если смогу его избежать.У меня есть полный программный контроль над тем, что будет родительским приложением.Любой совет?Заранее спасибо!

Ответы [ 3 ]

22 голосов
/ 11 мая 2011

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

5 голосов
/ 28 июня 2013

* Добавление некоторого решения в ответ. **

Этот код помог мне закрепить некоторые исполняемые файлы в форме Windows.как NotePad, Excel, Word, Acrobat Reader и многие другие ...

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

так что я сделал один трюк, чтобы решить эту проблему

Если вы получите дескриптор главного окна как нулевой ... тогда выполните поиск по всем запущенным процессам в sytem и найдите ваш процесс ... затем получите основную часть процессаи установить панель в качестве родителя.

            ProcessStartInfo info = new ProcessStartInfo();
            info.FileName = "xxxxxxxxxxxx.exe";
            info.Arguments = "yyyyyyyyyy";
            info.UseShellExecute = true;
            info.CreateNoWindow = true;
            info.WindowStyle = ProcessWindowStyle.Maximized;
            info.RedirectStandardInput = false;
            info.RedirectStandardOutput = false;
            info.RedirectStandardError = false;

            System.Diagnostics.Process p = System.Diagnostics.Process.Start(info); 

            p.WaitForInputIdle();
            Thread.Sleep(3000);

            Process[] p1 ;
        if(p.MainWindowHandle == null)
        {
            List<String> arrString = new List<String>();
            foreach (Process p1 in Process.GetProcesses())
            {
                // Console.WriteLine(p1.MainWindowHandle);
                arrString.Add(Convert.ToString(p1.ProcessName));
            }
            p1 = Process.GetProcessesByName("xxxxxxxxxxxx");
            //p.WaitForInputIdle();
            Thread.Sleep(5000);
           SetParent(p1[0].MainWindowHandle, this.panel2.Handle);
        }
         else
        {
           SetParent(p.MainWindowHandle, this.panel2.Handle);
        }
0 голосов
/ 30 апреля 2011

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

    //This is my docking window
    private System.Diagnostics.Process notepad;
    private void windowDockTest()
    {
        /*
         * Docking notepad to panel2 of the splitcontainer
         */

        //if panel2 moves or is resized, call the docking function
        spcScript.Panel2.Move += new EventHandler(Panel2_Resize);
        spcScript.Panel2.SizeChanged += new EventHandler(Panel2_Resize);

        //Call the docking function if main form is moved
        this.LocationChanged += new EventHandler(Panel2_Resize);

        //Start the notepad process
        notepad = new System.Diagnostics.Process();
        notepad.StartInfo.FileName = "notepad";
        notepad.Start();

        //Wait a second for notpad to fully load
        notepad.WaitForInputIdle(1000);

        //Dock it
        Panel2_Resize(new Object(), new EventArgs());
    }

    void Panel2_Resize(object sender, EventArgs e)
    {
        //Get the screen location of panel2
        Rectangle r = spcScript.Panel2.RectangleToScreen(spcScript.Panel2.ClientRectangle);

        //Dock it
        redock(notepad.MainWindowHandle, r.X, r.Y, r.Width, r.Height);
    }

    [DllImport("user32.dll")]
    public static extern IntPtr SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
    public static void redock(IntPtr handle, int x, int y, int width, int height)
    {
        IntPtr HWND_TOPMOST = new IntPtr(-1);
        const short SWP_NOACTIVATE = 0x0010;

        SetWindowPos(handle,HWND_TOPMOST, x, y, width, height,SWP_NOACTIVATE);
    }
...