2013-12-04 2 views
1

Привет Я пытаюсь разместить exe (блокнот) в приложении WPF. Пожалуйста, найдите код здесь:Хостинг внешних exe в WPF

public partial class MainWindow : Window 
{ 
    private Process _process; 
    private System.Windows.Forms.Panel _panel; 

    [DllImport("user32.dll")] 
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); 

    [DllImport("user32.dll", SetLastError = true)] 
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex); 

    [DllImport("user32")] 
    private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent); 

    [DllImport("user32")] 
    private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags); 

    private const int SWP_NOZORDER = 0x0004; 
    private const int SWP_NOACTIVATE = 0x0010; 
    private const int GWL_STYLE = -16; 
    private const int WS_CAPTION = 0x00C00000; 
    private const int WS_THICKFRAME = 0x00040000; 
    const string patran = "patran"; 
    public MainWindow() 
    { 
     InitializeComponent(); 
     _process = Process.Start("notepad.exe"); 

     _panel = new System.Windows.Forms.Panel(); 
     wfHost.Child = _panel; 
     var patranPanelHandle = _panel.Handle; 
     SetParent(_process.MainWindowHandle, patranPanelHandle); 

     // remove control box 
     int style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE); 
     style = style & ~WS_CAPTION & ~WS_THICKFRAME; 
     SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style); 
     // resize embedded application & refresh 
     ResizeEmbeddedApp(); 
    } 

    private void ResizeEmbeddedApp() 
    { 
     if (_process == null) 
      return; 
     SetWindowPos(_process.MainWindowHandle, IntPtr.Zero, 0, 0, (int)_panel.Width, (int)_panel.Height, SWP_NOZORDER | SWP_NOACTIVATE); 
    } 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     Size size = base.MeasureOverride(availableSize); 
     ResizeEmbeddedApp(); 
     return size; 
    } 
} 

же код отлично работает для Winforms, так что я использовал WinformsHost, а затем добавили панель WinForms и, как описано выше. Но результаты не так ожидаемы. Блокнота приходит вне приложения WPF и родитель ребенка не работает надлежащим

ответа не отвечал за this слишком

ответ

1

Я думаю, вы призываете SetParent слишком рано. Вы должны сделать SetParent после того, как будут открыты оба родительских и дочерних окна. Итак, что вы можете сделать, это подождать, пока родительское окно будет Loaded, а затем запустит Child Process. Однако вызовите WaitForInputIdle в дочернем процессе, прежде чем вы вызовете SetParent.

Ниже приведен пример кода, я попробовал и это работает:

public partial class MainWindow : Window 
{ 
    private Process _process; 

    [DllImport("user32.dll")] 
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); 

    [DllImport("user32.dll", SetLastError = true)] 
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex); 

    [DllImport("user32")] 
    private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent); 

    [DllImport("user32")] 
    private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags); 

    private const int SWP_NOZORDER = 0x0004; 
    private const int SWP_NOACTIVATE = 0x0010; 
    private const int GWL_STYLE = -16; 
    private const int WS_CAPTION = 0x00C00000; 
    private const int WS_THICKFRAME = 0x00040000; 
    const string patran = "patran"; 
    public MainWindow() 
    { 
     InitializeComponent(); 

     Loaded += (s, e) => LaunchChildProcess(); 
    } 

    private void LaunchChildProcess() 
    { 
     _process = Process.Start("notepad.exe"); 
     _process.WaitForInputIdle(); 

     var helper = new WindowInteropHelper(this); 

     SetParent(_process.MainWindowHandle, helper.Handle); 

     // remove control box 
     int style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE); 
     style = style & ~WS_CAPTION & ~WS_THICKFRAME; 
     SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style); 
     // resize embedded application & refresh 
     ResizeEmbeddedApp(); 
    } 

    private void ResizeEmbeddedApp() 
    { 
     if (_process == null) 
      return; 
     SetWindowPos(_process.MainWindowHandle, IntPtr.Zero, 0, 0, (int)ActualWidth, (int)ActualHeight, SWP_NOZORDER | SWP_NOACTIVATE); 
    } 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     Size size = base.MeasureOverride(availableSize); 
     ResizeEmbeddedApp(); 
     return size; 
    } 

Для получения дополнительной информации о WaitForInputIdle, пожалуйста, обратитесь к этой странице MSDN.

ОБНОВЛЕНИЕ

Прикрепление результата изображения:

enter image description here