📜  如何制作 pc bsod C# (1)

📅  最后修改于: 2023-12-03 15:08:30.454000             🧑  作者: Mango

如何制作 PC BSOD C#

简介

BSOD(Blue Screen of Death)指的是Windows操作系统在遇到一些不可恢复的故障时,为了保护系统不被更严重的损坏而自动运行的一个蓝色屏幕。本文将介绍如何制作一个虚假的BSOD。

准备工作

我们需要先下载一个“~~美丽~~ ”的BSOD背景图片,以及制作BSOD所需的字体文件,可以在该链接中找到所需的素材。

准备好这些素材后,我们可以开始编写代码了。

编写代码

在C#中,我们可以使用Windows.Forms命名空间中的Form类来实现一个简单的窗体。在窗体的构造函数中,我们可以设置窗体样式、背景色和字体等属性,然后在窗体上绘制文字并显示窗体即可。

以下是示例代码:

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

// 导入GDI32.dll中的函数
internal static class UnsafeNativeMethods
{
    [DllImport("GDI32.dll")]
    internal static extern IntPtr CreateFontIndirect(ref IntPtr pLOGFONT);

    [DllImport("USER32.dll")]
    internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttribData data);
}

internal struct WindowCompositionAttribData
{
    public WindowCompositionAttribute Attribute;
    public IntPtr Data;
    public int SizeOfData;
}

internal enum WindowCompositionAttribute
{
    WCA_BLUR_BACKGROUND = 0x802,
}

public class BSOD : Form
{
    public BSOD()
    {
        this.FormBorderStyle = FormBorderStyle.None;
        this.WindowState = FormWindowState.Maximized;
        this.BackColor = Color.FromArgb(0, 0, 123);
        this.ForeColor = Color.FromArgb(0, 255, 255);

        IntPtr hFont = CreateFontIndirect(ref new IntPtr(7));
        this.Font = Font.FromHfont(hFont);

        this.Text = "A problem has been detected and windows has been shut down to prevent damage to your computer...";
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        var graphics = e.Graphics;

        graphics.DrawString("If this is the first time you've seen this stop error screen, ", this.Font, SystemBrushes.ControlText, 20, 60);
        graphics.DrawString("Restart your computer. If this screen appears again, follow these steps:", this.Font, SystemBrushes.ControlText, 20, 80);
        graphics.DrawString("Check to be sure you have adequate disk space.", this.Font, SystemBrushes.ControlText, 20, 110);
        graphics.DrawString("If a driver is identified in the stop message, disable the driver or check with the manufacturer for driver updates.", this.Font, SystemBrushes.ControlText, 20, 130);
        graphics.DrawString("Try changing video adapters.", this.Font, SystemBrushes.ControlText, 20, 150);
        graphics.DrawString("Check with your hardware vendor for any BIOS updates.", this.Font, SystemBrushes.ControlText, 20, 170);
        graphics.DrawString("Disable BIOS memory options such as caching or shadowing.", this.Font, SystemBrushes.ControlText, 20, 190);
        graphics.DrawString("If you need to use Safe Mode to remove or disable components, restart your computer.", this.Font, SystemBrushes.ControlText, 20, 210);
        graphics.DrawString("Press F8 to select Advanced Startup Options, and then select Safe Mode.", this.Font, SystemBrushes.ControlText, 20, 230);
        graphics.DrawString("Technical information:", this.Font, SystemBrushes.ControlText, 20, 260);

        var rect = new Rectangle(20, 290, this.Width - 40, this.Height - 330);
        var brush = new SolidBrush(Color.FromArgb(0xF0, 0xF0, 0xFF));
        graphics.FillRectangle(brush, rect);
        graphics.DrawRectangle(Pens.Black, rect);

        graphics.DrawString("**** STOP: 0x00000000 (0x00000000, 0x00000000, 0x00000000, 0x00000000)", this.Font, Brushes.Black, rect.X + 10, rect.Y + 10);
        graphics.DrawString("Some random text", this.Font, Brushes.Black, rect.X + 10, rect.Y + 30);
    }
    
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x00000020; // Turn on WS_EX_COMPOSITED
            return cp;
        }
    }

    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);

        var accent = new AccentPolicy { AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND };
        var accentStructSize = Marshal.SizeOf(accent);
        var accentPtr = Marshal.AllocHGlobal(accentStructSize);
        Marshal.StructureToPtr(accent, accentPtr, false);
        var data = new WindowCompositionAttribData
        {
            Attribute = WindowCompositionAttribute.WCA_BLUR_BACKGROUND,
            Data = accentPtr,
            SizeOfData = accentStructSize
        };
        SetWindowCompositionAttribute(this.Handle, ref data);
    }
}

internal enum AccentState
{
    ACCENT_DISABLED = 0,
    ACCENT_ENABLE_GRADIENT = 1,
    ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
    ACCENT_ENABLE_BLURBEHIND = 3,
    ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
    ACCENT_ENABLE_HOSTBACKDROP = 5,
    ACCENT_INVALID_STATE = 6
}

internal struct AccentPolicy
{
    public AccentState AccentState;
    public int AccentFlags;
    public int GradientColor;
    public int AnimationId;
}

代码中,我们创建了一个继承自Form的BSOD类。在构造函数中,我们设置窗体的一些属性,如样式、颜色、字体等。然后,在OnPaint事件中进行绘制。

需要注意的是,在OnPaint事件中,我们调用了graphics.DrawString方法来绘制文本。我们依次绘制了每一行文字,并使用graphics.FillRectangle方法绘制了一个矩形作为后面的提示文本区域。

在程序运行时,我们因为需要开启一个半透明窗口,所以在OnShown事件中,我们通过调用Windows系统库中的函数,实现了窗口半透明效果。

完整代码

完整的BSOD程序代码如下:

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

// 导入GDI32.dll中的函数
internal static class UnsafeNativeMethods
{
    [DllImport("GDI32.dll")]
    internal static extern IntPtr CreateFontIndirect(ref IntPtr pLOGFONT);

    [DllImport("USER32.dll")]
    internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttribData data);
}

internal struct WindowCompositionAttribData
{
    public WindowCompositionAttribute Attribute;
    public IntPtr Data;
    public int SizeOfData;
}

internal enum WindowCompositionAttribute
{
    WCA_BLUR_BACKGROUND = 0x802,
}

public class BSOD : Form
{
    public BSOD()
    {
        this.FormBorderStyle = FormBorderStyle.None;
        this.WindowState = FormWindowState.Maximized;
        this.BackColor = Color.FromArgb(0, 0, 123);
        this.ForeColor = Color.FromArgb(0, 255, 255);

        IntPtr hFont = CreateFontIndirect(ref new IntPtr(7));
        this.Font = Font.FromHfont(hFont);

        this.Text = "A problem has been detected and windows has been shut down to prevent damage to your computer...";
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        var graphics = e.Graphics;

        graphics.DrawString("If this is the first time you've seen this stop error screen, ", this.Font, SystemBrushes.ControlText, 20, 60);
        graphics.DrawString("Restart your computer. If this screen appears again, follow these steps:", this.Font, SystemBrushes.ControlText, 20, 80);
        graphics.DrawString("Check to be sure you have adequate disk space.", this.Font, SystemBrushes.ControlText, 20, 110);
        graphics.DrawString("If a driver is identified in the stop message, disable the driver or check with the manufacturer for driver updates.", this.Font, SystemBrushes.ControlText, 20, 130);
        graphics.DrawString("Try changing video adapters.", this.Font, SystemBrushes.ControlText, 20, 150);
        graphics.DrawString("Check with your hardware vendor for any BIOS updates.", this.Font, SystemBrushes.ControlText, 20, 170);
        graphics.DrawString("Disable BIOS memory options such as caching or shadowing.", this.Font, SystemBrushes.ControlText, 20, 190);
        graphics.DrawString("If you need to use Safe Mode to remove or disable components, restart your computer.", this.Font, SystemBrushes.ControlText, 20, 210);
        graphics.DrawString("Press F8 to select Advanced Startup Options, and then select Safe Mode.", this.Font, SystemBrushes.ControlText, 20, 230);
        graphics.DrawString("Technical information:", this.Font, SystemBrushes.ControlText, 20, 260);

        var rect = new Rectangle(20, 290, this.Width - 40, this.Height - 330);
        var brush = new SolidBrush(Color.FromArgb(0xF0, 0xF0, 0xFF));
        graphics.FillRectangle(brush, rect);
        graphics.DrawRectangle(Pens.Black, rect);

        graphics.DrawString("**** STOP: 0x00000000 (0x00000000, 0x00000000, 0x00000000, 0x00000000)", this.Font, Brushes.Black, rect.X + 10, rect.Y + 10);
        graphics.DrawString("Some random text", this.Font, Brushes.Black, rect.X + 10, rect.Y + 30);
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x00000020; // Turn on WS_EX_COMPOSITED
            return cp;
        }
    }

    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);

        var accent = new AccentPolicy { AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND };
        var accentStructSize = Marshal.SizeOf(accent);
        var accentPtr = Marshal.AllocHGlobal(accentStructSize);
        Marshal.StructureToPtr(accent, accentPtr, false);
        var data = new WindowCompositionAttribData
        {
            Attribute = WindowCompositionAttribute.WCA_BLUR_BACKGROUND,
            Data = accentPtr,
            SizeOfData = accentStructSize
        };
        SetWindowCompositionAttribute(this.Handle, ref data);
    }
}

internal enum AccentState
{
    ACCENT_DISABLED = 0,
    ACCENT_ENABLE_GRADIENT = 1,
    ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
    ACCENT_ENABLE_BLURBEHIND = 3,
    ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
    ACCENT_ENABLE_HOSTBACKDROP = 5,
    ACCENT_INVALID_STATE = 6
}

internal struct AccentPolicy
{
    public AccentState AccentState;
    public int AccentFlags;
    public int GradientColor;
    public int AnimationId;
}

public class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new BSOD());
    }
}
运行效果

最后,运行程序,我们可以看到如下效果:

BSOD效果图