我需要实现一个截屏功能,截屏我已经实现了,但是当我的计算机锁定后,进入登录桌面后,截屏就失败了,截的是黑屏,我的问题是怎么样才能在计算机锁定后进入登录桌面我的程序还能截屏?
截屏代码
var hWnd = WinAPI.GetDesktopWindow();
IntPtr hSrcDC = WinAPI.GetWindowDC(hWnd);
WinAPI.SetThreadDesktop(hSrcDC);
IntPtr hDC = g.GetHdc();
int retval = WinAPI.BitBlt(hDC, 0, 0, GetPhysicalDisplaySize().Width, GetPhysicalDisplaySize().Height, hSrcDC, 0, 0, (int)(CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt));
g.ReleaseHdc();
windows api
[DllImport("user32.dll")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr ptr);
[DllImport("user32.dll")]
public static extern bool SwitchDesktop(IntPtr hDesktop);
[DllImport("user32.dll")]
public static extern IntPtr CreateDesktop(string lpszDesktop,
IntPtr lpszDevice,
IntPtr pDevmode,
int dwFlags,
uint dwDesiredAccess,
IntPtr lpsa);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr OpenInputDesktop(uint dwFlags, bool fInherit, uint dwDesiredAccess);
[DllImport("user32.dll", EntryPoint = "CloseDesktop", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseDesktop(IntPtr handle);
[DllImport("user32.dll")]
public static extern IntPtr OpenDesktop(string lpszDesktop,
uint dwFlags,
bool fInherit,
uint dwDesiredAccess);
[DllImport("user32.dll")]
public static extern bool SetThreadDesktop(IntPtr hDesktop);
我写了写给你
using System.Drawing;
using System.Runtime.InteropServices;
// 定义 Windows API 函数
[DllImport("user32.dll")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("gdi32.dll")]
public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSrc, int xSrc, int ySrc, int rop);
[DllImport("user32.dll")]
public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
// 定义截屏函数
public static Bitmap CaptureScreen()
{
// 获取桌面窗口句柄
IntPtr hWnd = GetDesktopWindow();
// 获取桌面窗口的设备上下文
IntPtr hDC = GetWindowDC(hWnd);
// 获取桌面窗口的尺寸
Rectangle rect = new Rectangle(0, 0, GetPhysicalDisplaySize().Width, GetPhysicalDisplaySize().Height);
// 创建位图
Bitmap bmp = new Bitmap(rect.Width, rect.Height);
// 创建位图的图形上下文
Graphics g = Graphics.FromImage(bmp);
// 将桌面窗口的图像复制到位图的图形上下文
IntPtr hDC2 = g.GetHdc();
bool retval = BitBlt(hDC2, 0, 0, rect.Width, rect.Height, hDC, 0, 0, (int)CopyPixelOperation.SourceCopy);
g.ReleaseHdc(hDC2);
// 释放桌面窗口的设备上下文
ReleaseDC(hWnd, hDC);
// 返回位图
return bmp;
}
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr OpenInputDesktop(uint dwFlags, bool fInherit, uint dwDesiredAccess);
[DllImport("user32.dll")]
public static extern bool SetThreadDesktop(IntPtr hDesktop);
// 访问桌面和窗口
public static void AccessDesktop()
{
// 打开输入桌面
IntPtr hDesktop = OpenInputDesktop(0, false, DESKTOP_SWITCHDESKTOP);
// 设置线程桌面
bool retval = SetThreadDesktop(hDesktop);
}
#然后,在服务中使用 BitBlt() 函数将屏幕的内容复制到缓冲区。 例如,您可以使用以下代码将屏幕的内容复制到缓冲区:
// 定义常量
public const int SRCCOPY = 0x00CC0020;
// 将屏幕的内容复制到缓冲区
public static void CopyScreenToBuffer(IntPtr hDC, Bitmap bmp)
{
// 获取屏幕的设备上下文
IntPtr hSrcDC = GetWindowDC(GetDesktopWindow());
// 创建位图的图形上下文
Graphics g = Graphics.FromImage(bmp);
// 将屏幕的图像复制到位图的图形上下文
IntPtr hDC2 = g.GetHdc();
bool ret
val = BitBlt(hDC2, 0, 0, bmp.Width, bmp.Height, hSrcDC, 0, 0, SRCCOPY);
g.ReleaseHdc(hDC2);
// 释放屏幕的设备上下文
ReleaseDC(GetDesktopWindow(), hSrcDC);
}
#最后,在服务中使用 Save() 方法将缓冲区的内容保存到文件中。 例如,您可以使用以下代码将缓冲区的内容保存到文件中:
// 保存缓冲区的内容到文件
public static void SaveBufferToFile(Bitmap bmp, string fileName)
{
bmp.Save(fileName);
}
你有没有想过,你代码没问题,是你运行的时候没有权限呢?
0、运行
1、锁屏
2、登录
3、还在运行
那么就涉及到有后台运行的情况,在后台运行的时候,某些情况,是需要有权限的,你懂不?
截屏需要使用UI交互,所以需要一个有用户权限的session
所以你需要用类似windows服务跨越session0的手段去做
一个参考
https://stackoverflow.com/questions/5200341/capture-screen-on-server-desktop-session
ps:这个也是系统特别设计,比如系统自己带的3389,你可以远程登录,然后各自用各自的桌面,互不干扰。所以UI是用户session挂沟,你锁定此时没有任何用户挂沟,所以UI的就是黑的
提供一篇笔记供你参考【关于java:计算机锁定时是否可以通过编程方式截取屏幕截图?】,链接:https://www.codenong.com/53842821/
在计算机锁定后进入登录桌面时,由于登录桌面是在系统级别运行的,所以访问权限较低,需要获取特殊的权限才能进行截屏。
在 Windows 操作系统中,您可以使用 Microsoft GDI (Graphics Device Interface) 库中的函数,比如 BitBlt() 或 PrintWindow() 来实现截屏功能。这些函数可以在系统级别访问窗口,所以即使在登录桌面锁定状态下,也可以截取屏幕。
您可以尝试使用 OpenCV 或其他图像处理库来读取这些函数的输出,这样就可以在锁定登录桌面时获取屏幕截图。
代码实现大概长这样:
HDC hScreenDC = GetDC(NULL);
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
SelectObject(hMemoryDC, hBitmap);
BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, 0, 0, SRCCOPY);
// 然后就可以使用 OpenCV 或其他图像库将这个 hBitmap 转换成 cv::Mat 类型的图像了。
cv::Mat img = cv::cvarrToMat(hBitmap);
// 使用完之后,释放资源
DeleteDC(hScreenDC);
DeleteDC(hMemoryDC);
DeleteObject(hBitmap);
这只是代码的大体思路,具体的代码请根据您的需要来改进。
需要注意的是,可能需要特殊权限或管理员权
权限问题导致的,那么下面是一些可能有用的解决方案。
1.如果你是在UWP应用程序中使用截屏功能,那么需要在应用程序的manifest中添加"窗口"权限。可以在你项目里面找到"Package.appxmanifest'"文件并打开,在里面添加一个名为"窗口”的声明。
2.如果你是在桌面应用程序中使用截屏功能,那么你需要确保程序具有足够的权限运行。可以尝试以管理员身份运行程序来解决这个问题。可以右键点击程序图标,然后选择"以管理员身份运行”
3.检查你的程序运行的环境,确保在程序运行时不会受到其他的权限限制.比如防火墙,杀毒软件,运行环境等
4.确保你所使用的用户帐户具有足够的权限。例如使用管理员身份运行程序。
5.可以尝试更新你的程序,确保使用的是最新的API
6.可以尝试在不同的机器上运行你的程序,来确认问题是否与本机环境有关