【问题标题】:GetForegroundWindow not working when C# program is run from a shortcut key of a desktop shortcut从桌面快捷方式的快捷键运行 C# 程序时,GetForegroundWindow 不起作用
【发布时间】:2011-02-10 16:34:34
【问题描述】:

我正在尝试通过在我的应用程序的表单构造函数中调用本机 GetForegroundWindow WinAPI 函数来获取 C#/Net 2.0/WinForms 中前台窗口的句柄。

当我直接从 Windows Explorer 或 Total Commander 运行程序时,它会正确识别 Windows Explorer 或 Total Commander 窗口。

但是,如果我在桌面上为我的程序创建一个快捷方式并为该快捷方式设置一个快捷键(比如说 Ctrl+Alt+X),当我使用该快捷方式运行我的程序时,前台窗口被识别为“Shell_TrayWnd 窗口”(句柄 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 等其他功能吗?

谢谢

【问题讨论】:

    标签: c# windows winforms keyboard-shortcuts foreground


    【解决方案1】:

    注意任务栏可能在你调用GetForegroundWindow的时候才是真正的前台窗口,因为是Explorer在处理快捷键,任务栏属于Explorer(Shell_TrayWnd是窗口任务栏的类)。

    如果您想对全局活动窗口进行操作,最好启动应用程序并让它在后台等待。然后,您可以在应用程序运行时处理按键操作,因此 Explorer 不会干扰。

    不知怎的,这让我想起了Raymond Chen的一篇文章。

    【讨论】:

      【解决方案2】:

      我认为您正在尝试做与我相同的事情 — 从资源管理器中打开当前路径的 shell。

      我遇到了完全相同的问题。这是一个对我有用的程序。它使用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)。请注意,您不必直接在“资源管理器”窗口上即可工作 - 它会使用 Tab 键顺序中的下一个窗口。

      【讨论】:

        【解决方案3】:

        我不确定您需要前景窗口来做什么,所以这可能有帮助,也可能没有帮助:

        您可能可以通过以下方式检测到您是通过快捷方式启动的:

        在这种情况下,您可能会尝试获取按 Z 顺序排列的前一个窗口,或者在桌面窗口的顶部。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-10-12
          • 1970-01-01
          • 2022-10-19
          • 1970-01-01
          • 2013-03-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多