Domanda

Ho un applicazione WPF che voglio guardare come è ospitato all'interno di un altro - non-WPF - applicazione.Nella vita reale questo non applicazione WPF è un ActiveX all'interno di Internet Explorer, ma per il bene di illustrare il problema, io uso un semplice Windows Form app.

Io uso la funzione API di Windows SetParent, che ci sono decine di discussioni già.Tuttavia non riesco a trovare nulla di scritto sul mio problema: Una piccola regione in basso e a destra dell'applicazione WPF non è dipinto all'interno non WPF finestra dell'applicazione.

La finestra WPF in esecuzione da solo:
alt text

La finestra WPF con WinForm app finestra del genitore:
alt text

Non ho esperienza il problema se una di swap l'applicazione WPF con un form di windows app o una normale applicazione di Win32 (come il blocco note).

WinForm il codice simile a questo:

private void Form1_Load(object sender, EventArgs e)
    {
        // Start process
        var psi = new ProcessStartInfo("c:\\wpfapp\\wpfapp\\bin\\Debug\\wpfapp.exe");
        psi.WindowStyle = ProcessWindowStyle.Normal;
        _process = Process.Start(psi);

        // Sleep until new process is ready
        Thread.Sleep(1000);

        // Set new process's parent to this window
        SetParent(_process.MainWindowHandle, this.Handle);

        // Remove WS_POPUP and add WS_CHILD window style to child window
        const int GWL_STYLE = -16;
        const long WS_POPUP = 0x80000000;
        const long WS_CHILD = 0x40000000;
        long style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
        style = (style & ~(WS_POPUP)) | WS_CHILD;
        SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);

        // Move and resize child window to fit into parent's
        MoveWindow(_process.MainWindowHandle, 0, 0, this.Width, this.Height, true);
    }

Nota:Sono consapevole che questo uso di SetParent non è necessariamente una pratica consigliata, ma mi desidera e la necessità di trovare il modo di farlo in questo modo, quindi, si prega di lasciare me :)

È stato utile?

Soluzione

Ho trovato una soluzione che funziona abbastanza bene:Chiamata MoveWindow prima SetParent:

private void Form1_Load(object sender, EventArgs e)
{
     // Start process            
     var psi = new ProcessStartInfo("C:\\WpfApp\\WpfApp.exe");
     psi.WindowStyle = ProcessWindowStyle.Normal;
     _process = Process.Start(psi);

     // Sleep until new process is ready
     Thread.Sleep(3000);

     // Move and resize child window to fit into parent's
     Rectangle rect;
     GetClientRect(this.Handle, out rect);
     MoveWindow(_process.MainWindowHandle, 0, 0, rect.Right - rect.Left, rect.Bottom - rect.Top, true);

     // Set new process's parent to this window
     SetParent(_process.MainWindowHandle, this.Handle);

     // Remove WS_POPUP and add WS_CHILD window style to child window
     long style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
     style = (style & ~(WS_POPUP) & ~(WS_CAPTION)) & ~(WS_THICKFRAME) | WS_CHILD;
     SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);
}           

Nel SizeChanged gestore di eventi, di prendere il bambino al di fuori del genitore, chiamata MoveWindow e riportarlo nella capogruppo.Per ridurre lo sfarfallio, nascondere la finestra, mentre facendo queste operazioni:

private void Form1_SizeChanged(object sender, EventArgs e)
{
     ShowWindow(_process.MainWindowHandle, SW_HIDE);

     var ptr = new IntPtr();
     SetParent(_process.MainWindowHandle, ptr);

     Rectangle rect;
     GetClientRect(this.Handle, out rect);

     MoveWindow(_process.MainWindowHandle, 0, 0, rect.Right - rect.Left, rect.Bottom - rect.Top, true);            
     SetParent(_process.MainWindowHandle, this.Handle);
     ShowWindow(_process.MainWindowHandle, SW_SHOW);
}

non spiega perché MoveWindow non funziona dopo SetParent, ma non risolve il mio problema, quindi mi segno la risposta, a meno che qualcosa di meglio arriva.

Altri suggerimenti

Probabilmente si dovrà ridimensionare la finestra WPF in modo che si adatta alla area clienti la sua principale nuova finestra:

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

[DllImport("user32.dll")]
static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);

// Move and resize child window to fit into parent's client area.
RECT rc = new RECT();
GetClientRect(this.Handle, out rc);
MoveWindow(_process.MainWindowHandle, 0, 0, rc.Right - rc.Left,
    rc.Bottom - rc.Top, true)

Ho usato un Modulo / UserControl con un Pannello.Poi ho usato il Pannello come nuovo padre e impostare la nuova posizione e la dimensione del pannello con SetWindowPos alla finestra figlio.

NOTA:MS consiglia di utilizzare SetWindowPos dopo l'utilizzo di SetWindowLong (o SetWindowLongPtr) per attivare i nuovi stili.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top