【问题标题】:SetForegroundWindow only working while visual studio is openSetForegroundWindow 仅在 Visual Studio 打开时工作
【发布时间】:2012-05-31 04:56:12
【问题描述】:

我正在尝试使用 c# 将进程窗口设置为前台/焦点(从当时没有焦点的应用程序),因此我使用 user32.dll static extern bool SetForegroundWindow(IntPtr hWnd) 方法:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd); 
public void setFocus()
{
    SetForegroundWindow(process.MainWindowHandle);       
}

一切正常,但只要我打开了visual studio 2008,我什至不需要从VS08启动应用程序,用它打开项目就足够了。在我关闭项目的那一刻,我的应用程序无法将另一个窗口设置为前台。唯一的结果是,在任务栏中,另一个窗口以蓝色突出显示。当我要再次使用 VS08 打开我的项目时,它工作正常。

我一点也不知道为什么...我认为问题可能是他无法导入 dll 但它不会被突出显示,并且其他 win32 函数(如static extern bool ShowWindow(IntPtr hWnd, IntPtr status);)即使在项目时也能正常工作已关闭。

这个问题的任何解决方案或提示?

编辑: 我看了这个函数的注释,我的想法是我的应用程序没有焦点,所以我尝试了这个:

[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
static extern bool AllowSetForegroundWindow(int procID);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); 
public void setAUTFocus()
{
    IntPtr hWnd = GetForegroundWindow();
    uint processID = 0;
    uint threadID = GetWindowThreadProcessId(hWnd, out processID);
    int intID = (int)processID;
    AllowSetForegroundWindow(intID);
    SetForegroundWindow(process.MainWindowHandle); 
}        

现在我正在搜索当前具有焦点的窗口进程并为此窗口设置AllowSetForegroundWindow 并尝试现在将焦点设置在我的窗口上。但是同样的问题,当我在 VS 中打开项目时它正在工作,如果不是,我只会在任务栏中得到蓝色突出显示。

在我的应用程序运行期间,我可以打开/关闭 vs 项目,它打开的那一刻一切正常,它关闭的那一刻它不起作用,我在运行我的应用程序时与 VS 项目没有交互。说真的,我不明白。

【问题讨论】:

  • 见SetForeground窗口文档msdn.microsoft.com/en-us/library/windows/desktop/…中的备注
  • 所以当我试图将另一个窗口放在前面时,我必须先调用函数 AllowSetForegroundWindow,并使用焦点窗口的进程 id ?
  • 这不是为什么它在 VS 项目打开时工作的原因,当前前台窗口永远不是 VS
  • 这不是答案,我只是发表评论以引起您对此事的注意
  • 这不适用于 UWP,因为此平台不支持检索有关本地进程的信息。

标签: c# visual-studio window focus


【解决方案1】:

在互联网上搜索了几天后,我找到了一种使 SetForegroundWindow 在 Windows 7 上工作的可行简单解决方案:在调用 SetForegroundWindow 之前按 Alt 键。

public static void ActivateWindow(IntPtr mainWindowHandle)
    {
        //check if already has focus
        if (mainWindowHandle == GetForegroundWindow())  return;

        //check if window is minimized
        if (IsIconic(mainWindowHandle))
        {
            ShowWindow(mainWindowHandle, Restore);
        }

        // Simulate a key press
        keybd_event((byte)ALT, 0x45, EXTENDEDKEY | 0, 0);

        //SetForegroundWindow(mainWindowHandle);

        // Simulate a key release
        keybd_event((byte)ALT, 0x45, EXTENDEDKEY | KEYUP, 0);

        SetForegroundWindow(mainWindowHandle);
    }

win32api 导入

  private const int ALT = 0xA4;
  private const int EXTENDEDKEY = 0x1;
  private const int KEYUP = 0x2;
  private const uint Restore = 9;

  [DllImport("user32.dll")]
  private static extern bool SetForegroundWindow(IntPtr hWnd);

  [DllImport("user32.dll")]
  private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

  [DllImport("user32.dll")]
  [return: MarshalAs(UnmanagedType.Bool)]
  private static extern bool IsIconic(IntPtr hWnd);

  [DllImport("user32.dll")]
  private static extern int ShowWindow(IntPtr hWnd, uint Msg);

  [DllImport("user32.dll")]
  private static extern IntPtr GetForegroundWindow();

【讨论】:

  • 为什么需要按 Alt 键?
  • 如果不模拟 Alt 键,setforgroundwindow 将无法正常工作。您要切换到的程序,它会在任务栏中闪烁,但不会出现在前台。当您从 Visual Studio 运行程序并进行调试时,Setforgroundwindow 工作正常。
  • 感谢您的回答。顺便说一句,非常奇怪的行为。我很高兴对此有详细的解释。
  • 抱歉,未在 Windows 10 上测试
  • 它适用于 Windows 10,您甚至不必模拟 alt 键向下,只需向上
【解决方案2】:

我在发送 Alt 键时遇到问题,因为当我选择 Enter 时它会强制打开窗口菜单(而不是我想要的 OK 按钮)。

这对我有用:

public static void ActivateWindow(IntPtr mainWindowHandle)
{
    //check if already has focus
    if (mainWindowHandle == GetForegroundWindow())  return;

    //check if window is minimized
    if (IsIconic(mainWindowHandle))
    {
        ShowWindow(mainWindowHandle, Restore);
    }

    // Simulate a key press
    keybd_event(0, 0, 0, 0);

    SetForegroundWindow(mainWindowHandle);
}

【讨论】:

  • keybd_event(0, 0, 0, 0); = Keys.NONE 在 Windows 7 中被内部过滤掉。但是,在 Windows 10 之后,它没有被 Windows 过滤掉,并且对应用程序有意想不到的影响。因此,如果您对此非常确定,请使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-26
相关资源
最近更新 更多