2008-10-17 9 views
6

Mi aplicación es un ejecutable vb6, pero algunas formas más nuevas en el sistema están escritas en C#. Me gustaría poder establecer la propiedad Propietario del formulario C# utilizando un identificador en la ventana principal de la aplicación, para que los cuadros de diálogo permanezcan en la parte superior cuando se avanza y retrocede entre mi aplicación y otras aplicaciones.¿Puedo obtener el comportamiento de establecer el propietario de mi formulario WinForms usando un hwnd/NativeWindow?

Puedo obtener el hwnd de la ventana principal de la aplicación. No estoy seguro de lo que puedo hacer desde allí?


Actualización 20 de Oct '08 a las 17:06:

Scott,

Gracias por la respuesta. Había pasado por alto que el parámetro del método Show/ShowDialog no era de tipo Formulario; solo buscaba en la propiedad Owner.

Modifiqué ligeramente el código que estoy usando de los anteriores - tenemos un componente que carga nuestros Formularios y llama a ShowDialog. Mi código es el siguiente:

Form launchTarget = FormFactory.GetForm(xxx); // psuedo-code for generic form loader 
launchTarget.StartPosition = FormStartPosition.CenterParent; 
IWin32Window parentWindow = GetWindowFromHwnd(hwnd); 

launchTarget.ShowDialog(parentWindow); 

GetWindowFromHwnd es una versión método envueltas de su código:

private IWin32Window GetWindowFromHost(int hwnd) 
{ 
    IWin32Window window = null; 
    IntPtr handle = new IntPtr(hwnd); 

    try 
    { 
     NativeWindow nativeWindow = new NativeWindow(); 
     nativeWindow.AssignHandle(handle); 
     window = nativeWindow; 
    } 
    finally 
    { 
     handle = IntPtr.Zero; 
    } 

    return window; 
} 

Desafortunadamente esto no es hacer lo que yo esperaba. El formulario se muestra modalmente, pero no se muestra en la posición correcta ni está aún en la parte superior cuando elimino la pestaña y regreso a la ventana principal. Nuestros modales no muestran una tarea en la barra de tareas, por lo que la ventana aparentemente "desaparece" (aunque todavía está presente en la lista de ventanas de alt-tab). Eso para mí indica que podría no tener el derecho de hwnd. Si tiene alguna otra sugerencia, responda. Gracias de nuevo.


Actualización 10 de Nov '08 a las 16:25

Una observación de seguimiento - Si se toma hacia fuera en una llamada a un método en un try/finally, como en el segundo puesto de Scott, la llamada en el bloque finally debe ser:

parentWindow.ReleaseHandle(); 
+0

Scott - disculpa por la larga demora, se tiró en otras cosas. Su respuesta original enviada funciona muy bien. Solo necesitaba pasar NativeWindow a través de ShowDialog en lugar de configurar Form.Owner. Mi otro problema fue que el código de llamada no estaba pasando el hWnd correcto en primer lugar. Gracias – mcw0933

+0

FYI, ambos problemas anteriores son solucionables - para el centrado, asegúrese de establecer: "form.StartPosition = FormStartPosition.CenterParent" - para el toppyness asegúrese de establecer: form.TopMost = true; - Por cierto, gracias por la información en ReleaseHandle()! :-) – BrainSlugs83

Respuesta

9

Así se llama a una clase Form C# Windows desde Visual Basic 6, lo que significa que probablemente está usando ya sea Show() o ShowDialog(), correcto? Ambos métodos también toman un parámetro IWin32Window, que simplemente define un objeto que devuelve una propiedad IntPtr llamada Handle.

Por lo tanto ... necesita agregar un constructor sobrecargado (o método ShowDialog) para sus clases de Windows Forms que toman un long como parámetro para que pueda pasar el VW6 hwnd al formulario. Una vez dentro del código C#, necesita crear un IntPtr desde el hwnd y asignarlo a un objeto NativeWindow y luego pasarlo como el propietario.

Algo así como este trabajo debe , aunque es no probado:

public DialogResult ShowDialog(long hwnd) 
{ 
    IntPtr handle = new IntPtr(hwnd); 
    try 
    { 
     NativeWindow nativeWindow = new NativeWindow(); 

     nativeWindow.AssignHandle(handle); 
     return this.ShowDialog(nativeWindow); 
    } 
    finally 
    { 
     handle = IntPtr.Zero; 
    } 
} 
2

Esto es demasiado largo para publicar como un comentario ...

Creo que el problema está ejecutando en el que es el forma de envolver el código que presenté en la sobrecarga de ShowDialog.Si sigue lo que hace su código GetWindowFromHost, sigue los siguientes pasos:

  1. Crea un nuevo IntPtr a partir del hwnd dado.
  2. Crea un nuevo objeto NativeWindow y le asigna su manejador para ser el IntPtr.
  3. Establece IntPtr (en el bloque finally) para ser IntPtr.Zero.

Creo que es este bloque finalmente el que está causando problemas. En mi código, el bloque finally se ejecutará después de que finalice la llamada a this.ShowDialog(nativeWindow). En ese momento, el identificador (IntPtr) ya no se usaba. En su código, está devolviendo un IWin32Window que aún debería contener una referencia a ese IntPtr, que en el momento de llamar al launchTarget.ShowDialog(parentWindow) es IntPtr.Zero.

trate de cambiar su código para tener este aspecto:

private NativeWindow GetWindowFromHost(int hwnd) 
{ 
    IntPtr handle = new IntPtr(hwnd); 
    NativeWindow nativeWindow = new NativeWindow(); 
    nativeWindow.AssignHandle(handle); 
    return window; 
} 

y después cambiar su código de llamada a tener este aspecto:

Form launchTarget = FormFactory.GetForm(xxx); // psuedo-code for generic form 
loaderlaunchTarget.StartPosition = FormStartPosition.CenterParent; 
NativeWindow parentWindow = GetWindowFromHwnd(hwnd); 

try 
{ 
    launchTarget.ShowDialog(parentWindow); 
} 
finally 
{ 
    parentWindow.DestroyHandle(); 
} 

Estos cambios debería funcionar, pero de nuevo esto no se ha probado.

Cuestiones relacionadas