2010-04-07 13 views
6

Lorsque vous hébergez des contrôles utilisateur WPF dans une application WinForms MDI, un problème de mise en plan se produit lorsque plusieurs formulaires se chevauchent et provoquent des artefacts visuels très distincts. Ces artefacts sont principalement visibles après avoir fait glisser un formulaire enfant sur un autre qui héberge également le contenu WPF ou en permettant aux bords du formulaire enfant d'être découpés par le parent MDI principal lors de son déplacement. Une fois que le glisser-déposer du formulaire enfant est terminé, les artefacts restent généralement, mais j'ai trouvé ce réglage sur une fenêtre d'application différente, puis je me suis recentré sur ma fenêtre d'application pour la redessiner et tout va bien jusqu'à ce que l'enfant les formulaires sont déplacés une fois de plus. S'il vous plaît voir l'image ci-dessous qui démontre le problème.Comment éviter les artefacts visuels lors de l'hébergement de contrôles utilisateur WPF dans une application WinForms MDI?

Screenshot of described artifacts

Ceux de Microsoft insistent sur le fait que le WinForms MDI est déjà une solution suffisante pour MDI et n'a pas besoin de réinventer en WPF bien que je trouve difficile de croire qu'ils ont essayé de créer une application WPF de cette façon à cause de la lacunes évidentes.

MISE À JOUR: Quelques notes supplémentaires que j'ai laissées de côté sont que si je crée ces formulaires sans définir le MdiParent, ils sont créés comme des formulaires normaux et ce problème ne se produit pas. Ce problème semble unique au scénario WinForms MDI. Aussi, je suis actuellement sous Windows 7 Enterprise et je suis conscient que les résultats peuvent être très différents sur Windows XP mais je n'ai pas pu le tester.

MISE À JOUR: J'ai trouvé quelques autres ressources connexes sur ce problème que je pensais que je devrais partager.

Répondre

2

Eh bien, je peux avoir trouvé une solution bien qu'il se sent comme un peu d'un hack. Il semble que si vous appelez la méthode Refresh sur le parent MDI à chaque fois qu'un formulaire MDI enfant est déplacé, les artefacts notés disparaissent. Visuellement, les choses semblent un peu nerveuses lorsque vous faites glisser une fenêtre, mais cela semble beaucoup plus acceptable que l'exemple que j'ai montré dans mon post original.

private void Form1_Move(object sender, EventArgs e) 
{ 
    this.ParentForm.Refresh(); 

    System.Diagnostics.Debug.WriteLine(string.Format("Form Moved to: ({0},{1})", this.Left, this.Top)); 
} 

J'ai essayé beaucoup de combinaisons dans le même ordre d'idées telles que rafraîchissants la fenêtre de l'enfant qui a été déplacé par des méthodes d'appel telles que Update(), Invalidate(), Refresh() et aussi j'ai essayé ces mêmes méthodes sur le parent MDI ainsi que Dispatcher.Invoke (DispatcherPriority.Render, ...) et InvalidateVisual() sur mon contrôle WPF hébergé, mais aucune de ces autres méthodes a travaillé pour accepter appelant Actualiser() spécifiquement sur le M DI parent. Je me rends compte que ce n'est probablement pas la solution optimale puisque je force l'ensemble de la fenêtre de l'application principale à se rafraîchir chaque fois qu'une fenêtre enfant déplace quelques pixels, mais pour le moment c'est la seule solution raisonnable que j'ai trouvée travaux. Si quelqu'un d'autre a des solutions de rechange ou des améliorations à ce sujet, j'accepterai volontiers votre réponse à la place.

8

Il semble qu'une autre solution consiste à revenir au rendu logiciel plutôt que de tirer parti de l'accélération matérielle.C'était le suggestion by Marco Zhou sur les forums MSDN.

public partial class UserControl1 : UserControl 
{ 
    public UserControl1() 
    { 
     InitializeComponent(); 
     this.Loaded += delegate 
     { 
      var source = PresentationSource.FromVisual(this); 
      var hwndTarget = source.CompositionTarget as HwndTarget; 
      if (hwndTarget != null) 
      { 
       hwndTarget.RenderMode = RenderMode.SoftwareOnly; 
      } 
     }; 
    } 
} 

Je l'ai testé cela et cette solution semble très bien fonctionner et jusqu'à présent est la seule solution que j'ai trouvé pour résoudre ce problème dans un scénario Interop FoxPro qui est très similaire aux WinForms un I posté à propos de l'origine. Pour l'instant, je prévois d'utiliser mon Refresh original sur la solution MDI Parent pour mon projet WinForms, mais pour mes autres applications d'interopérabilité natives, comme lorsque mes contrôles WPF sont hébergés dans Visual FoxPro, j'utiliserai cette solution. C'est à moins, bien sûr, si une solution plus élégante est découverte pour l'un ou l'autre des cas. Il est également important de noter que, d'après ce que je sais, le rendu logiciel est la seule option sur les systèmes XP et normalement WinForms Visual FoxPro profite normalement du même type d'accélération matérielle que les applications natives WPF sur Vista OS et en haut Donc, l'utilisation de cette option peut ne pas être aussi mauvaise qu'elle le semble lorsque vous devez faire face à interop. À l'heure actuelle, je ne suis au courant d'aucun effet secondaire lié à l'utilisation de cette solution, mais s'il y en a, il faudrait en tenir compte sérieusement.

2

Vérifiez les pilotes vidéo et essayez de désactiver l'accélération matérielle. La plupart des artefacts sont causés par de mauvais pilotes, une carte vidéo défaillante ou un temps insuffisant pour terminer l'actualisation.

Première étape de dépannage: Mettre à jour les pilotes vidéo. Évident, je sais. J'ai rencontré un problème similaire, en vérifiant les paramètres de ma carte vidéo (NVidia Control Panel), le réglage global était très élevé, ce qui entraînait un intervalle de rafraîchissement plus long qui peut être interrompu si la durée est trop longue. Le rétablissement de mes paramètres par défaut a permis de résoudre la plupart des problèmes. Mais je lance aussi des programmes de hachage qui utilisent intensivement le GPU donc c'est probablement la cause de mon problème d'artefacts qui reste très rarement maintenant et qui montre surtout sa face laide dans Visual Studio. Une autre étape de dépannage que j'ai exécutée consiste à désactiver l'accélération matérielle pour WPF, ceci peut être fait dans 'HKEY_CURRENT_USER/SOFTWARE/Microsoft/Avalon.Graphics', ou peut-être une application peut le faire MAIS ceci est seulement pour le dépannage; ne les définissez jamais dans une application car elle sera désactivée pour TOUTES les applications WPF. Je n'ai pas ce paramètre de registre et je ne l'ai pas ajouté, donc je ne suis pas sûr du succès, mais beaucoup disent que cela a résolu leur problème. Notez également que certaines applications ont cette option disponible, essayez de la désactiver si elle est disponible.

Une autre étape de dépannage consiste à s'assurer que la carte vidéo est un niveau approprié pour le rendu. Toute carte qui prend en charge DX9 ou plus devrait être suffisante, mais d'autres facteurs sont impliqués (comme c'est mon cas), donc juste parce qu'il est sur la liste ne signifie pas qu'il est adapté à votre objectif. Enfin, vous pouvez utiliser Visual Profiler (partie de Windows SDK) et d'autres outils pour vous aider à déterminer ce qui se passe de façon plus précise lorsque WPF manque de performances en termes de capacité graphique.

notes de niveau Tier rendu et WPF information sur le rendement ->http://msdn.microsoft.com/en-us/library/vstudio/ms742196(v=vs.90).aspx

Hope this helps quelqu'un.

--Ryan Strassburg

0

Votre usercontrol ou un événement chargé de la fenêtre;

this.WindowState = System.Windows.WindowState.Minimized; 

this.WindowState = System.Windows.WindowState.Normal; 

cela peut sembler une mauvaise solution. pas besoin de vous heurter la tête contre le mur.Un proverbe turc dit: le meilleur code est le code est en cours d'exécution :)