本次屏笔的实现采用隐藏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;
}
}
效果图如下: