window 切换需要 VisualStudio 调试
VisualStudio debugging required for window switching
先介绍一下我正在做的事情的背景。这是一个基于 C# 的启动器程序,允许在主要的家庭影院媒体播放器(在我的例子中是 Plex、MediaPortal 和 Kodi)之间轻松切换,以便它们都可以用于各自的优点(Plex 用于下载内容,MediaPortal 用于电视录音和直播电视,以及 Kodi 用于其他一切,通常是流媒体)。
这些应用程序使用 pssuspend 暂停,这意味着它们可以同时保持打开状态,这对于速度较慢的计算机来说非常有用。
用户按下按钮(在他们的遥控器上)切换回启动器以选择另一个应用程序。
我几乎处于可用版本,但我遇到了一段时间的问题,我已经缩小了范围。
如果我的启动器切换到一个应用程序(使用下面提到的方法),我无法切换回我的启动器进程。
这仅发生在:
- VisualStudio 未调试或 "Visual Studio hosting process"(进程的 vshost 版本)未 运行。
- 键盘/远程输入已应用于要切换到的应用程序
- 即:如果我向下移动到切换到的应用程序的任何位置,我可以很好地返回到启动器,但是一旦我在应用程序中按下任何其他按钮,我就无法切换出去。
- 正在切换 退出 已切换到的应用程序,而不是从启动器切换到该应用程序。
在所有其他时间,一切都按预期工作。
要切换,我目前使用的是SwitchToThisWindow(IntPtr hWnd, bool fAltTab)
(来自http://www.pinvoke.net/default.aspx/user32/SwitchToThisWindow.html)。
我也用过Microsoft.VisualBasic.Interaction.AppActivate
(来自http://msdn.microsoft.com/en-us/library/x9784w8e(v=vs.100).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1)。
两者的结果相同。
我已经确认的事情与问题无关:
- pssuspend:如果我在切换回启动器之前没有挂起应用程序就运行,同样的事情会发生
- 操作系统和计算机:我在 3 台计算机上都遇到了同样的问题,我的 Windows 8 安装和两个 Windows 7 安装
- 主屏幕 return 的侦听器:这是使用 EventGhost 的 UDP 广播并执行所有其他需要完成的操作,例如更新启动器上的界面,只是不切换到启动器
- 在本地机器上编译:我最初认为这有帮助,但只是因为上面的情况。在我的 Windows 8 机器上编译的版本在 Windows 7 上运行良好,只要该 vshost 进程处于打开状态。我没有在任何其他系统上尝试过。
- 以管理员身份运行没有效果
有一点不应该成为问题,但应该注意以防万一,即启动器的前端全部使用 CefSharp(CEF 是 Chrome 浏览器的集成版本)。
虽然这个问题是在添加之前发生的。
我的潜在想法:
- 由于
AppActivate
中提到的事情,我意识到 UIPermission 级别可能很重要,但是手动将其设置为完全信任不会产生任何变化。
我还在 VisualStudio 中意识到,"Security" 的属性设置为使用 "OneClick Security" 设置并且在 "This is a full trust application" 选项上。
这对我来说很有意义,因为调试器会授予它这些提升的权限,但大概这应该在没有调试运行的情况下工作。
我的应用在上下文中切换的一些代码:
[DllImport("user32.dll", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
static Process currentProcess = Process.GetCurrentProcess();
public static void SwitchToApplication(Process toSwitchTo)
{
SwitchProcess(toSwitchTo);
}
public static void SwitchToLauncher()
{
FrontendBridge.GetInstance().Reset();
SwitchProcess(Process.GetCurrentProcess());
Taskbar.Hide();
}
private static void SwitchProcess(Process toSwitchTo)
{
if (currentProcess == toSwitchTo)
return;
if (toSwitchTo.MainWindowHandle != IntPtr.Zero)
{
SwitchToThisWindow(toSwitchTo.MainWindowHandle,true);
}
currentProcess = toSwitchTo;
}
希望有人有一些想法或过去遇到过类似的问题。
如果您需要任何其他信息或源代码,请告诉我。
所以我设法解决了这个问题。
事实证明问题不是因为我的任何代码围绕这些 API 调用,也不是因为正在切换到自身的应用程序。
突破性答案来自这里:
http://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo
这解释了如何在调试时允许设置前景 window,但如果不调试,window 必须是最后一个获得键盘输入的,否则它不会获得焦点。
解决方案是让按住 alt 键的代码让 windows 允许我的程序设置前景 window,然后是 SetForegroundWindow 或 SwitchToThisWindow(切换到可能还没有打开的东西)可以使用。
我在这里找到了一个使用此代码的示例:
http://csharpapprentice.blogspot.co.nz/2013/03/ok-ok-its-c.html
先介绍一下我正在做的事情的背景。这是一个基于 C# 的启动器程序,允许在主要的家庭影院媒体播放器(在我的例子中是 Plex、MediaPortal 和 Kodi)之间轻松切换,以便它们都可以用于各自的优点(Plex 用于下载内容,MediaPortal 用于电视录音和直播电视,以及 Kodi 用于其他一切,通常是流媒体)。
这些应用程序使用 pssuspend 暂停,这意味着它们可以同时保持打开状态,这对于速度较慢的计算机来说非常有用。
用户按下按钮(在他们的遥控器上)切换回启动器以选择另一个应用程序。
我几乎处于可用版本,但我遇到了一段时间的问题,我已经缩小了范围。
如果我的启动器切换到一个应用程序(使用下面提到的方法),我无法切换回我的启动器进程。
这仅发生在:
- VisualStudio 未调试或 "Visual Studio hosting process"(进程的 vshost 版本)未 运行。
- 键盘/远程输入已应用于要切换到的应用程序
- 即:如果我向下移动到切换到的应用程序的任何位置,我可以很好地返回到启动器,但是一旦我在应用程序中按下任何其他按钮,我就无法切换出去。
- 正在切换 退出 已切换到的应用程序,而不是从启动器切换到该应用程序。
在所有其他时间,一切都按预期工作。
要切换,我目前使用的是SwitchToThisWindow(IntPtr hWnd, bool fAltTab)
(来自http://www.pinvoke.net/default.aspx/user32/SwitchToThisWindow.html)。
我也用过Microsoft.VisualBasic.Interaction.AppActivate
(来自http://msdn.microsoft.com/en-us/library/x9784w8e(v=vs.100).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1)。
两者的结果相同。
我已经确认的事情与问题无关:
- pssuspend:如果我在切换回启动器之前没有挂起应用程序就运行,同样的事情会发生
- 操作系统和计算机:我在 3 台计算机上都遇到了同样的问题,我的 Windows 8 安装和两个 Windows 7 安装
- 主屏幕 return 的侦听器:这是使用 EventGhost 的 UDP 广播并执行所有其他需要完成的操作,例如更新启动器上的界面,只是不切换到启动器
- 在本地机器上编译:我最初认为这有帮助,但只是因为上面的情况。在我的 Windows 8 机器上编译的版本在 Windows 7 上运行良好,只要该 vshost 进程处于打开状态。我没有在任何其他系统上尝试过。
- 以管理员身份运行没有效果
有一点不应该成为问题,但应该注意以防万一,即启动器的前端全部使用 CefSharp(CEF 是 Chrome 浏览器的集成版本)。 虽然这个问题是在添加之前发生的。
我的潜在想法:
- 由于
AppActivate
中提到的事情,我意识到 UIPermission 级别可能很重要,但是手动将其设置为完全信任不会产生任何变化。
我还在 VisualStudio 中意识到,"Security" 的属性设置为使用 "OneClick Security" 设置并且在 "This is a full trust application" 选项上。 这对我来说很有意义,因为调试器会授予它这些提升的权限,但大概这应该在没有调试运行的情况下工作。
我的应用在上下文中切换的一些代码:
[DllImport("user32.dll", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
static Process currentProcess = Process.GetCurrentProcess();
public static void SwitchToApplication(Process toSwitchTo)
{
SwitchProcess(toSwitchTo);
}
public static void SwitchToLauncher()
{
FrontendBridge.GetInstance().Reset();
SwitchProcess(Process.GetCurrentProcess());
Taskbar.Hide();
}
private static void SwitchProcess(Process toSwitchTo)
{
if (currentProcess == toSwitchTo)
return;
if (toSwitchTo.MainWindowHandle != IntPtr.Zero)
{
SwitchToThisWindow(toSwitchTo.MainWindowHandle,true);
}
currentProcess = toSwitchTo;
}
希望有人有一些想法或过去遇到过类似的问题。
如果您需要任何其他信息或源代码,请告诉我。
所以我设法解决了这个问题。
事实证明问题不是因为我的任何代码围绕这些 API 调用,也不是因为正在切换到自身的应用程序。
突破性答案来自这里:
http://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo
这解释了如何在调试时允许设置前景 window,但如果不调试,window 必须是最后一个获得键盘输入的,否则它不会获得焦点。
解决方案是让按住 alt 键的代码让 windows 允许我的程序设置前景 window,然后是 SetForegroundWindow 或 SwitchToThisWindow(切换到可能还没有打开的东西)可以使用。
我在这里找到了一个使用此代码的示例:
http://csharpapprentice.blogspot.co.nz/2013/03/ok-ok-its-c.html