基本信息
源码名称:C# 实现图片截取
源码大小:0.08M
文件格式:.zip
开发语言:C#
更新时间:2016-04-07
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
public partial class Form2 : Form
{
public Form2() {
InitializeComponent();
this.FormBorderStyle = FormBorderStyle.None;
this.Location = new Point(0, 0);
this.Size = new Size(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height);
pictureBox1.Dock = DockStyle.Fill;
this.TopMost = true;
toolStrip1.SendToBack();
}
~Form2() {//窗体关闭时卸载Hook
mHook.UnLoadMouseHook();
}
Bitmap screenBmp; //保存全屏的图像
bool isDrawed; //是否已经存在截图区域了
bool isDraw; //是否允许绘制(鼠标点下拖动)
IntPtr hWnd; //保存相应对象的句柄(最终获取窗体大小信息就用这个句柄)
int sx, sy; //鼠标点下时的鼠标坐标 Start X,Start Y;
int w, h; //鼠标拖动出来的区域的宽高(也就是要截图的宽高)
int x, y; //鼠标抬起是最终的矩形框左上角坐标(鼠标拖动绘制矩形 也就是要截图的左上角坐标)
MouseHook mHook = new MouseHook();//创建一个Hook
private void Form2_Load(object sender, EventArgs e) {
screenBmp = GetScreen(); //保存全屏画面
pictureBox1.Image = GetScreen(); //再次取得全屏画面(在上面填充半透明黑色)
using (Graphics g = Graphics.FromImage(pictureBox1.Image)) {
SolidBrush sb = new SolidBrush(Color.FromArgb(125, 0, 0, 0));
g.FillRectangle(sb, 0, 0, this.Width, this.Height);
sb.Dispose();
}
this.Enabled = false; //禁用此窗体(这样在查找的时候才能把当前窗体忽略)
mHook.HooKMouseEvent =new MouseHook.MEventhandler(mHook_HooKMouseEvent);
mHook.SetMouseHook(); //启用Hook
}
public Bitmap GetScreen() {//获得全屏图像
Bitmap bmp = new Bitmap(this.Width, this.Height);
using (Graphics g = Graphics.FromImage(bmp)) {
g.CopyFromScreen(0, 0, 0, 0, this.Size);
}
return bmp;
}
//绑定到Hook上面的事件
private void mHook_HooKMouseEvent(object sender,MouseInfoEventArys e) {
if (!isDrawed && !isDraw) //如果已经存在截图区域或者用户正在拖动那么就不用找寻了
FoundRect();
if (e.MBtn == Btn.LeftDowm) {//判断左键是否点下
if (isDrawed) //如果已经存在截图区域了那么久返回
return;
this.Enabled = true; //点下的时候恢复窗体的禁用
sx = MousePosition.X; //记录下当前鼠标位置以
sy = MousePosition.Y;
DrawRect("Normal"); //然后把当前区域绘制出来
isDrawed = true; //已经存在截图区域
isDraw = true; //只要左键还没有抬起允许拖动绘制自己的区域
} else if(e.MBtn == Btn.RightUp) {//如果右键抬起
if (isDrawed) { //判断是否已存在截图区域 已经存在就撤销
hWnd = IntPtr.Zero; //句柄清空 重新找寻
isDrawed = false; //没有截图区域
this.Enabled = false; //继续禁用窗体 (查找时忽略禁用的窗体)
toolStrip1.SendToBack();//工具栏隐藏起来(至于所有控件底部)
} else {
mHook.UnLoadMouseHook(); //退出之前 先卸载Hook
this.Enabled = true; //如果没有截图区域 那关闭窗体 先恢复窗体
new Thread(new ThreadStart(() => {
Thread.Sleep(100);//暂停100毫秒再关闭窗体 (让改窗体接受到鼠标右键抬起)
try {//好吧 我承认 这里我也不知道为什么 有时候提示改 不能再该句柄创建前调用Invoke(我很郁闷我的窗体不是创建了么)
this.Invoke(new MethodInvoker(() => {
this.Close();
}));
} catch {
this.Close();
}
})).Start();
}
}
}
public void FoundRect() {
//mhWnd找到的窗体的句柄main hWnd
IntPtr mhWnd = WinAPI.ChildWindowFromPointEx(
WinAPI.GetDesktopWindow(), //从桌面开始查找
new WinAPI.LPPOINT(MousePosition.X,MousePosition.Y), //鼠标当前坐标
WinAPI.CWP_SKIPDISABLED | WinAPI.CWP_SKIPINVISIBL);//忽略桌面上隐藏或者禁用的窗体
WinAPI.LPPOINT lp = new WinAPI.LPPOINT(MousePosition.X,MousePosition.Y); //注意这里的鼠标不是屏幕坐标 而是 窗体内部坐标
//fhWnd作为继续查找的标志 flag hWnd
IntPtr fhWnd = mhWnd;
IntPtr rhWnd = IntPtr.Zero;//rhWnd查找上来的句柄
bool isEnd = false;
while (!isEnd) {//循环的去找寻在窗体上当前坐标最内层的控件
WinAPI.ScreenToClient(fhWnd, out lp);//循环一次 转化一下(查找是用内部坐标)
rhWnd = WinAPI.ChildWindowFromPointEx(fhWnd, new WinAPI.LPPOINT(lp.x, lp.y), WinAPI.CWP_All);
if (rhWnd == IntPtr.Zero || rhWnd == fhWnd) {//如果循环是没有找到或找到的与上一个句柄一样那么就结束
rhWnd = fhWnd; //结束前赋值为上一次找到的句柄
isEnd = true;
} else {
fhWnd = rhWnd;//否则根据找到的句柄的作为标志句柄再在其内部继续找寻
}
}
if (hWnd == rhWnd) //如果找到的句柄 和上一次绘制是用的句柄一样 那么 就直接返回
return;
hWnd = rhWnd; //把查找上来的句柄 赋值 给最终要是用的句柄
DrawRect("Normal"); //然后在这个新的句柄外面绘制一圈
}
public void DrawRect(string type) {//绘制区域
using (Graphics g = pictureBox1.CreateGraphics()) //建立画布
using (Pen p = new Pen(Color.FromArgb(255, 24, 219, 255), 4)) {//画笔
pictureBox1.Refresh(); //绘制前先清空画布
switch (type) {
case "Normal"://绘制找到的区域
WinAPI.LPRECT rect = new WinAPI.LPRECT();
WinAPI.GetWindowRect(hWnd, out rect);
x = rect.left;y = rect.top;
w = rect.right - rect.left;h = rect.bottom - rect.top;
g.DrawRectangle(p, x, y, w, h);
Rectangle drawRect = new Rectangle(x, y, w, h);
g.DrawImage(screenBmp, drawRect, drawRect, GraphicsUnit.Pixel);
break;
case "Rectangle"://鼠标点下并且拖动的时候 绘制矩形(也就是自定义区域 - 现在鼠标处于拖动状态)
p.Width = 1;
w = Math.Abs(MousePosition.X - sx);//注意当前鼠标于鼠标点下时的坐标的差值的绝对值
h = Math.Abs(MousePosition.Y - sy);
if (MousePosition.X < sx) { //如果x轴是负数那么图像x轴的其实坐标用当前鼠标的x
x = MousePosition.X;
} else { //否则就用鼠标点下是的坐标
x = sx;
}
if (MousePosition.Y < sy) {
y = MousePosition.Y;
} else {
y = sy;
}
g.DrawRectangle(p, x, y, w, h);//s,y矩形框左上角,w,h矩形框宽高 也就是图像的大小
break;
case "MouseUp"://鼠标抬起的时候 把相应区域的图片也画上去(正常的不是黑色的图)
//为什么要加一个像素?为了精确 你的屏幕宽1440你鼠标放到右边坐标是1339 多想想就明白了
//鼠标在第一像素时x为0 在第二个像素时x为1
Rectangle imgRect = new Rectangle(x, y, w 1, h 1);
g.DrawRectangle(p, x, y, w 1, h 1);
g.DrawImage(screenBmp, imgRect, imgRect, GraphicsUnit.Pixel);
break;
}
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e) {
//判断鼠标是否点下 如果点下没有松开 那么移动的时候就绘制区域
if (isDraw) {
//因为窗体在恢复禁用的时候就会马上出发Move事件 所以判断一下 如果鼠标在点下的时候 位置没用动那么什么都不做
if (sx == MousePosition.X && sy == MousePosition.Y) {
return;
}
isDrawed = false;
//前面去看 鼠标默认才点下的时候isDrawed = true;isDraw = true如果鼠标不移动就抬起
//那么就以找到的区域作为截图区域 如果点下的时候鼠标没有抬起移动的话 那么isDrawed = false取消默认找到的区域
//直到鼠标抬起才确认为 isDrawed = true表示 截图区已经存在
DrawRect("Rectangle");//注意 这个是自己拖动出来的区域 如果你是从右向左拖动 那么宽度的差值是负数
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e) {
isDraw = false; //进制鼠标move事件里面的代码
SetToolStripLocation(); //既然鼠标抬起 那么就说用户确认好了截图区 那么设置工具条的位置
toolStrip1.BringToFront(); //显示工具条
//因为第一次点下鼠标 默认是 绘制自动框选的区域 所以 坐标没有变的话 什么都不做
if (sx == MousePosition.X && sy == MousePosition.Y || isDrawed) {
return;
}
DrawRect("MouseUp");
isDrawed = true;
}
//设置工具条的位置
public void SetToolStripLocation() {
toolStrip1.Left = x 10;
if (y h 20 toolStrip1.Height <= Screen.PrimaryScreen.Bounds.Height) {
toolStrip1.Top = y h 10;
} else if (toolStrip1.Height 20 <= y) {
toolStrip1.Top = y - 10 - toolStrip1.Height;
} else {
toolStrip1.Top = y 10;
}
if (toolStrip1.Right >= Screen.PrimaryScreen.Bounds.Width - 10)
toolStrip1.Left = Screen.PrimaryScreen.Bounds.Width - 10 - toolStrip1.Width;
}
//双击就把截图区域的内容复制到剪贴板
private void pictureBox1_DoubleClick(object sender, EventArgs e) {
Clipboard.SetImage(GetSaveBmp());
this.Close();
}
//工具条上面的 复制到剪贴板
private void tool_Clipboard_Click(object sender, EventArgs e) {
pictureBox1_DoubleClick(null, null);
}
//工具条上面的 退出
private void tool_Exit_Click(object sender, EventArgs e) {
this.Close();
}
//工具条上面的 撤销
private void tool_Cancel_Click(object sender, EventArgs e) {
mHook_HooKMouseEvent(null, new MouseInfoEventArys(Btn.RightUp, 0, 0));
}
//工具条上面的 保存
private void tool_Save_Click(object sender, EventArgs e) {
SaveFileDialog saveFile = new SaveFileDialog();
saveFile.Filter = "JPEG文件|*.jpg;*.jpeg|BMP文件|*.bmp";
saveFile.FileName = "SL截图" GetTimeStr(); //设置默认的文件名
if (DialogResult.OK == saveFile.ShowDialog()) {
switch (saveFile.FilterIndex) {
case 1:
GetSaveBmp().Save(saveFile.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
break;
case 2:
GetSaveBmp().Save(saveFile.FileName, System.Drawing.Imaging.ImageFormat.Bmp);
break;
}
this.Close();
}
}
//保存的时候默认文件名取时间
public String GetTimeStr(){
DateTime time = DateTime.Now;
return time.Year "-" time.Month "-" time.Day "_"
time.Hour time.Minute time.Second;
}
//获得最终要保存的图像内容
public Bitmap GetSaveBmp() {
Bitmap bmp = new Bitmap(w, h);
using (Graphics g = Graphics.FromImage(bmp)) {
Rectangle srcRect = new Rectangle(x, y, w 1, h 1);
Rectangle destRect = new Rectangle(0, 0, w 1, h 1);
g.DrawImage(screenBmp, destRect, srcRect, GraphicsUnit.Pixel);
}
return bmp;
}
}