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

StackOverflow https://stackoverflow.com/questions/213661

  •  03-07-2019
  •  | 
  •  

Question

Mon application est un exécutable vb6, mais certains formulaires plus récents du système sont écrits en C #. J'aimerais 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 dialogue restent en haut lorsque vous faites des va-et-vient 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 DU 20 oct. 2008 à 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 enveloppée par une méthode de votre code:

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 répond pas à mes attentes. Le formulaire s’affiche de manière modale, mais il ne s’affiche ni dans la position correcte, ni au sommet de la liste lorsque je quitte la fenêtre par la fenêtre parent. Nos modaux n'affichent aucune tâche dans la barre des tâches. La fenêtre semble donc "disparaître". (bien qu'il soit toujours présent 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 DU 10 NOVEMBRE 2008 à 16h25

Remarque complémentaire: si vous en tenez compte dans un appel de méthode dans un essai / enfin, comme dans le second message de Scott, l'appel dans le bloc finally devrait être:

parentWindow.ReleaseHandle();
Était-ce utile?

La solution

Vous appelez donc 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 objet renvoyant une propriété IntPtr nommée Handle.

Donc ... vous devez ajouter un constructeur surchargé (ou une méthode ShowDialog) pour vos classes Windows Forms qui prennent un long en tant que paramètre afin de pouvoir transmettre le VB6 hwnd au formulaire. Une fois dans le code C #, vous devez créer un IntPtr à partir du hwnd et l'assigner à un objet NativeWindow , puis le transmettre en tant que propriétaire.

Quelque chose comme cela devrait fonctionner, même si cela 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;
   }
}

Autres conseils

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 instructions de votre code GetWindowFromHost , procédez comme suit:

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

Je pense que c'est finalement ce blocage qui vous pose problème. Dans mon code, le bloc finally s'exécuterait après l'appel à this.ShowDialog (nativeWindow) . À ce stade, le handle (IntPtr) n'était plus utilisé. Dans votre code, vous retournez un 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é.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top