首页 后端开发 C#.Net教程 C# GDI+编程(四)

C# GDI+编程(四)

Dec 17, 2016 am 10:11 AM

截屏
Grahpics类里的CopyFromScreen函数,可以把屏幕拷贝到Graphics对象里。如果Graphics对象是从窗口Form里创建的,那么屏幕就直接
显示在窗口里。看例子:给窗口添加一个按钮,然后给这个按钮添加单击事件处理函数。
函数里的代码如下:
private void button1_Click(object sender, EventArgs e)
 {
  this.CreateGraphics().CopyFromScreen(50,50, 0, 0, this.Size,CopyPixelOperation.SourceCopy);
 }
第一个参数和第二个参数,指明是从屏幕的哪里开始复制,而后面的0,0,就是把屏幕复制到窗口里了,从窗口哪里开始显示。
this.Size是要复制的大小(宽高)。

是VC++里的。这里只不过换了种说法而已。最终的结果还是一样的。

之前的Graphics对象创建,都是通过窗口的, 这次我们通过图片来创建Graphics对象,这样我们就可以在图片上进行绘制了。
而图片对象的创建,并不是只有加载文件这一个方式。我们可以创建一个“空”位图(通过构造函数),这种位图里面没有具体的数据,或者说里面的默认数据,没有用而已,我们只是需要这么个容器。在里面绘图,添加数据进去。


例子:截屏并把图片保存为文件
private void button1_Click(object sender, EventArgs e)
{
  //创建Bitmap图片,800宽,600高,这么个大小的容器。
 Bitmap bmp = new Bitmap(800, 600);
 //从图片里创建Grahpics对象
 Graphics gr = Graphics.FromImage(bmp);
 //拷贝屏幕到Bitmap
 gr.CopyFromScreen(0, 0, 0, 0, new Size(800, 600), CopyPixelOperation.SourceCopy);
 //保存为图片文件
 bmp.Save("d:\\screen.jpg");
}
怎么样,够简单的吧,四行代码就完成了屏幕截图,并保存为文件,VC++可是要很多行代码。另Bitmap是从Image类里派生出来的。

 

双缓冲一次性绘图
 直接看一个没有使用双缓冲的例子吧,鼠标在窗口内移动的时候,左上角的矩形就显示鼠标当前的位置
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.MouseMove += formMouseMove;
        }
        private void formMouseMove(object sender, MouseEventArgs e)
        {
            Graphics gr = this.CreateGraphics();
            Rectangle rect = new Rectangle(0, 0, 100, 35);
            //填充矩形
            LinearGradientBrush brush =
                new LinearGradientBrush(rect, Color.FromArgb(44, 55, 66), Color.FromArgb(123, 150, 189),
                LinearGradientMode.Horizontal);
            gr.FillRectangle(brush, rect);
            //画矩形
            Pen pen = new Pen(Color.Green, 2);
            gr.DrawRectangle(pen, rect);
            //显示文本
            gr.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            String str = String.Format("鼠标位置:\n{0},{1}", e.X, e.Y);
            gr.DrawString(str, new Font("黑体", 11),Brushes.White, rect);
        }
    }
可以看到,当鼠标移动的时候,左上角的矩形明显闪烁了,这是因为进行了三次绘制,填充矩形,画矩形,显示文本。才导致的。
当绘制的次数越多,这个闪烁就越明显。
而这三次绘制最终只要得到一个结果,也就是得到一张图片,那么我们就可以使用双缓冲来完成了,先把要绘制的图形绘制到Bitmap里面。然后再把Bitmap绘制到窗口就行了。
看例子:
        private void formMouseMove(object sender, MouseEventArgs e)
        {
            Graphics graphics = this.CreateGraphics();
            //从Bitmap里创建Graphics对象
            Bitmap bmp=new Bitmap(100,35);
            Graphics gr = Graphics.FromImage(bmp);
            Rectangle rect = new Rectangle(0, 0, 100, 35);
            //填充矩形
            LinearGradientBrush brush =
                new LinearGradientBrush(rect, Color.FromArgb(44, 55, 66), Color.FromArgb(123, 150, 189),
                LinearGradientMode.Horizontal);
            gr.FillRectangle(brush, rect);
            //画矩形
            Pen pen = new Pen(Color.Green, 2);
            gr.DrawRectangle(pen, rect);
            //显示文本
            gr.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            String str = String.Format("鼠标位置:\n{0},{1}", e.X, e.Y);
            gr.DrawString(str, new Font("黑体", 11),Brushes.White, rect);

            //一次性绘制
            graphics.DrawImage(bmp, 0, 0);
        }

获取窗口(控件)的Bitmap
DrawToBitmap函数,可以把窗口或控件的外观绘制到Bitmap里。它属于Control类,而窗口类和控件类都是从Control类派生出来的。
看例子:(一个按钮单击事件处理函数的代码)
private void button1_Click(object sender, EventArgs e)
{
 Bitmap bmp = new Bitmap(Width, Height);
 this.DrawToBitmap(bmp, new Rectangle(0, 0, Width, Height));
 bmp.Save("d:\\form.jpg");
}
DrawToBitmap的第二个参数,是窗口显示在Bitmap里的区域。这个是不能缩小或放大图片的,窗口的大小和Bitmap的大小是一致的,
如果填10,10,50,50那就是窗口的0,0,50,50显示在位图的10,10,50,50矩形区域内,窗口起始位置是不是能指定的,只能从位置0,0开始。

获取一个像素点的值
Bitmap类里GetPixel函数可以获取一个像素点的Color值,如果要获取窗口某一个像素点的颜色值,可以先调用DrawToBitmap函数,把
窗口保存成Bitmap。然后再获取。另:还有对应的函数SetPixel设置一个像素的颜色值。

获取Png图片显示区域,创建不规则窗口。
获取Png图片区域可以用GetPixel函数,获取图片里每一个像素点的颜色值,如果Alpha值为0的话,那就是透明的,否则把这个点加入区域。那么要如何获取一个Color对象的Alpah值呢,调用ToArgb成员函数,这个是32位整数,刚好可以存储4个8位字节的数值:A,R,G,B。
看下示例吧,把Alpha值提取出来
{
 Color cor1 = Color.FromArgb(123,225,229,230);
 //获取Color的argb值 
 int argb = cor2.ToArgb();
 //转换成字符数组
 byte[] bargb = BitConverter.GetBytes(argb);
 //bargb[3]存储的是Alpha值
 String str = String.Format("{0},{1},{2},{3}", bargb[0], bargb[1], bargb[2], bargb[3]);
 MessageBox.Show(str);
}
一个完整的示例,获取PNG显示区域

示例代码:       

public Form1()
        {
            InitializeComponent();
            //存储PNG非透明部分的路径
            GraphicsPath path = new GraphicsPath();
            //加载PNG图片
            Bitmap bmp = new Bitmap("d:\\Image\\win.png");
            //判断每个像素的颜色值,获取图片的显示区域
            for (int y = 0; y < bmp.Height; y++)
                for (int x = 0; x < bmp.Width; x++)
                {
                    Color cor = bmp.GetPixel(x, y);
                    int argb = cor.ToArgb();
                    byte[] bargb = BitConverter.GetBytes(argb);
                    //像素颜色值不是透明的
                    if (bargb[3] != 0)
                    {
                        //把这个像素点区域添加到路径里去
                        path.AddRectangle(new Rectangle(x, y, 1, 1));
                    }
                }
            //设置窗口显示区域,通过路径创建区域
            this.Region = new Region(path);
        }

但是这个方法有点不可靠,如果PNG图片里有些像素点的颜色值是半透明的,这样就得不到想要的外观结果。虽然看着PNG图片里有些地方好像是透明的。
解决方法就是自己来做PNG图片,按你自己的规则来。不要从网上找。

设置了不规则窗口,就可以把那张PNG图片绘制到窗口里去了,但由于半透明的问题,得先用透明画刷填充窗口,然后再绘制。

不过还有一个问题,非客户区窗口绘制,像我们之前的绘制,都是在窗口客户区里绘制的。

如果要绘制的图片和窗口对应起来的话,得从非客户区域开始绘制。这个要怎么做到呢。下一章再说吧。


更多C# GDI+编程(四)相关文章请关注PHP中文网!


本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

C语言各种符号的使用方法 C语言各种符号的使用方法 Apr 03, 2025 pm 04:48 PM

C 语言中符号的使用方法涵盖算术、赋值、条件、逻辑、位运算符等。算术运算符用于基本数学运算,赋值运算符用于赋值和加减乘除赋值,条件运算符用于根据条件执行不同操作,逻辑运算符用于逻辑操作,位运算符用于位级操作,特殊常量用于表示空指针、文件结束标记和非数字值。

char在C语言中如何处理特殊字符 char在C语言中如何处理特殊字符 Apr 03, 2025 pm 03:18 PM

C语言中通过转义序列处理特殊字符,如:\n表示换行符。\t表示制表符。使用转义序列或字符常量表示特殊字符,如char c = '\n'。注意,反斜杠需要转义两次。不同平台和编译器可能有不同的转义序列,请查阅文档。

char在C语言字符串中的作用是什么 char在C语言字符串中的作用是什么 Apr 03, 2025 pm 03:15 PM

在 C 语言中,char 类型在字符串中用于:1. 存储单个字符;2. 使用数组表示字符串并以 null 终止符结束;3. 通过字符串操作函数进行操作;4. 从键盘读取或输出字符串。

c#多线程和异步的区别 c#多线程和异步的区别 Apr 03, 2025 pm 02:57 PM

多线程和异步的区别在于,多线程同时执行多个线程,而异步在不阻塞当前线程的情况下执行操作。多线程用于计算密集型任务,而异步用于用户交互操作。多线程的优势是提高计算性能,异步的优势是不阻塞 UI 线程。选择多线程还是异步取决于任务性质:计算密集型任务使用多线程,与外部资源交互且需要保持 UI 响应的任务使用异步。

char数组在C语言中如何使用 char数组在C语言中如何使用 Apr 03, 2025 pm 03:24 PM

char 数组在 C 语言中存储字符序列,声明为 char array_name[size]。访问元素通过下标运算符,元素以空终止符 '\0' 结尾,用于表示字符串终点。C 语言提供多种字符串操作函数,如 strlen()、strcpy()、strcat() 和 strcmp()。

char与wchar_t在C语言中的区别 char与wchar_t在C语言中的区别 Apr 03, 2025 pm 03:09 PM

在 C 语言中,char 和 wchar_t 的主要区别在于字符编码:char 使用 ASCII 或扩展 ASCII,wchar_t 使用 Unicode;char 占用 1-2 个字节,wchar_t 占用 2-4 个字节;char 适用于英语文本,wchar_t 适用于多语言文本;char 广泛支持,wchar_t 依赖于编译器和操作系统是否支持 Unicode;char 的字符范围受限,wchar_t 的字符范围更大,并使用专门的函数进行算术运算。

char在C语言中如何进行类型转换 char在C语言中如何进行类型转换 Apr 03, 2025 pm 03:21 PM

在 C 语言中,char 类型转换可以通过:强制类型转换:使用强制类型转换符将一种类型的数据直接转换为另一种类型。自动类型转换:当一种类型的数据可以容纳另一种类型的值时,编译器自动进行转换。

C语言 sum 的作用是什么? C语言 sum 的作用是什么? Apr 03, 2025 pm 02:21 PM

C语言中没有内置求和函数,需自行编写。可通过遍历数组并累加元素实现求和:循环版本:使用for循环和数组长度计算求和。指针版本:使用指针指向数组元素,通过自增指针遍历高效求和。动态分配数组版本:动态分配数组并自行管理内存,确保释放已分配内存以防止内存泄漏。

See all articles