如何创建透明 Unity 窗口 + OS 的屏幕截图
Posted
技术标签:
【中文标题】如何创建透明 Unity 窗口 + OS 的屏幕截图【英文标题】:How to create a screenshot of a transparant Unity window + OS 【发布时间】:2020-03-09 10:50:34 【问题描述】:因此,对于我们正在尝试创建的应用程序,我们希望将独立应用程序的 Unity 窗口透明化(除了几个按钮之外的所有内容)并让用户一起截取他们的视图/操作系统 + 统一层.
例如: 用户打开我们的应用程序,单击一个按钮,整个统一窗口(除了几个按钮)变成透明的。然后,用户可以像平常一样使用它的操作系统,而前面提到的按钮保持在顶部。然后,用户可以单击按钮来创建他们操作系统的屏幕截图,然后我们将把它保存到他们的系统中。例如,我们可以通过屏幕截图在用户操作系统之上显示 Unity(3D 模型、图像)中的任何内容。
目前,我们可以通过类似这样的设置将窗口变为透明:https://alastaira.wordpress.com/2015/06/15/creating-windowless-unity-applications/
效果很好,在窗口等中单击也是如此。但是,我们现在想创建一个屏幕截图并将其保存在某个地方。为此,我们尝试了多种方法,几年前,在我们将这个项目放在一边之前,我们通过一个自定义 dll 让它工作,该 dll 使用我们从内部调用的“使用 System.Drawing”代码。请参阅下面的此 dll 和代码示例。
using System.Drawing;
namespace ScreenShotDll
public class ScreenShotClass
public static void TakeScreenShotRect(int srcX, int srcY, int dstX, int dstY) //both fullscreen screenshot and cropped rectangle screenshot
int width = Math.Abs(srcX - dstX);
int height = Math.Abs(srcY - dstY);
Bitmap memoryImage;
memoryImage = new Bitmap(width, height);
Size s = new Size(memoryImage.Width, memoryImage.Height);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.CopyFromScreen(srcX, srcY, 0, 0, s);
string str = "";
try
str = string.Format(AppDomain.CurrentDomain.BaseDirectory + @"Screenshot.png");
catch (Exception er)
Console.WriteLine("Sorry, there was an error: " + er.Message);
Console.WriteLine();
memoryImage.Save(str);
但是这似乎不再起作用了。我们在 Unity 的 IL2CPP 后端并收到错误:NotSupportedException: System.Drawing.Bitmap
我们也在尝试使用 Unity 中的 user32.dll 并使用它的 GetPixel、ReleaseDC 和 GetActiveWindow 函数,正如在几个论坛上发布的那样,但我们得到的只是一张白色图像。
任何调整我们的自定义 dll 的方法或任何其他方法都将受到高度赞赏。如果您需要更多信息,请告诉我。
【问题讨论】:
也许this 对你有帮助?也许您可以将其移植到运行时 @derHugo 我会看看。谢谢你。同时欢迎任何其他/新的建议。 @derHugo 不能移植它,因为它几乎完全依赖于 Unity 的编辑器功能。还有人有什么想法吗? 【参考方案1】:几天后,我设法在 Unity 中解决了这个问题。
我使用以下代码制作窗口的屏幕截图,并将其保存为位图。然后将其保存在我的磁盘上以 .png 格式。
[DllImport("user32.dll", SetLastError = true)] static extern int GetSystemMetrics(int smIndex);
[DllImport("user32.dll", SetLastError = false)] static extern IntPtr GetDesktopWindow();
[DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC", SetLastError=true)] static extern IntPtr CreateCompatibleDC([In] IntPtr hdc);
[DllImport("gdi32.dll", EntryPoint = "DeleteDC")] public static extern bool DeleteDC([In] IntPtr hdc);
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")] public static extern bool DeleteObject([In] IntPtr hObject);
[DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")] static extern IntPtr CreateCompatibleBitmap([In] IntPtr hdc, int nWidth, int nHeight);
[DllImport("gdi32.dll", EntryPoint = "SelectObject")] public static extern IntPtr SelectObject([In] IntPtr hdc, [In] IntPtr hgdiobj);
[DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)] static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);
private void screenShot()
Debug.Log("In screenShot!");
int nScreenWidth = GetSystemMetrics(0);
int nScreenHeight = GetSystemMetrics(1);
IntPtr hDesktopWnd = GetDesktopWindow();
IntPtr hDesktopDC = GetDC(hDesktopWnd);
IntPtr hCaptureDC = CreateCompatibleDC(hDesktopDC);
IntPtr hCaptureBitmap = CreateCompatibleBitmap(hDesktopDC, nScreenWidth, nScreenHeight);
SelectObject(hCaptureDC, hCaptureBitmap);
BitBlt(hCaptureDC, 0, 0, nScreenWidth, nScreenHeight, hDesktopDC, 0, 0, 0x00CC0020 | 0x40000000);
Bitmap bmp = Image.FromHbitmap(hCaptureBitmap);
ImageConverter converter = new ImageConverter();
byte[] bytes = (byte[])converter.ConvertTo(bmp, typeof(byte[]));
string path = Application.dataPath;
if (Application.platform == RuntimePlatform.OSXPlayer)
path += "/../../";
else if (Application.platform == RuntimePlatform.WindowsPlayer)
path += "/../";
File.WriteAllBytes(path + "Screenshot" + ".png", bytes);
ReleaseDC(hDesktopWnd, hDesktopDC);
DeleteDC(hCaptureDC);
DeleteObject(hCaptureBitmap);
【讨论】:
以上是关于如何创建透明 Unity 窗口 + OS 的屏幕截图的主要内容,如果未能解决你的问题,请参考以下文章