You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:20:50