.NET正常运行的Bitmap椭圆绘制代码在Mono环境下失效求助
解决Mono 4.6.2环境下WinForms Bitmap圆形绘制异常问题
我之前在早期Mono版本上也碰到过类似的GDI+绘制兼容问题,结合你的场景(Raspbian 9 Stretch + Mono 4.6.2 + .NET 4.0 WinForms),大概率是Mono对GDI+的实现差异、屏幕尺寸获取偏差,或者旧版本的已知bug导致的。下面一步步帮你排查和解决:
可能的核心问题点
- Screen.Bounds的兼容性问题:早期Mono在Linux桌面环境下,
Screen.Bounds可能无法正确识别屏幕真实分辨率,或者返回的区域包含了系统UI(比如任务栏),导致生成的Bitmap尺寸不对。 - GDI+绘制逻辑差异:Mono依赖的
libgdiplus库在处理椭圆绘制时,对坐标计算、像素格式的支持和Windows原生GDI+有区别,比如非整数坐标、特定像素格式可能导致绘制失效。 - 旧版本Mono的bug:Mono 4.6.2是比较老旧的版本,存在不少GDI+相关的已知bug,比如
DrawEllipse/FillEllipse在某些场景下不渲染的问题。
具体解决方案
1. 验证并修正屏幕尺寸获取
首先确认Screen.Bounds返回的尺寸是否正确,在代码里添加打印逻辑:
var screen = Screen.PrimaryScreen; Console.WriteLine($"获取到的屏幕宽: {screen.Bounds.Width}, 高: {screen.Bounds.Height}");
如果输出和实际屏幕分辨率不符,可以替换成以下两种方式获取正确尺寸:
- 使用
SystemInformation.PrimaryMonitorSize:var screenSize = SystemInformation.PrimaryMonitorSize; int screenWidth = screenSize.Width; int screenHeight = screenSize.Height; - 手动指定分辨率(如果是固定设备的话,比如树莓派固定分辨率):
int screenWidth = 1920; // 根据你的屏幕实际分辨率修改 int screenHeight = 1080;
2. 修改绘制逻辑适配Mono
调整Bitmap创建和绘制代码,优先使用兼容性更好的API:
using System.Drawing; using System.Windows.Forms; public class FullScreenCircleGenerator { public static Bitmap GenerateCircles(int circleDiameter) { // 获取正确屏幕尺寸 var screen = Screen.PrimaryScreen; int screenWidth = screen.Bounds.Width; int screenHeight = screen.Bounds.Height; // 创建Bitmap时指定兼容的像素格式 using (Bitmap tempBmp = new Bitmap(screenWidth, screenHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { using (Graphics g = Graphics.FromImage(tempBmp)) { // 填充黑色背景 g.Clear(Color.Black); // 使用SolidBrush填充圆形(比DrawEllipse兼容性更好) using (SolidBrush whiteBrush = new SolidBrush(Color.White)) { // 计算每个圆形的矩形区域(确保坐标为整数) Rectangle topLeft = new Rectangle(0, 0, circleDiameter, circleDiameter); Rectangle topRight = new Rectangle(screenWidth - circleDiameter, 0, circleDiameter, circleDiameter); Rectangle bottomLeft = new Rectangle(0, screenHeight - circleDiameter, circleDiameter, circleDiameter); Rectangle bottomRight = new Rectangle(screenWidth - circleDiameter, screenHeight - circleDiameter, circleDiameter, circleDiameter); // 中心圆形:确保居中,避免整数除法偏移 int centerX = (screenWidth - circleDiameter) / 2; int centerY = (screenHeight - circleDiameter) / 2; Rectangle center = new Rectangle(centerX, centerY, circleDiameter, circleDiameter); // 绘制五个圆形 g.FillEllipse(whiteBrush, topLeft); g.FillEllipse(whiteBrush, topRight); g.FillEllipse(whiteBrush, bottomLeft); g.FillEllipse(whiteBrush, bottomRight); g.FillEllipse(whiteBrush, center); } // 返回Bitmap副本,避免using块释放原对象 return new Bitmap(tempBmp); } } } }
3. 升级依赖库和Mono版本(推荐)
Mono 4.6.2的GDI+兼容问题在后续版本中大量修复,建议:
- 更新
libgdiplus:在Raspbian终端执行:sudo apt-get update && sudo apt-get install --upgrade libgdiplus - 升级Mono到6.x版本(兼容.NET 4.0且修复了大量bug):可以参考Mono官方的Raspbian安装指南本地操作,替换源后安装最新稳定版。
4. 调试排查技巧
如果还是有问题,可以先跳过Bitmap生成,直接在Form的Paint事件中绘制,排除Bitmap创建的问题:
private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(Color.Black); using (SolidBrush brush = new SolidBrush(Color.White)) { // 绘制逻辑和上面一致 int diameter = 50; g.FillEllipse(brush, 0,0,diameter,diameter); // ...其他四个圆形 } }
如果Form上能正常显示,说明问题出在Bitmap的创建或保存环节,可以检查Bitmap的保存逻辑(如果有的话)是否正确。
内容的提问来源于stack exchange,提问作者K_Trenholm
相关产品推荐
相关产品推荐

