2010-04-21 9 views
0

J'essaie d'obtenir un handle de la fenêtre de premier plan dans C#/Net 2.0/WinForms en appelant la fonction WinAPI GetForegroundWindow native, dans la forme de mon application constructeur. Lorsque j'exécute le programme directement à partir de Windows Explorer ou Total Commander, il identifie correctement la fenêtre Windows Explorer ou Total Commander.GetForegroundWindow ne fonctionne pas lorsque le programme C# est exécuté à partir d'une touche de raccourci

Cependant, si je crée un raccourci vers mon programme sur le bureau et définir une touche de raccourci pour le raccourci (disons Ctrl + Alt + X), quand je suis en cours d'exécution de mon programme en utilisant le raccourci, est identifié la fenêtre de premier plan comme la "fenêtre Shell_TrayWnd" (poignée 0x00010064), et non la fenêtre réelle. (Disons que je suis en cours d'exécution de Firefox sur le dessus, quand j'appuyez sur Ctrl + Alt + X démarrage de mon programme et dit que la fenêtre de premier plan n'est pas Firefox, comme il se doit, il dit que c'est la barre des tâches -. Shell_TrayWnd)

public MainForm() 
    { 
     this.InitializeComponent(); 

     IntPtr handle = WinAPI.GetForegroundWindow(); 
     this.Text = handle.ToString(); 
     StringBuilder title = new StringBuilder(255); 
     if (WinAPI.GetWindowText(handle, title, 255) > 0) 
     { 
      this.Text += title.ToString(); 
     } 
    } 

Comment puis-je obtenir la vraie fenêtre de premier plan? Dois-je (aussi) utiliser d'autres fonctions comme GetWindow?

Merci

Répondre

1

Notez que la barre des tâches peut être la vraie fenêtre de premier plan au moment où vous appelez GetForegroundWindow, simplement parce qu'il est l'explorateur qui est la manipulation de la presse de raccourci, et la barre des tâches appartient à Explorer (Shell_TrayWnd est la classe de fenêtre de la barre des tâches).

Si vous voulez faire quelque chose avec la fenêtre globale active, il vaut mieux démarrer votre application et la laisser attendre en arrière-plan. Ensuite, vous pouvez gérer les pressions sur les touches pendant que votre application est en cours d'exécution, de sorte que l'Explorateur n'interfère pas.

D'une certaine façon, cela me rappelle un article de Raymond Chen.

0

Je pense que vous essayez de faire la même chose que je suis — ouvrir un shell à partir de l'explorateur sur le chemin actuel.

J'ai rencontré exactement le même problème. Voici un programme qui fonctionne pour moi. Il utilise EnumWindows pour rechercher dans toutes les fenêtres visibles jusqu'à ce qu'il trouve celui dont le titre est un chemin réel.

using System; 
using System.IO; 
using System.Text; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 

public class ShellHere 
{ 
    // Thanks to pinvoke.net for the WinAPI stuff 

    [DllImport("user32.dll")] 
    private static extern int EnumWindows(CallBackPtr callPtr, int lPar); 

    [DllImport("user32.dll")] 
    static extern int GetWindowText(int hWnd, StringBuilder text, int count); 

    [DllImport("user32.dll", EntryPoint="GetWindowLong")] 
    private static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, GWL nIndex); 

    [DllImport("user32.dll", EntryPoint="GetWindowLongPtr")] 
    private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, GWL nIndex); 

    public delegate bool CallBackPtr(int hwnd, int lParam); 
    private static CallBackPtr _callBackPtr; 

    // This static method is required because Win32 does not support 
    // GetWindowLongPtr directly 
    public static IntPtr GetWindowLongPtr(IntPtr hWnd, GWL nIndex) 
    { 
     if (IntPtr.Size == 8) 
      return GetWindowLongPtr64(hWnd, nIndex); 
     else 
      return GetWindowLongPtr32(hWnd, nIndex); 
    } 

    public static bool FindPathInTitle(int hwnd, int lparams) 
    { 
     const int nChars = 256; 
     StringBuilder buffer = new StringBuilder(nChars); 

     IntPtr result = GetWindowLongPtr(new IntPtr(hwnd), GWL.GWL_STYLE); 

     // ignore invisible windows 
     if ((result.ToInt64() & WS_VISIBLE) != 0) 
     { 
      if (GetWindowText(hwnd, buffer, nChars) > 0) 
      { 
       string title = buffer.ToString(); 

       // ignore the taskbar 
       if (title.ToLower() != "start" && Directory.Exists(title)) 
       { 
        _folder = title; 
        return false; 
       } 
      } 
     } 

     return true; 
    } 

    private static string _folder; 

    public static void Main() 
    { 
     _callBackPtr = new CallBackPtr(FindPathInTitle); 
     EnumWindows(_callBackPtr, 0); 

     Process shell = new Process(); 
     shell.StartInfo.FileName = "cmd.exe"; 
     if (!string.IsNullOrEmpty(_folder)) 
      shell.StartInfo.WorkingDirectory = _folder; 
     shell.Start(); 
    } 

    public enum GWL 
    { 
     GWL_WNDPROC = (-4), 
     GWL_HINSTANCE = (-6), 
     GWL_HWNDPARENT = (-8), 
     GWL_STYLE =  (-16), 
     GWL_EXSTYLE = (-20), 
     GWL_USERDATA = (-21), 
     GWL_ID =  (-12) 
    } 

    // Window Styles 
    const UInt32 WS_VISIBLE = 0x10000000; 
} 

Cela fonctionne pour moi jusqu'à présent (Win7-64). Notez que vous n'avez pas besoin d'être directement dans la fenêtre de l'Explorateur pour que cela fonctionne — il utilisera le suivant dans l'ordre des onglets.

0

Je ne suis pas sûr de ce que vous avez besoin de la fenêtre de premier plan pour, donc cela pourrait ou non aider à:

Vous pouvez probablement détecter que vous commencé par un raccourci par:

Dans ce cas, vous pouvez essayer d'obtenir la fenêtre t Le précédent est dans l'ordre Z, ou en haut sur la fenêtre du bureau.