GetForegroundWindow не работает, когда программа C # запускается с помощью сочетания клавиш на рабочем столе - PullRequest
0 голосов
/ 21 апреля 2010

Я пытаюсь получить дескриптор окна переднего плана в C # / Net 2.0 / WinForms, вызывая встроенную функцию WinAPI GetForegroundWindow в конструкторе формы моего приложения.

Когда я запускаю программу прямо из WindowsExplorer или Total Commander, он правильно определяет окно Windows Explorer или Total Commander.

Однако, если я создаю ярлык для моей программы на рабочем столе и устанавливаю клавишу быстрого доступа для ярлыка (скажем, Ctrl + Alt + X), когда я запускаю свою программу с помощью ярлыка, окно переднего плана идентифицируется как «Shell_TrayWnd window» (дескриптор 0x00010064), а не как фактическое окно.(Допустим, я запускаю Firefox сверху, когда я нажимаю Ctrl + Alt + X, моя программа запускается и говорит, что окно переднего плана не Firefox, как и должно быть, оно говорит, что это панель задач - 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();
        }
    }

Как мне получить реальное окно переднего плана?Должен ли я (также) использовать другие функции, такие как GetWindow?

Спасибо

Ответы [ 3 ]

1 голос
/ 21 апреля 2010

Обратите внимание, что панель задач может быть реальным окном переднего плана во время вызова GetForegroundWindow, просто потому что это Explorer, который обрабатывает нажатие клавиш, а панель задач принадлежит Explorer (Shell_TrayWnd - класс окна панели задач).

Если вы хотите что-то сделать с глобальным активным окном, вам может быть лучше, если вы запустите свое приложение и подождите, пока оно будет работать в фоновом режиме. Затем вы можете обрабатывать нажатия клавиш во время работы вашего приложения, поэтому Explorer не будет мешать работе.

Почему-то это напоминает мне статью Раймонда Чена .

0 голосов
/ 23 сентября 2010

Я не уверен, для чего вам нужно окно переднего плана, так что это может или не может помочь:

Вы, вероятно, можете обнаружить, что вы начали через ярлык по:

В этом случае вы можете попытаться получить предыдущее окно в Z-порядке или сверху в окне рабочего стола.

0 голосов
/ 23 сентября 2010

Я думаю, вы пытаетесь сделать то же самое, что и я - открыть оболочку из Проводника по текущему пути.

Я столкнулся с точно такой же проблемой. Вот программа, которая работает для меня. Он использует EnumWindows для поиска во всех видимых окнах, пока не найдет то, чей заголовок является реальным путем.

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

Пока это работает для меня (Win7-64). Обратите внимание, что вам не нужно находиться непосредственно в окне проводника, чтобы он работал - он будет использовать следующий в порядке вкладок.

...