简体   繁体   English

从桌面快捷方式的快捷键运行C#程序时,GetForegroundWindow不起作用

[英]GetForegroundWindow not working when C# program is run from a shortcut key of a desktop shortcut

I'm trying to get a handle to the foreground window in C#/Net 2.0/WinForms by calling the native GetForegroundWindow WinAPI function, in my app's form's constructor. 我试图通过在应用程序窗体的构造函数中调用本机GetForegroundWindow WinAPI函数来获取C#/ Net 2.0 / WinForms中前景窗口的句柄。

When I run the program directly from Windows Explorer or Total Commander, it correctly identifies the Windows Explorer or Total Commander window. 当我直接从Windows资源管理器或Total Commander运行程序时,它可以正确识别Windows资源管理器或Total Commander窗口。

However, if I create a shortcut to my program on desktop and set a shortcut key for the shortcut (let's say Ctrl+Alt+X), when I'm running my program using the shortcut, the foreground window is identified as the "Shell_TrayWnd window" (Handle 0x00010064), and not the actual window. 但是,如果我在桌面上创建程序的快捷方式并设置该快捷方式的快捷键(例如Ctrl + Alt + X),则当我使用快捷方式运行程序时,前景窗口将被标识为“ Shell_TrayWnd窗口”(句柄0x00010064),而不是实际窗口。 (Let's say I'm running Firefox on top, when I press Ctrl+Alt+X my program starts and says that the foreground window is not Firefox, as it should, it says it's the taskbar - Shell_TrayWnd.) (假设我在最上面运行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();
        }
    }

How can I get the real foreground window? 如何获得真正的前景窗口? Should I (also) use other functions like GetWindow? 我也应该使用其他功能,例如GetWindow吗?

Thank you 谢谢

Note that the task bar may be the real foreground window at the time you call GetForegroundWindow, simply because it's Explorer who's handling the shortcut press, and the task bar belongs to Explorer (Shell_TrayWnd is the window class of the task bar). 请注意,在您调用GetForegroundWindow时,任务栏可能是真正的前台窗口,这仅仅是因为是由资源管理器处理快捷键,并且任务栏属于资源管理器(Shell_TrayWnd是任务栏的窗口类)。

If you want to do something with the global active window, you may be better off by starting your application and letting it wait in the background. 如果您想对全局活动窗口执行某些操作,最好通过启动应用程序并让其在后台等待而更好。 Then you can handle key presses while your application is running, so Explorer won't interfere. 然后,您可以在应用程序运行时处理按键操作,这样资源管理器就不会受到干扰。

Somehow, this reminds me of an article by Raymond Chen . 不知何故,这让我想起了Raymond Chen的一篇文章。

I think you're trying to do the same thing as I am — open a shell from Explorer at the current path. 我认为您正在尝试做与我相同的事情-在当前路径下从Explorer打开外壳。

I ran into exactly the same problem. 我遇到了完全相同的问题。 Here's a program that's working for me. 这是一个对我有用的程序。 It uses EnumWindows to search through all visible windows until it finds one whose title is a real path. 它使用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;
}

It's working for me so far (Win7-64). 到目前为止,它对我有用(Win7-64)。 Note that you don't have to be directly on the Explorer window for it to work — it'll use the next one in the tab order. 请注意,您不必直接在“资源管理器”窗口中就可以正常工作-它会以制表符顺序使用下一个。

I'm not sure what you need the foreground window for, so this might or might not help: 我不确定您需要前台窗口做什么,因此这可能会或可能不会有帮助:

You probably can detect that you were started through a shortcut by: 您可能可以通过以下方式检测到您是通过快捷方式启动的:

In that case you might try to get the window that's previous in Z order, or on top on the Desktop window. 在这种情况下,您可以尝试获取Z顺序中先前的窗口,或“桌面”窗口顶部的窗口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM