C#實(shí)現(xiàn)截圖工具小項(xiàng)目
本文實(shí)例為大家分享了C#實(shí)現(xiàn)截圖工具小項(xiàng)目的具體代碼,供大家參考,具體內(nèi)容如下
1.起因
一直用的截圖是qq的截圖,所以想要實(shí)現(xiàn)一個(gè)簡單點(diǎn)的截圖,為了方便。
2.思路
講一下實(shí)現(xiàn)流程。
1、主窗體,上有截圖按鈕,點(diǎn)擊進(jìn)入截圖窗體
2、在截圖窗體中,背景設(shè)置為全屏幕的截圖圖片,無邊框,窗體最大化,這時(shí)你看到的就是一張屏幕圖,其實(shí)是一個(gè)窗體,然后我們將在這個(gè)窗體中截取圖片,其實(shí)主要就是畫板Graphics的使用,截取完之后圖片將保存到剪切板。
3.代碼
熱鍵注冊類 HotKey.cs
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace test {
/// <summary>
/// 熱鍵類
/// </summary>
public class HotKey {
/// <summary>
/// 如果函數(shù)執(zhí)行成功,返回值不為0,如果執(zhí)行失敗,返回值為0
/// </summary>
/// <returns></returns>
[DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(
IntPtr hWnd, // 窗口的句柄, 當(dāng)熱鍵按下時(shí),會(huì)產(chǎn)生WM_HOTKEY信息,該信息該會(huì)發(fā)送該窗口句柄
int id, // 定義熱鍵ID,屬于唯一標(biāo)識(shí)熱鍵的作用
uint fsModifiers, // 熱鍵只有在按下Alt、 Ctrl、Shift、Windows等鍵時(shí)才會(huì)生效,即才會(huì)產(chǎn)生WM_HOTKEY信息
Keys vk // 虛擬鍵,即按了Alt+Ctrl+ X ,X就是代表虛擬鍵
);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(
IntPtr hWnd, // 窗口句柄
int id // 要取消熱鍵的ID
);
}
}
主窗體 Form1.cs
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
namespace test {
public partial class Form1 : Form {
[Flags]
public enum KeyModifiers { //定義熱鍵值字符串(熱鍵值是系統(tǒng)規(guī)定的,不能改變)
None = 0,
Alt = 1,
Ctrl = 2,
Shift = 4,
WindowsKey = 8
}
public Form1() {
InitializeComponent();
}
//窗體加載時(shí)-注冊快捷鍵
private void Form1_Load(object sender, EventArgs e) {
uint ctrlHotKey = (uint)(KeyModifiers.Alt | KeyModifiers.Ctrl);
// 注冊熱鍵為Alt+Ctrl+A, "100"為唯一標(biāo)識(shí)熱鍵
HotKey.RegisterHotKey(Handle,100,ctrlHotKey,Keys.A);
}
//截圖按鈕
private void button1_Click(object sender, EventArgs e) {
if (this.WindowState != FormWindowState.Minimized) {
this.WindowState = FormWindowState.Minimized;
Thread.Sleep(200);
}
int swidth = Screen.PrimaryScreen.Bounds.Width;
int sheight = Screen.PrimaryScreen.Bounds.Height;
Bitmap btm = new Bitmap(swidth,sheight); //空圖與屏幕同大小
Graphics g = Graphics.FromImage(btm); //空圖的畫板
g.CopyFromScreen(new Point(0,0),new Point(0,0),new Size(swidth,sheight)); //將屏幕內(nèi)容復(fù)制到空圖
Cutter cutter = new Cutter(btm); //傳送截圖
cutter.FormBorderStyle = FormBorderStyle.None; //截圖全屏,無邊框
cutter.BackgroundImage = btm; //新的窗體截圖做背景
cutter.Show();
}
private void tiaoZ(object sender, ElapsedEventArgs e) {
}
//窗體關(guān)閉-取消熱鍵
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
HotKey.UnregisterHotKey(Handle,100);
}
//快捷鍵按下執(zhí)行的事件
private void GlobalKeyProcess() {
this.WindowState = FormWindowState.Minimized;
Thread.Sleep(200);
button1.PerformClick();
}
//重寫。監(jiān)視系統(tǒng)消息,調(diào)用對應(yīng)方法
protected override void WndProc(ref Message m) {
const int WM_HOTKEY = 0x0312;
//如果m.Msg的值為0x0312(我也不知道為什么是0x0312)那么表示用戶按下了熱鍵
switch (m.Msg) {
case WM_HOTKEY:
if (m.WParam.ToString().Equals("100")) {
GlobalKeyProcess();
}
//todo 其它熱鍵
break;
}
// 將系統(tǒng)消息傳遞自父類的WndProc
base.WndProc(ref m);
}
}
}
截圖窗體-核心 Cutter.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace test {
public partial class Cutter : Form {
Bitmap screenBtmp = null; //電腦屏幕的截圖
public Cutter(Bitmap btm) {
InitializeComponent();
screenBtmp = btm;
}
//鼠標(biāo)右鍵退出
private void Cutter_MouseClick(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Right) {
this.DialogResult = DialogResult.OK;
this.Close();
}
}
bool CatchStart = false; //自由截圖開始
Point downPoint; //初始點(diǎn)
//鼠標(biāo)左鍵按下-開始自由截圖
private void Cutter_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
if (!CatchStart) {
CatchStart = true;
downPoint = new Point(e.X,e.Y); //初始點(diǎn)
}
}
}
Rectangle catchRec;//存放截取范圍
//鼠標(biāo)移動(dòng)-繪制自由截圖路徑
private void Cutter_MouseMove(object sender, MouseEventArgs e) { //路徑繪制,核心
if (CatchStart) {
//
//二次緩沖
//不是直接在控件的背景畫板上進(jìn)行繪制鼠標(biāo)移動(dòng)路徑,那樣會(huì)造成繪制很多路徑,因?yàn)榍懊胬L制的路徑還在
//而是在內(nèi)存中每移動(dòng)一次鼠標(biāo)就創(chuàng)建一張和屏幕截圖一樣的新BImtap,在這個(gè)Bitmap中繪制鼠標(biāo)移動(dòng)路徑
//然后在窗體背景畫板上,繪制這個(gè)新的Bitmap,這樣就不會(huì)造成繪制很多路徑,因?yàn)槊看味祭L制了全新的Bitmao
//但是這樣做的話,因?yàn)槭髽?biāo)移動(dòng)的次數(shù)是大量的,所以在內(nèi)存中會(huì)創(chuàng)建大量的Bitmap會(huì)造成內(nèi)存消耗嚴(yán)重,所以每次移動(dòng)繪制完后,
//需要釋放Dispose() 畫板,畫筆,Bitmap資源。
//
Bitmap copyBtmp = (Bitmap)screenBtmp.Clone(); //創(chuàng)建新的,在其上繪制路徑
//左上角
Point firstP = new Point(downPoint.X,downPoint.Y);
//新建畫板,畫筆
Graphics g = Graphics.FromImage(copyBtmp);
Pen p = new Pen(Color.Red,1);
//計(jì)算路徑范圍
int width = Math.Abs(e.X - downPoint.X);
int height = Math.Abs(e.Y - downPoint.Y);
if (e.X < downPoint.X) {
firstP.X = e.X;
}
if (e.Y < downPoint.Y) {
firstP.Y = e.Y;
}
//繪制路徑
catchRec = new Rectangle(firstP,new Size(width,height));
//將路徑繪制在新的BItmap上,之后要釋放
g.DrawRectangle(p, catchRec);
g.Dispose();
p.Dispose();
//窗體背景畫板
Graphics gf = this.CreateGraphics();
//將新圖繪制在窗體的畫板上 -- 自由截圖-路徑繪制處,其實(shí)還是一張和屏幕同樣大小的圖片,只不過上面有紅色的選擇路徑
gf.DrawImage(copyBtmp,new Point(0,0));
gf.Dispose();
//釋放內(nèi)存Bimtap
copyBtmp.Dispose();
}
}
bool catchFinished = false; //自由截圖結(jié)束標(biāo)志
//鼠標(biāo)左鍵彈起-結(jié)束自由截圖
private void Cutter_MouseUp(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
if (CatchStart) {
CatchStart = false;
catchFinished = true;
}
}
}
//鼠標(biāo)左鍵雙擊,保存自由截取的圖片
private void Cutter_MouseDoubleClick(object sender, MouseEventArgs e) {
if((e.Button == MouseButtons.Left) && catchFinished){
//創(chuàng)建用戶截取的范圍大小的空圖
Bitmap catchBtmp = new Bitmap(catchRec.Width,catchRec.Height);
Graphics g = Graphics.FromImage(catchBtmp);
//在原始的屏幕截圖ScreenBitmap上 截取 用戶選擇范圍大小的區(qū)域 繪制到上面的空圖
//繪制完后,這個(gè)空圖就是我們想要的截取的圖片
//參數(shù)1 原圖
//參數(shù)2 在空圖上繪制的范圍區(qū)域
//參數(shù)3 原圖的截取范圍
//參數(shù)4 度量單位
g.DrawImage(screenBtmp,new Rectangle(0,0,catchRec.Width,catchRec.Height),catchRec,GraphicsUnit.Pixel);
//將自由截取的圖片保存到剪切板中
Clipboard.Clear();
Clipboard.SetImage(catchBtmp);
g.Dispose();
catchFinished = false;
this.BackgroundImage = screenBtmp;
catchBtmp.Dispose();
this.DialogResult = DialogResult.OK;
this.Close();
}
}
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解WPF如何顯示具有層級關(guān)系的數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了在WPF中如何顯示具有層級關(guān)系的數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
使用C# Winform應(yīng)用程序獲取網(wǎng)頁源文件的解決方法
本篇文章是對使用C# Winform應(yīng)用程序獲取網(wǎng)頁源文件的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C# Socket 發(fā)送&接收&返回 簡單應(yīng)用實(shí)例
下面小編就為大家分享一篇C# Socket 發(fā)送&接收&返回 簡單應(yīng)用實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-11-11
WPF自定義實(shí)現(xiàn)雷達(dá)圖控件的示例詳解
雷達(dá)圖用于表示不同內(nèi)容的占比關(guān)系,在項(xiàng)目中有廣泛的應(yīng)用,但是目前未曾有封裝良好的雷達(dá)圖控件,所以本文分享了如何封裝一個(gè)通用的雷達(dá)圖控件,希望對大家有所幫助2023-08-08

