我在更改窗口的透明度方面遇到了问题。
我正在努力实现的目标
我开发了一个WPF应用程序,它与另一个应用程序(在Unity3D中开发的游戏)有一些交互。我的目标是将游戏“集成”到我的WPF应用程序中,使其看起来像游戏是WPF应用程序的自然组成部分。因此,当我移动主窗口时,我也使用PInvoke移动游戏窗口,我使用PInvoke来隐藏游戏窗口的窗口边界等。这一切都很有效。
然而,当我试图隐藏游戏而不关闭游戏时会出现问题。我的第一种方法是使用PInvoke将游戏窗口设置为隐藏:
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hwnd, int show);
const int SW_HIDE = 0;
const int SW_Show = 5;
ShowWindow(Handle, SW_HIDE);
使用此函数调用窗口会消失,但结果是游戏进程的CPU使用率从1%跃升至20%。到目前为止,我不知道为什么会这样。也许它与Unity有关,也许不是。 (但是当我再次显示窗口时CPU恢复正常)。
我的第二种方法不是使用ShowWindow调用隐藏窗口,而是将窗口的不透明度设置为0(as suggested in this thread)。在我的设置,这工作得很好(没有CPU疯狂),但在其他设置,窗口将保持可见。
更新图形驱动程序有时会解决问题,但并非总能如此。我有一台老式的Vista机器,一切正常,我也在安装了Windows 10的新款戴尔笔记本电脑上尝试过,它不起作用。我在使用Windows 10和Boot Camp的Mac上没有这个问题。所以我不知道是什么导致了这个问题。
有没有人遇到过类似的问题?有没有其他方法来隐藏窗口或有人知道为什么CPU在使用ShowWindow()方法时会发疯?
非常感谢任何提示。
修改
很高兴知道为什么这篇文章被大量投票,但没关系。我认为特别是CPU使用情况是一个有趣的问题,如果有人认为这很明显而且我是个白痴,我会非常抱歉。
对于那些也感兴趣的人来说,这是我的问题的最小WPF重建:
MainWindow.xaml
<Window x:Class="SampleWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="1024" Width="1280"
KeyDown="MainWindow_OnKeyDown">
<Grid>
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
const int SW_HIDE = 0;
const int SW_SHOW = 5;
private Process gameProcess;
private IntPtr gameWindowHandle;
private bool windowHidden = false;
public MainWindow()
{
InitializeComponent();
this.SizeChanged += OnSizeChanged;
}
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
StartGame();
}
private void MainWindow_OnKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
{
if (windowHidden)
{
NativeMethods.ShowWindow(gameWindowHandle, SW_HIDE);
windowHidden = false;
}
else
{
NativeMethods.ShowWindow(gameWindowHandle, SW_SHOW);
windowHidden = true;
}
}
}
private void StartGame()
{
var mainWindowHandle = new WindowInteropHelper(this).Handle;
var processStartInfo = new ProcessStartInfo(@"Path\To\SampleUnityApp.exe");
processStartInfo.Arguments += "-parentHWND " + mainWindowHandle.ToInt32() + " " + Environment.CommandLine + " ";
processStartInfo.CreateNoWindow = true;
processStartInfo.UseShellExecute = false;
gameProcess = Process.Start(processStartInfo);
gameProcess.WaitForInputIdle();
NativeMethods.EnumChildWindows(mainWindowHandle,
(hwnd, lparam) =>
{
// Set the window handle of the game
gameWindowHandle = hwnd;
return 0;
}, IntPtr.Zero);
}
static class NativeMethods
{
[DllImport("user32.dll")]
internal static extern bool ShowWindow(IntPtr hwnd, int show);
[DllImport("user32.dll")]
internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);
internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);
}
}
我使用的SampleUnityApp只是一个带有主摄像头的空白Unity项目。没有其他游戏对象。我写的没有代码。它是使用Unity 5.3.4f1 Personal创建的。