GDI+屏笔 桌面画图(二)

本次屏笔的实现采用隐藏Form的方式实现,ALT+Q激活屏笔,再次点击取消。

激活屏笔时,先cpoy屏幕内容到bitmap,然后将其显示到picturebox,之后最大化Form,然后再用Graphics记录鼠标轨迹画图。

使用钩子捕捉键盘和鼠标全局事件。全局键盘鼠标钩子请参考http://blog.csdn.net/q317379184/article/details/47979309

使用方法:Alt+q 启动,再次点击取消。鼠标右键保存图片到剪切板。

功能实现类如下:

    /* 可以成为你讲课的辅助工具
     * 让学员更好了解到课程中学习重点
     * 让讲师上课更加轻松,质量更完美
     * 点击“Alt + Q” 电脑屏幕画图,再次点击“Alt + Q”取消屏幕画图,鼠标右键保存当前画图到剪切板。
     * 适合网络教学
     */
    class NewDeskTopDraw
    {

        /// <summary>
        /// 委托
        /// </summary>
        public delegate void pictureBox_Invoke(Bitmap bt);

        public event pictureBox_Invoke pictureBox_Invoker;
        /// <summary>
        /// 调用者的form容器
        /// </summary>
        static Form form;
        private static NewDeskTopDraw dtd = null;
        private static readonly object locker = new object();
        /// <summary>
        /// 是否开始绘制
        /// </summary>
        bool isDraw = false;
        /// <summary>
        /// 屏笔的原始图像
        /// </summary>
        Bitmap bt;
        /// <summary>
        /// 画笔
        /// </summary>
        public Pen p = new Pen(Brushes.Red, 5);
        /// <summary>
        /// 起始点
        /// </summary>
        Point start = new Point();
        /// <summary>
        /// 结束点
        /// </summary>
        Point end = new Point();
        /// <summary>
        /// 鼠标钩子
        /// </summary>
        MouseHook mouseHook = new MouseHook();
        /// <summary>
        /// 键盘钩子
        /// </summary>
        KeyboardHook keyboardHool = new KeyboardHook();
        /// <summary>
        /// 是否启动屏笔
        /// </summary>
        bool isStart = false;

        /// <summary>
        /// 该函数检索一指定窗口的客户区域或整个屏幕的显示设备上下文环境的句柄,
        /// 以后可以在GDI函数中使用该句柄来在设备上下文环境中绘图。
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        [DllImport("User32.dll")]
        private extern static IntPtr GetDC(System.IntPtr hWnd);
        /// <summary>
        /// 单例模式
        /// </summary>
        /// <param name="_form"></param>
        /// <returns></returns>
        public static NewDeskTopDraw GetInstance(Form _form)
        {
            lock (locker)
            {
                if (dtd == null)
                    dtd = new NewDeskTopDraw(_form);
            }
            return dtd;
        }

        /// <summary>
        /// 获取屏幕截图
        /// </summary>
        /// <returns></returns>
        Bitmap GetScreen()
        {
            Bitmap bt = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            using (Graphics g = Graphics.FromImage(bt))
            {
                g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size);
            }
            return bt;
        }

        /// 设置图片的透明度
        /// </summary>
        /// <param name="image">原图</param>
        /// <param name="alpha">透明度0-255</param>
        /// <returns></returns>
        private Bitmap SetPictureAlpha(Image image, int alpha)
        {
            //颜色矩阵
            float[][] matrixItems =
           {
               new float[]{1,0,0,0,0},
               new float[]{0,1,0,0,0},
               new float[]{0,0,1,0,0},
               new float[]{0,0,0,alpha/255f,0},
               new float[]{0,0,0,0,1}
           };
            ColorMatrix colorMatrix = new ColorMatrix(matrixItems);
            ImageAttributes imageAtt = new ImageAttributes();
            imageAtt.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            Bitmap bmp = new Bitmap(image.Width, image.Height);
            Graphics g = Graphics.FromImage(bmp);
            g.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height),
                    0, 0, image.Width, image.Height, GraphicsUnit.Pixel, imageAtt);
            g.Dispose();
            return bmp;
        }

        /// <summary>
        /// 默认构造函数
        /// </summary>
        private NewDeskTopDraw(Form _form)
        {
            form = _form;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <returns></returns>
        public bool Init()
        {
            //设置笔的属性,避免出现“毛刺”
            p.StartCap = LineCap.Round;
            p.EndCap = LineCap.Round;
            p.LineJoin = LineJoin.Round;
            //捕获全局鼠标键盘事件
            mouseHook.MouseMove += new MouseEventHandler(mouseHook_MouseMove);
            mouseHook.MouseDown += new MouseEventHandler(mouseHook_MouseDown);
            mouseHook.MouseUp += new MouseEventHandler(mouseHook_MouseUp);
            keyboardHool.KeyDown += new KeyEventHandler(keyboardHool_KeyDown);
            mouseHook.Start();
            keyboardHool.Start();
            return mouseHook.IsStarted;
        }
        /// <summary>
        /// KeyDown事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void keyboardHool_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Alt && e.KeyCode == Keys.Q)
            {

                isStart = !isStart;
                if (!isStart)//启动未屏笔
                {
                    form.TopMost = false;
                    isDraw = false;
                    form.Refresh();
                    form.WindowState = FormWindowState.Minimized;
                    bt = GetScreen();
                    pictureBox_Invoker.Invoke(bt);
                }
                else//启动屏笔
                {
                    form.WindowState = FormWindowState.Maximized;
                    form.TopMost = true;
                    form.Activate();
                    form.BringToFront();
                    bt = GetScreen();
                    pictureBox_Invoker.Invoke(bt);
                }
            }
        }
        /// <summary>
        /// MouseDown事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mouseHook_MouseDown(object sender, MouseEventArgs e)
        {
            if (isStart)//ALT+Q
            {

                if (e.Button == MouseButtons.Left)
                {
                    form.WindowState = FormWindowState.Maximized;
                    form.TopMost = true;
                    form.Activate();
                    form.BringToFront();
                    form.Refresh();
                    start = e.Location;//记录开始位置
                    //鼠标左键点下 则开始绘制
                    isDraw = true;
                }
                else
                    if (e.Button == MouseButtons.Right)
                    {
                        Clipboard.SetDataObject(bt);//发送数据到剪切板

                        //test
                        //form.TopMost = false;
                        //isDraw = false;
                        //form.Refresh();
                        //form.WindowState = FormWindowState.Minimized;
                        //bt = GetScreen();
                        //get.Invoke(bt);
                    }
            }
        }
        /// <summary>
        /// MouseMove事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mouseHook_MouseMove(object sender, MouseEventArgs e)
        {
            if (isStart)
            {
                if (isDraw)
                {
                    end = e.Location;//记录结束位置
                    Graphics g = System.Drawing.Graphics.FromImage(bt);//创建画板
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    g.DrawLine(p, start, end);//画线
                    start = end;//将结束位置再次作为开始位置
                    g.Dispose();
                    pictureBox_Invoker.Invoke(bt);
                }
            }
        }
        /// <summary>
        /// MouseUp事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mouseHook_MouseUp(object sender, MouseEventArgs e)
        {
            if (isStart)
            {
                if (e.Button == MouseButtons.Left)
                {
                    isDraw = false;
                }
            }
        }

        /// <summary>
        /// 反初始化
        /// </summary>
        public void Uinit()
        {
            mouseHook.Stop();
        }

    }

form调用代码如下:

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.BackColor = Color.White;
            this.TransparencyKey = Color.White;
            this.FormBorderStyle = FormBorderStyle.None;
            this.WindowState = FormWindowState.Maximized;
            NewDeskTopDraw ntd = NewDeskTopDraw.GetInstance(this);
            ntd.pictureBox_Invoker += new NewDeskTopDraw.pictureBox_Invoke(ntd_pictureBox_Invoker);
            ntd.Init();
        }

        void ntd_pictureBox_Invoker(Bitmap bt)
        {
            pictureBox1.Image = bt;
        }
    }

效果图如下:

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 16:06:36

GDI+屏笔 桌面画图(二)的相关文章

C#GDI+编程基础(二)

pen类:绘制指定宽度和样式的直线.使用DashStyle属性绘制几种虚线,可以使用各种填充样式(包括纯色和纹理)来填充Pen绘制的直线,填充模式取决于画笔或用作填充对象的纹理. 创建画笔: //用指定的颜色实例化一只画笔的方法如下: public Pen(Color); //用指定的画刷实例化一只画笔的方法如下: public Pen(Brush); //用指定的画刷和宽度实例化一只画笔的方法如下: public Pen(Brush , float); //用指定的颜色和宽度实例化一只画笔的方

烂泥:学习ubuntu远程桌面(二):远程桌面会话管理

本文首发于烂泥行天下 在上一篇文章中,我们讲解了如何给ubuntu安装远程桌面及其配置,这篇文章我们再来讲解下有关ubuntu远程桌面会话的问题. 一.问题描述 在我们使用ubuntu远程桌面时,会经常遇到这样的问题.在连接远程桌面时,我打开的是会话A,我在会话A下处理一些工作的事情.由于自己不小心把这个远程桌面给关闭了,或者今天工作完毕关闭该远程桌面会话.等再进行连接远程桌面时,发现ubuntu会给出一个新的远程桌面会话B,而不是我们刚刚连接过的那个会话A,或者是昨天连接的那个会话A. 以上这

Delphi以GDI+制作桌面歌词效果

在Windows XP下效果图: 在Windows 7下有焦点时效果图: 在Windows 7下无焦点时效果图: 在Windows 7下右键菜单效果图: 很多音频播放软件都带有桌面歌词效果,在桌面上显示歌词字幕,可以设置是否置顶桌面,是否背景穿透等等.要实现这样的效果方法有很多种,利用GDI+的特性来实现桌面歌词效果,可以达到歌词字幕的平滑柔和.在参考了CodeProject的一篇文章,文章标题<To Create A COOL Desktop Lyrics Demo >链接地址:http:/

go语言使用go-sciter创建桌面应用(二) ui元素查找,增加,删除,修改

我们可以通过go-sciter给我们提供的方法,方便的对html,css编写的UI界面进行增删改查. demo3.go代码如下: package main; import ( "github.com/sciter-sdk/go-sciter" "github.com/sciter-sdk/go-sciter/window" "log" "fmt" ) //一些基础操作 func base(root *sciter.Elemen

使用Raphael 画图(二) 扩展的图形 (javascript)

看这文章前,建议先看第一编文章<使用Raphael 画图(一) 基本图形 (javascript)>. 在Raphael基础上扩展的图形: 要运行该例子要引入附件的2个js包.(g.raphael.rar) <script type="text/javascript" src="raphael.js" charset="utf-8"></script> <script type="text/ja

Citrix XenDesktop发布Centos 7.2桌面(二)--安装Centos7

一.   安装CentosLinux 7.2 1.新建VM,模板选择"Centos 7" 2.挂载ISO镜像后,启动VM,选择"Install CentOS 7" 3.根据自身需要,选择相应语言.本次为方便演示,选择"中文".点击"继续". 4.选择相应的"时区.键盘及语言",安全策略选择默认即可,软件选择"GNOME桌面"并勾选"X Windows"(其他组件根据各

CSS3(二)Box Model、边距折叠、内联与块标签、CSSReset

目录 一.盒子模型(Box Model) 1.1.宽度测试 1.2.溢出测试 1.3.box-sizing属性 1.4.利用CSS画图 二.边距折叠 2.1.概要 2.2.垂直方向外边距合并计算 三.内联与块级标签 3.1.行内标签与块标签区别 3.2.隐藏 3.3.行内块标签 3.4.菜单示例 四.重置浏览器默认样式 4.1.CSSReset 4.1.1.MT css reset 4.1.2.PC css reset 4.1.3.PPTV css reset 4.1.4 YUI css res

Linux远程桌面(三)

上一篇中的vnc配置已经很方便了,这一篇介绍更为简单的xmanager的配置,xmanager画面好一丢丢. Xmanager服务器配置             Linux远程桌面(二):vnc之xinetd服务搭建配置 主要修改以下两个文件(在root权限下): (1)/usr/share/gdm/defaults.conf                 //GNOME管理默认的配置文件,也可编辑/etc/gdm/custom.conf, 启用xdmcp (2)/etc/inittab  

Matlab画图-非常具体,非常全面

Matlab画图 强大的画图功能是Matlab的特点之中的一个,Matlab提供了一系列的画图函数,用户不须要过多的考虑画图的细节,仅仅须要给出一些基本參数就能得到所需图形,这类函数称为高层画图函数.此外,Matlab还提供了直接对图形句柄进行操作的低层画图操作.这类操作将图形的每一个图形元素(如坐标轴.曲线.文字等)看做一个独立的对象,系统给每一个对象分配一个句柄,能够通过句柄对该图形元素进行操作,而不影响其它部分. 本章介绍绘制二维和三维图形的高层画图函数以及其它图形控制函数的用法,在此基础