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太过国际化,在国内水土不服,无法满足我的一些需求. 比如实 ...
随机推荐
- Windows核心编程 第八章 用户方式中线程的同步(上)
第8章 用户方式中线程的同步 当所有的线程在互相之间不需要进行通信的情况下就能够顺利地运行时, M i c r o s o f t Wi n d o w s的运行性能最好.但是,线程很少能够在所有的时 ...
- CTF密码学常见加解密总结
CTF密码学常见加解密总结 2018年03月10日 19:35:06 adversity` 本文链接:https://blog.csdn.net/qq_40836553/article/details ...
- 冒泡排序——Python实现
冒泡排序Python实现 # -*- coding: utf-8 -*- # @Time : 2019/10/28 19:41 # @Author : yuzhou_1shu # @Email : y ...
- 初学Golang的笔记
Note 一个module是一个go package的集合,该module用于发布的一个单位. 一般一个go repo仅仅包含一个module,含有一个go.mod文件 每个module路径不仅仅用于 ...
- Day009 稀疏数组
稀疏数组(数据结构) 场景 需求:编写五子棋游戏中,有存盘和续上盘的功能. 分析问题:因为该二维数组的很多值默认都是0,因此记录了很多没有意义的数据. 解决:稀疏数组 稀疏数组介绍 当一个数组大部分元 ...
- ES常用查询语法
1.query string search GET /index/type/_search?q=name:zhangsan&sort=age:desc 2.query DSL(Domain S ...
- 使用TK框架中 insert与insertSelective区别
insertSelective会对字段进行判断再更新(如果为Null就忽略更新),如果你只想插入某些字段,可以用这个方法. insert对你注入的字段全部插入
- SE_Work3_结队项目
项目 内容 课程:北航-2020-春-软件工程 博客园班级博客 要求:求交点个数 结对项目作业 班级:005 Sample GitHub地址 intersect 北航网盘地址 SE结队项目 1. PS ...
- CRM系统有哪几种常见类型?
随着市场的快速变化,客户开始变得越来越重要,因此CRM客户管理系统开始逐渐被企业所认可.从CRM系统进入中国市场到现在十余年的发展中,越来越多的CRM厂商开始出现.为了满足不同行业.不同类型的企业的需 ...
- JAVA基础——包机制
包机制 包的语法格式package pkg1[.pkg2[.pkg3...]] 一般利用 公司域名倒置 作为包名; 例如www.baidu.com,则建立报的名字com.baidu.www 一般不要让 ...