C#實(shí)現(xiàn)截圖工具小項(xiàng)目
本文實(shí)例為大家分享了C#實(shí)現(xiàn)截圖工具小項(xiàng)目的具體代碼,供大家參考,具體內(nèi)容如下
1.起因
一直用的截圖是qq的截圖,所以想要實(shí)現(xiàn)一個(gè)簡(jiǎn)單點(diǎn)的截圖,為了方便。
2.思路
講一下實(shí)現(xiàn)流程。
1、主窗體,上有截圖按鈕,點(diǎn)擊進(jìn)入截圖窗體
2、在截圖窗體中,背景設(shè)置為全屏幕的截圖圖片,無邊框,窗體最大化,這時(shí)你看到的就是一張屏幕圖,其實(shí)是一個(gè)窗體,然后我們將在這個(gè)窗體中截取圖片,其實(shí)主要就是畫板Graphics的使用,截取完之后圖片將保存到剪切板。
3.代碼
熱鍵注冊(cè)類 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í)-注冊(cè)快捷鍵 private void Form1_Load(object sender, EventArgs e) { uint ctrlHotKey = (uint)(KeyModifiers.Alt | KeyModifiers.Ctrl); // 注冊(cè)熱鍵為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); //空?qǐng)D與屏幕同大小 Graphics g = Graphics.FromImage(btm); //空?qǐng)D的畫板 g.CopyFromScreen(new Point(0,0),new Point(0,0),new Size(swidth,sheight)); //將屏幕內(nèi)容復(fù)制到空?qǐng)D 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)用對(duì)應(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)建用戶截取的范圍大小的空?qǐng)D Bitmap catchBtmp = new Bitmap(catchRec.Width,catchRec.Height); Graphics g = Graphics.FromImage(catchBtmp); //在原始的屏幕截圖ScreenBitmap上 截取 用戶選擇范圍大小的區(qū)域 繪制到上面的空?qǐng)D //繪制完后,這個(gè)空?qǐng)D就是我們想要的截取的圖片 //參數(shù)1 原圖 //參數(shù)2 在空?qǐng)D上繪制的范圍區(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(); } } } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解WPF如何顯示具有層級(jí)關(guān)系的數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了在WPF中如何顯示具有層級(jí)關(guān)系的數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04使用C# Winform應(yīng)用程序獲取網(wǎng)頁源文件的解決方法
本篇文章是對(duì)使用C# Winform應(yīng)用程序獲取網(wǎng)頁源文件的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C# MJPEG 客戶端簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了C# MJPEG 客戶端簡(jiǎn)單實(shí)現(xiàn)的方法,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03C# Socket 發(fā)送&接收&返回 簡(jiǎn)單應(yīng)用實(shí)例
下面小編就為大家分享一篇C# Socket 發(fā)送&接收&返回 簡(jiǎn)單應(yīng)用實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-11-11WPF自定義實(shí)現(xiàn)雷達(dá)圖控件的示例詳解
雷達(dá)圖用于表示不同內(nèi)容的占比關(guān)系,在項(xiàng)目中有廣泛的應(yīng)用,但是目前未曾有封裝良好的雷達(dá)圖控件,所以本文分享了如何封裝一個(gè)通用的雷達(dá)圖控件,希望對(duì)大家有所幫助2023-08-08