2010-08-13 10 views
6

Si j'énumère des fenêtres dans Application.Current.Windows, comment puis-je dire, pour deux fenêtres quelconques, laquelle est "plus proche" (c'est-à-dire a un z-index plus grand)?Comment trier Windows par z-index?

Ou, pour dire la même chose en d'autres termes, comment puis-je trier ces fenêtres par z-index?

Répondre

6

Vous ne pouvez pas obtenir les informations d'une commande Z de Windows à partir de WPF, vous devez donc utiliser Win32.

Quelque chose comme cela devrait faire l'affaire:

var topToBottom = SortWindowsTopToBottom(Application.Current.Windows.OfType<Window>()); 
... 

public IEnumerable<Window> SortWindowsTopToBottom(IEnumerable<Window> unsorted) 
{ 
    var byHandle = unsorted.ToDictionary(win => 
    ((HwndSource)PresentationSource.FromVisual(win)).Handle); 

    for(IntPtr hWnd = GetTopWindow(IntPtr.Zero); hWnd!=IntPtr.Zero; hWnd = GetNextWindow(hWnd, GW_HWNDNEXT) 
    if(byHandle.ContainsKey(hWnd)) 
     yield return byHandle[hWnd]; 
} 

const uint GW_HWNDNEXT = 2; 
[DllImport("User32")] extern IntPtr GetTopWindow(IntPtr hWnd); 
[DllImport("User32")] extern IntPtr GetNextWindow(IntPtr hWnd, uint wCmd); 

La façon dont cela fonctionne est:

  1. Il utilise un dictionnaire pour indexer les fenêtres données par la poignée de fenêtre, en utilisant le fait que l'implémentation Windows de WPF, PresentationSource de Windows est toujours HwndSource.
  2. Il utilise Win32 pour analyser toutes les fenêtres non exécutées de haut en bas pour trouver l'ordre approprié.
+0

Et oui, désolé, cela nécessite une autorisation de code non géré ("confiance totale"). –

+0

Je l'accepterai néanmoins, car c'est la seule réponse à ce jour. –

+0

Pourriez-vous s'il vous plaît jeter un oeil à ma dernière question? Je voudrais vraiment voir votre angle sur le problème. http://stackoverflow.com/questions/3642763/static-verification-of-bindings –

0

Ah c'était vraiment amusant un:

[DllImport("user32.dll")] 
static extern IntPtr GetActiveWindow(); 

public static Window ActiveWindow 
{ 
    get 
    { 
     return HwndSource.FromHwnd(GetActiveWindow()).RootVisual as Window; 
    } 
} 

Il vous donnera la fenêtre active dans votre application (qui est généralement le lieu).

+0

Je pense que ce n'est pas qu'il voulait dire –

+2

Non seulement ce n'est pas ce que je voulais dire, mais il faut aussi une confiance totale (comme tout P/Invoke). Et il pourrait même en valoir la peine, n'était-ce pas facilement réalisable avec la propriété 'Window.IsActive'. –