Puis-je avoir le comportement de définition du propriétaire de mon formulaire WinForms à l’aide d’un hwnd / NativeWindow?

Mon application est un exécutable vb6, mais certains formulaires plus récents du système sont écrits en C #. Je souhaite pouvoir définir la propriété Owner du formulaire C # à l’aide d’un descripteur dans la fenêtre principale de l’application, afin que les boîtes de dialog restnt en haut lors de la tabulation entre mon application et d’autres applications.

Je peux obtenir le hwnd de la fenêtre principale de l’application. Je ne suis pas sûr de ce que je peux faire à partir de là?


MISE À JOUR 20 Octobre 08 à 17h06:

Scott,

Merci pour la réponse. J’avais oublié que le paramètre de méthode Show / ShowDialog n’était pas de type Form – je ne cherchais que la propriété Owner.

J’ai légèrement modifié le code que j’utilise à partir de ce qui précède – nous avons un composant qui charge de manière générique nos formulaires et appelle ShowDialog. Mon code ressemble à ceci:

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

GetWindowFromHwnd est une version de votre code GetWindowFromHwnd méthodes:

 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; } 

Malheureusement, cela ne fait pas ce que j’avais espéré. Le formulaire s’affiche de manière modale, mais il ne s’affiche pas dans la position correcte ni au sumt de la liste lorsque je quitte la fenêtre et me ramène à la fenêtre parente. Nos modaux ne montrent pas une tâche dans la barre des tâches, donc la fenêtre semble “disparaître” (même si elle est toujours présente dans la liste de la fenêtre alt-tab). Pour moi, cela indique que je pourrais ne pas avoir le droit hwnd. Si vous avez d’autres suggestions, veuillez répondre. Merci encore.


MISE À JOUR 10 novembre 08 à 16h25

Remarque complémentaire: si vous intégrez un appel de méthode dans un essai / un appel final, comme dans le deuxième message de Scott, l’appel du bloc finally devrait être:

 parentWindow.ReleaseHandle(); 

Donc, vous appelez une classe Windows Form C # à partir de VB6, ce qui signifie que vous utilisez probablement Show() ou ShowDialog() , n’est-ce pas? Ces deux méthodes utilisent également un paramètre IWin32Window, qui définit simplement un object renvoyant une propriété IntPtr appelée Handle.

Donc … vous devez append un constructeur surchargé (ou une méthode ShowDialog) pour vos classes Windows Forms, qui prend un long paramètre, de sorte que vous puissiez passer le VB6 hwnd au formulaire. Une fois dans le code C #, vous devez créer un IntPtr à partir du hwnd et l’assigner à un object NativeWindow , puis le transmettre en tant que propriétaire.

Quelque chose comme ça devrait marcher, même si ça n’a pas été testé:

 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; } } 

C’est trop long pour poster en tant que commentaire …

Je pense que le problème que vous rencontrez est la façon dont vous avez enveloppé le code que j’ai présenté dans la surcharge ShowDialog. Si vous suivez les GetWindowFromHost votre code GetWindowFromHost procédez comme suit:

  1. Crée un nouveau IntPtr à partir du hwnd donné.
  2. Crée un nouvel object NativeWindow et assigne son handle à IntPtr.
  3. Définit IntPtr (dans le bloc finally) sur IntPtr.Zero.

Je pense que c’est finalement ce bloc qui vous pose problème. Dans mon code, le bloc finally s’exécuterait après l’appel à this.ShowDialog(nativeWindow) terminé. À ce stade, le handle (IntPtr) n’était plus utilisé. Dans votre code, vous retournez une IWin32Window qui devrait toujours contenir une référence à cet IntPtr, qui au moment où vous appelez launchTarget.ShowDialog(parentWindow) est IntPtr.Zero.

Essayez de changer votre code pour qu’il ressemble à ceci:

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

Et changez ensuite votre code d’appel pour qu’il ressemble à ceci:

 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(); } 

Ces modifications devraient fonctionner, mais encore une fois, cela n’a pas été testé.