我试图通过调用应用程序窗体构造函数中的本机GetForegroundWindow WinAPI函数来获取C#/NET2.0/WinForms中的前台窗口的句柄。
当我直接从Windows资源管理器或总指挥官运行程序时,它可以正确识别Windows资源管理器或总指挥官窗口。
但是,如果我在桌面上创建了一个程序的快捷方式,并为该快捷方式设置了一个快捷键(比方说Ctrl+Alt+X),当我使用该快捷方式运行我的程序时,前景窗口被标识为"Shell_TrayWnd窗口“(句柄0x00010064),而不是实际的窗口。(假设我在顶部运行Firefox,当我按Ctrl+Alt+X时,我的程序启动,并指出前景窗口不是Firefox,因为它应该是taskbar -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?
谢谢
发布于 2010-04-22 00:17:21
请注意,在调用GetForegroundWindow时,任务栏可能是真正的前台窗口,原因很简单,因为它是资源管理器处理快捷键,而任务栏属于资源管理器(Shell_TrayWnd是任务栏的窗口类)。
如果您想要对全局活动窗口执行某些操作,那么启动应用程序并让其在后台等待可能会更好。这样,您就可以在应用程序运行时处理按键操作,这样Explorer就不会受到干扰。
不知何故,这让我想起了Raymond Chen的一篇文章。
发布于 2010-09-23 13:37:09
我认为您正在尝试做与我相同的事情--在当前路径下从Explorer打开一个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键顺序中的下一个窗口。
发布于 2010-09-23 16:47:55
我不确定您需要前景窗口的目的是什么,因此这可能会有帮助,也可能没有帮助:
您可能可以通过以下方式检测到您是通过快捷方式启动的:
针对STARTF_TITLEISLINKNAME
调用GetStartupInfo
dwFlags
的在这种情况下,您可能会尝试获取Z顺序中的前一个窗口,或桌面窗口的顶部。
https://stackoverflow.com/questions/2684562
复制相似问题