C#搞跨平台桌面UI,分别实现Windows,Mac,Linux屏幕截图
搞跨平台IM,截图功能少不了。
Windows
创建GDI的兼容位图,把桌面的图像通过BitBlt拷贝到兼容位图里,通过兼容位图的数据指针创建Bitmap对象,由于兼容位图的内存是非托管的,Bitmap无法释放该内存,拷贝一下,把兼容位图的释放掉,新的Bitmap的内存就可以由新Bitmap来自己托管释放。
public override Bitmap Screenshot()
{
var srcDC = GetDC(IntPtr.Zero);
var bounds = Bounds; IntPtr memDc = CreateCompatibleDC(srcDC);
BITMAPINFOHEADER info = new BITMAPINFOHEADER();
info.biSize = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADER));
info.biBitCount = 32;
info.biHeight = -(int)bounds.Height;
info.biWidth = (int)bounds.Width;
info.biPlanes = 1;
var hBitmap = CreateDIBSection(memDc, ref info, 0, out var ppvBits, IntPtr.Zero, 0);
var oldBits = SelectObject(memDc, hBitmap); BitBlt(memDc, 0, 0, (int)bounds.Width,
(int)bounds.Height, srcDC, (int)bounds.X, (int)bounds.Y, TernaryRasterOperations.SRCCOPY);
Bitmap temp = new Bitmap((int)bounds.Width, (int)bounds.Height, (int)bounds.Width * 4, PixelFormat.Bgra, ppvBits); Bitmap bitmap = (Bitmap)temp.Clone();
temp.Dispose(); SelectObject(memDc, oldBits);
DeleteObject(hBitmap);
DeleteDC(memDc); ReleaseDC(IntPtr.Zero, srcDC);
return bitmap;
}

Mac
直接使用Mac里的 CGWindowListCreateImage 来截图,由于数据格式不同,需要读取像素,一个个设置给Bitmap
Mac里在不同权限选项下截取的图片内容不同的,没有录制权限的情况下只能截取当前程序的界面和空的桌面。
public unsafe override Bitmap Screenshot()
{
using (var img = new CGImage(CGImage.CGWindowListCreateImage(screen.Frame, CGWindowListOption.All, 0, CGWindowImageOption.Default), owns: true))
{
//CGImage imageRef = CGImage.CGWindowListCreateImage(mainRect, kCGWindowListOptionOnScreenOnly, kCGNullWindowID, kCGWindowImageNominalResolution | kCGWindowImageShouldBeOpaque);
var height = img.Height;
var width = img.Width;
var bpr = img.BytesPerRow;
var bpp = img.BitsPerPixel;
var bpc = img.BitsPerComponent;
var bytes_per_pixel = bpp / bpc; using (var data = img.DataProvider.CopyData())
{
var bitmap = new Bitmap(img.Width, img.Height);
var bytes = (byte*)data.Bytes;
using (var b = bitmap.Lock())
{
for (var row = 0; row < height; row++)
{
for (var col = 0; col < width; col++)
{
var pixel = &bytes[row * bpr + col * bytes_per_pixel]; b.SetPixel(col, row, pixel[3], pixel[2], pixel[1], pixel[0]);
}
}
}
return bitmap;
}
}
}



Linux
使用XGetImage来截图,同样需要转换一下位图格式
public override Bitmap Screenshot()
{
var bounds = Bounds;
var image = XGetImage(LinuxPlatform.Platform.Display, LinuxPlatform.Platform.Info.RootWindow, (int)bounds.X, (int)bounds.Y, (int)bounds.Width,
(int)bounds.Height, ~0, 2 /* ZPixmap*/);
if (image == IntPtr.Zero)
{
string s = String.Format("XGetImage returned NULL when asked to for a {0}x{1} region block",
bounds.Width, bounds.Height);
throw new InvalidOperationException(s);
} Bitmap bmp = new Bitmap((int)bounds.Width, (int)bounds.Height);
var visual = LinuxPlatform.Platform.Info.TransparentVisualInfo;
int red, blue, green;
int red_mask = (int)visual.red_mask;
int blue_mask = (int)visual.blue_mask;
int green_mask = (int)visual.green_mask;
using (var b = bmp.Lock())
{
for (int y = 0; y < bounds.Height; y++)
{
for (int x = 0; x < bounds.Width; x++)
{
var pixel = XGetPixel(image, x, y); switch (visual.depth)
{
case 16: /* 16bbp pixel transformation */
red = (int)((pixel & red_mask) >> 8) & 0xff;
green = (int)(((pixel & green_mask) >> 3)) & 0xff;
blue = (int)((pixel & blue_mask) << 3) & 0xff;
break;
case 24:
case 32:
red = (int)((pixel & red_mask) >> 16) & 0xff;
green = (int)(((pixel & green_mask) >> 8)) & 0xff;
blue = (int)((pixel & blue_mask)) & 0xff;
break;
default:
string text = string.Format("{0}bbp depth not supported.", visual.depth);
throw new NotImplementedException(text);
} b.SetPixel(x, y, 255, (byte)red, (byte)green, (byte)blue);
}
}
} XDestroyImage(image);
return bmp;
}

上面的就是CPF的内部实现,一般你不需要管这些细节,直接调用CPF的函数就行了。
最终封装到CPF就是一行代码就行
window.Screen.Screenshot();
要实现QQ截图的效果的话,先截图,再搞个全屏的窗体,把截图内容放到里面,再对屏幕截图进行裁剪,绘图处理。


C#搞跨平台桌面UI,分别实现Windows,Mac,Linux屏幕截图的更多相关文章
- [.net 面向对象程序设计深入](5)MVC 6 —— 构建跨平台.NET开发环境(Windows/Mac OS X/Linux)
[.net 面向对象程序设计深入](5)MVC 6 —— 构建跨平台.NET开发环境(Windows/Mac OS X/Linux) 1.关于跨平台 上篇中介绍了MVC的发展历程,说到ASP.NET ...
- BesLyric 全新版本下载 ( windows \ mac \ linux )
导读 BesLyric , 一款专门制作 网易云音乐 LRC 滚动歌词的软件! 搜索.下载.制作 歌词更方便! 很荣幸地,自 beslyric 2017 年开发推出以来,得到了很多云村村民的肯定,现在 ...
- OpenGL环境搭建Windows+Mac+Linux
OpenGL环境搭建Windows+Mac+Linux Mac平台下 下载列表:GLFWcmake 下载的GLFW解压缩 然后安装cmake, 安装好cmake之后打开 1.browse source ...
- SSH客户端,FinalShell服务器管理,远程桌面加速软件,支持Windows,Mac OS X,Linux,版本2.6.3.1
FinalShell是一体化的的服务器,网络管理软件,不仅是ssh客户端,还是功能强大的开发,运维工具,充分满足开发,运维需求. 用户QQ群 342045988 Windows版下载地址:http:/ ...
- 实现一个跨平台的mysock库(windows、linux)
源码下载 1.首先确定自己的操作系统为32位还是64位: root@bfq:~/mysock# uname -a Linux bfq 3.11.0-26-generic#45~precise1- ...
- centos7 通过kvm+vnc 实现远程桌面虚拟化和创建windows、Linux虚拟机
感谢朋友支持本博客.欢迎共同探讨交流,因为能力和时间有限.错误之处在所难免,欢迎指正! 假设转载.请保留作者信息. 博客地址:http://blog.csdn.net/qq_21398167 原博文地 ...
- 全网最详细的Git学习系列之介绍各个Git图形客户端(Windows、Linux、Mac系统皆适用ing)(图文详解)
不多说,直接上干货! 一.TortoiseGit - The coolest Interface to Git Version Control TortoiseGit 是 TortoiseSVN 的 ...
- C#搞跨平台UI,封装Cef作为Cpf的控件支持Windows,Linux,Mac
终于封装完成了,采用离屏渲染方式,支持JS和C#互相调用,C#方法自动绑定到JS里,中文输入有自动调整输入法位置. 基于开源的CefGlue 移植,本来想用CefSharp,不过这个里面有很多C++的 ...
- 原创|我是如何从零学习开发一款跨平台桌面软件的(Markdown编辑器)
原始冲动 最近一直在学习 Electron 开发桌面应用程序,目的是想做一个桌面编辑器,虽然一直在使用Typore这款神器,但无奈Typore太过国际化,在国内水土不服,无法满足我的一些需求. 比如实 ...
随机推荐
- CentOS安装Redis报错[server.o] Error 1
原因 准备安装的Redis服务版本为6.0.8, gcc的版本为4.8.5,可能是gcc版本过低到导致的 解决办法 安装低版本Redis或者安装高版本gcc
- ThinkPHP5中出现unserialize()报错
简述 unserialize(): Error at offset 533 of 1857 bytes 发现问题 dump一下出错的位置的变量,可以发现是缓存出了问题,改了名字的文件的路径对不上 解决 ...
- Java 并发编程(一) → LockSupport 详解
开心一刻 今天突然收到花呗推送的消息,说下个月 9 号需要还款多少钱 我就纳了闷了,我很长时间没用花呗了,怎么会欠花呗钱? 后面我一想,儿子这几天玩了我手机,是不是他偷摸用了我的花呗 于是我找到儿子问 ...
- 【tee小白的第一篇随笔】keystone代码略读
武大信安在读,最近在自学Risc-v架构的可信执行环境. (实验报告多半是为了交差.临时起意写写博客,分享一些自己读代码的心得理解.) 本篇内容由队和我友总结而成,如有错误欢迎指正交流. keysto ...
- UVa OJ 455 Periodic Strings
Periodic Strings A character string is said to have period k if it can be formed by concatenating ...
- Jenkins 基础篇 - 任务分类
从前面的小节中我们看到在创建 Jenkins 任务的时候有好几种类型,如果你专门安装了 Maven 相关插件,可能还会有一个[构建一个 maven 项目]的任务类型,那这些任务类型究竟有何区别,以及我 ...
- [bug] SSM项目:Cannot load driver class: com.mysql.jdbc.Driver
检查pom文件,mysql包部分为: <dependency> <groupId>mysql</groupId> <artifactId>mysql-c ...
- head tail diff -c fff hhh 前5行 后5行 区别 动态显示文本最新信息: $tail -f crawler.log
显示文件第一行: $head -1 filename 显示文件倒数第五行: $tail -5 filename ]# tail -5 test.py option=sys.argv[1] main(o ...
- ipmitool使用手册
ipmitool使用手册原创xinqidian_xiao 最后发布于2018-07-05 12:15:47 阅读数 17948 收藏展开一.查找安装包 查看ipmitool属于哪个安装包 #yum p ...
- mysql基础之视图、事务、索引、外键
一.视图 视图是一个虚拟表,其内容由查询定义.同真实的表一样,视图包含一系列带有名称的列和行数据.但是,视图并不在数据库中以存储的数据值集形式存在.行和列数据来自由定义视图的查询所引用的表,并且在引用 ...