C# 绘制屏幕水印

1. 基本思路

在一个窗口上的PictureBox上绘制,并动态的计算PictureBox的个数,并设置主窗口置顶显示等样式。基本思路就是酱紫了,上代码!!!

2. 实现

代码是只放了核心部分,想要完整项目的同学可以关注公众号CoderPro回复 C# WaterMarker

// 主窗口代码
public MainForm()
{
    InitializeComponent();
    // 不在任务栏中显示
    this.ShowInTaskbar = false;
    // 设置窗口为最小化
    this.WindowState = FormWindowState.Minimized;
    // 获取当前登录用户名
    currentUser = System.Environment.GetEnvironmentVariable("USERNAME");
}

private void CheckScreen()
{
    if (_screenNum == Screen.AllScreens.Length)
        return;
    if (Screen.AllScreens.Length >= 1)
    {
        // 屏幕数目发生变化
        if (_screenNum != Screen.AllScreens.Length)
        {
            // 移除之前的水印窗口
            for (int iIndex = _watermarkWinList.Count - 1; iIndex >= 0; iIndex--)
            {
                _watermarkWinList[iIndex].Dispose();
                _watermarkWinList.RemoveAt(iIndex);
            }
            _screenNum = Screen.AllScreens.Length;
        }
        // 设置显示内容
        SetShowContent();
    }
}
private void SetShowContent()
{
	// 遍历所有屏幕
	foreach (Screen sc in Screen.AllScreens)
	{
	    // 创建水印窗口
	    WaterMarkWin watermarkWin = new WaterMarkWin(sc, currentUser);
	    // 显示水印窗口
	    watermarkWin.Show();
	    _watermarkWinList.Add(watermarkWin);
	}
}

// 水印窗口代码
public WaterMarkWin(Screen sc, string UserName)
{
	_sc = sc;
	_userName = UserName;
	InitializeComponent();
	
	// 最顶层现实窗口
	this.TopMost = true;
	// 窗口不再任务栏中显示
	this.ShowInTaskbar = false;
	// 设置透明区域颜色
	this.TransparencyKey = Color.Lime;
	// 设置窗口的边框样式
	this.FormBorderStyle = FormBorderStyle.None;
	// 设置窗口最大化
	this.WindowState = FormWindowState.Maximized;
	// 设置窗口背景色
	this.BackColor = Color.Lime;
	// 设置水印
	CreateWatermark();
}

private void CreateWatermark()
{
    // 清除所有水印
    pictureBox1.Controls.Clear();
    // 水印内容
    string watermarkContent = Environment.MachineName + " " + System.Environment.UserDomainName;
    // 创建水印图片
    Image img = CreateImage(watermarkContent, 11);
    // 工作区域宽度
    int maxWidth = _sc.WorkingArea.Width;
    int maxHeight = _sc.WorkingArea.Height;
    // 可以绘制的列数
    int cols = maxWidth / img.Width;
    // 可以位置的行数
    int rows = maxHeight / img.Height;

    for (int col = 0; col <= cols; col++)
    {
        for (int row = 0; row <= rows; row++)
        {
            // 创建图片对象
            PictureBox pic = new PictureBox();
            // 要绘制的图片
            pic.Image = img;
            // 图片宽度
            pic.Width = img.Width;
            // 图片高度
            pic.Height = img.Height;
            // 图片显示的位置
            pic.Left = col * pic.Width;
            pic.Top = row * pic.Height;

            pictureBox1.Controls.Add(pic);
        }
    }
    // 主动回收内存
    GC.Collect();
}
/// <summary>
/// 生成文字图片
/// </summary>
/// <param name="text"></param>
/// <param name="isBold"></param>
/// <param name="fontSize"></param>
public Image CreateImage(string text, int fontSize)
{
	// 宽度
	int width = 40;
	// 高度
	int height = 20;
	// 字体
	Font font = new Font("微软雅黑", fontSize, FontStyle.Bold);
	
	// 定义单色画笔
	SolidBrush brush = new SolidBrush(Color.Gray);
	// 设置显示字符串格式
	StringFormat format = new StringFormat(StringFormatFlags.NoClip);
	// 字符串水平对齐方式
	format.Alignment = StringAlignment.Center;
	// 字符串垂直对齐方式
	format.LineAlignment = StringAlignment.Center;
	// 创建Graphics对象
	Graphics grph = Graphics.FromImage(new Bitmap(1, 1));
	// 解决绘制闪烁
	grph.Clear(this.BackColor);
	// 测量出字体的宽高
	SizeF sf = grph.MeasureString(text, font);
	width = Convert.ToInt32(sf.Width);
	height = Convert.ToInt32(sf.Height);
	int bitmapWidth = height > width ? height : width;
	// 创建位图对象(此处按照最大的宽或高进行设置,是为防止在进行字符串旋转后,字符串显示区域不够)
	Bitmap image = new Bitmap(bitmapWidth, bitmapWidth);
	// 根据实际的位图对象创建 
	grph = Graphics.FromImage(image);
	// 将绘制原点偏移到(0,width),不进行偏移,则以(0,0)点作为绘制原点
	grph.TranslateTransform(0, width);
	// 旋转绘制的图形以(0,width)为圆心
	grph.RotateTransform(-45);
	// 指定文本的呈现模式
	/* 
	* ClearType: 由美国微软公司在其Windows操作系统中提供的荧幕字体平滑工具,让Windows字体更加漂亮。ClearType主要是针对LCD 液晶 显示器设计,
	* 可提高文字的清晰度。基本原理是,将显示器的R, G, B各个次像素也发光,让其色调进行微妙调整,可以达到实际分辨率以上(横方向分辨率的三倍)
	* 的纤细文字的显示效果
	*/
	grph.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
	// 用于渲染抗锯齿和 ClearType 文本的伽马校正值(32是随便写的)
	// grph.TextContrast = 32;
	// 指定直线、 曲线和已填充区域的边缘是否使用平滑处理(也称为抗锯齿).当是路径渐变画笔不遵守平滑模式
	// grph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
	// InterpolationMode的指决定了如何计算两点之间的插补值
	// grph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
	// 指定如何将合成图像绘制到此 Graphics。复合模式确定从源映像的像素是覆盖(SourceCopy)还是组合(SourceOver, 需要使用半透明、混合叠加效果时使用)使用背景像素。默认值为 SourceOver。
	// grph.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
	// 设置绘制到此 Graphics 的合成图像的呈现质量
	// grph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
	
	// 实际要绘制的区域的大小
	RectangleF rect = new RectangleF(0, 0, width, height);
	// 绘制字符串
	grph.DrawString(text, font, brush, rect, format);
	// 释放对象
	grph.Dispose();
	// 返回绘制好的image对象
	return image;
}

3. 问题及注意点

3.1 绘图闪烁

在绘制水印的一瞬会有屏幕的闪烁,原因是因为窗口的背景色问题,
所以在绘制的时候将grph的背景设置为与窗口背景一样的颜色即
可"grph.Clear(this.BackColor);"

3.2 任务栏显示预览窗口遮挡问题

  1. 描述:当任务栏的程序在允许时鼠标放到图标上就会出现预览窗口,之后将鼠标移动到预览窗口上,这个窗口就会被指定显示,并且遮挡住水印,环境是Win10。
  2. 解决(方法比较另类,如果哪位大神有更好的办法请留言指教谢谢!)
    1. 思路:鼠标放上去让它长时间不显示
    2. \HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced下面增加"ExtendedUIHoverTime"(DWORD32类型)这个是用来设置鼠标在任务栏图标上多久后显示预览窗口的
    3. \HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband下面增加"NumThumbnails"(DWORD32类型)可以让预览窗口以列表形式显示,但是当鼠标放到列表的某一项时还会显示预览窗口,而且当应用只打开一个的时候默认还是以预览窗口显示。🤣

关注「CoderPro」公众号,专注于分享.NET/C++知识及算法的大本营,新手公众号请大家多多关照/(ㄒoㄒ)/~~
在这里插入图片描述

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值