欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#實(shí)現(xiàn)屬于自己的QQ截圖工具

 更新時(shí)間:2020年04月16日 10:38:11   投稿:lijiao  
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)屬于自己的QQ截圖工具的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了C#實(shí)現(xiàn)QQ截圖工具的具體代碼,供大家參考,具體內(nèi)容如下

下面就具體介紹下實(shí)現(xiàn)截圖工具的實(shí)現(xiàn)思路。

為了讓大家更清楚地知道如何去實(shí)現(xiàn)自己的截圖工具,首先我來描述下截圖的一個(gè)過程——我們使用QQ的截圖工具和Windows 自帶的截圖工具都可以發(fā)現(xiàn),當(dāng)我們點(diǎn)擊QQ窗體中的截圖按鈕時(shí),此時(shí)我們將看到一個(gè)全屏圖片,然后我們可以在其上截圖,當(dāng)鼠標(biāo)左鍵按下時(shí),即代表開始截圖,并我們可以移動(dòng)鼠標(biāo)來改變截圖的大小,鼠標(biāo)彈起時(shí)即代表結(jié)束截圖,此時(shí)我們可以雙擊矩形區(qū)域完全截圖,并且可以通過粘貼操作把截取的圖片粘貼到聊天窗口的發(fā)送區(qū),鼠標(biāo)右鍵點(diǎn)擊則是退出截圖。這樣我們截圖的過程描述就是這樣的,從這個(gè)描述中我們就可以抽象出實(shí)現(xiàn)我們截圖工具的思路來:

從 “此時(shí)我們將看到一個(gè)全屏圖片”這句話描述我們應(yīng)該抽象為——對(duì)于QQ截圖工具的實(shí)現(xiàn)來說,我們看到的這個(gè)全屏圖片其實(shí)并不是一張“圖片”(這里最好不要鉆空子),而是一個(gè)窗體,這個(gè)窗體我們命名為 “截圖窗體”,只是把窗體的背景圖片設(shè)置為全屏圖片。說到這里,一些沒有研究過QQ截圖工具的人開始有疑問了——我們看到的是窗體?那為什么邊框的,即沒有最大化按鈕,最下化按鈕的呢?(對(duì)于這點(diǎn)的解釋就是,程序中可以設(shè)置Form的BorderStyle屬性為none的方式來隱藏掉邊框)。
既然要設(shè)置窗體的背景圖片為全屏圖片,我們知道設(shè)置背景圖片只需要設(shè)置窗體的BackgroundImage屬性就好了,但是全屏圖片怎么獲取呢?既然是全屏圖片,自然我就應(yīng)該使窗體最大化話了,不然我們看到只是一個(gè)沒有邊框的“小圖片”了,而不是一個(gè)全屏的圖片。下面是具體實(shí)現(xiàn)這個(gè)分析的代碼:           

// 通過Graphics的CopyFromScreen方法把全屏圖片的拷貝到我們定義好的一個(gè)和屏幕大小相同的空白圖片中,
 // 拷貝完成之后,CatchBmp就是全屏圖片的拷貝了,然后指定為截圖窗體背景圖片就好了。
 // 新建一個(gè)和屏幕大小相同的圖片
 Bitmap CatchBmp = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);
 
 // 創(chuàng)建一個(gè)畫板,讓我們可以在畫板上畫圖
 // 這個(gè)畫板也就是和屏幕大小一樣大的圖片
 // 我們可以通過Graphics這個(gè)類在這個(gè)空白圖片上畫圖
 Graphics g = Graphics.FromImage(CatchBmp);

 // 把屏幕圖片拷貝到我們創(chuàng)建的空白圖片 CatchBmp中
 g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height));

 // 創(chuàng)建截圖窗體
 cutter = new Cutter();

 // 指示窗體的背景圖片為屏幕圖片
 cutter.BackgroundImage = CatchBmp;

3. 從 “然后我們可以在其上截圖”這句話中我們抽象為——其實(shí)我們截圖操作,從程序角度來說就是我們?cè)谶@個(gè)最大化的窗體中畫圖,可能這個(gè)對(duì)一些不了解GDI+畫圖的朋友有些難理解,這里做個(gè)比喻——我們會(huì)拿筆在紙上畫圖,我們可以用比畫三角形,矩形已經(jīng)各種圖形,此時(shí)紙就是我們一個(gè)畫板,筆是用來畫圖圖形的,同時(shí)筆也是有顏色和粗細(xì)的,我們可以用紅色水筆畫,畫出來的圖就是紅色的了,也可以用黑色水筆畫,自然畫出來的就是黑色的了,同樣,在GDI+也就是Graphics Device Interface Plus也就是圖形設(shè)備接口,在.NET 中也提供了一些這樣的類來讓我們實(shí)現(xiàn)對(duì)圖像的訪問,也就是我們可以使用.NET中提供的類來進(jìn)行 “畫畫”,要畫畫當(dāng)然必須要有畫板吧(我們開始比喻中紙就是畫板),在.NET 類中Graphics類就是對(duì)畫板的抽象,畫板可以由三種方式創(chuàng)建:(1)從圖片或繼承自圖像對(duì)象中創(chuàng)建;(2)從窗體或控件的Paint事件中創(chuàng)建;(3)利用窗體或控件的CreateGraphics方法創(chuàng)建。有了畫板之后,當(dāng)然就需要筆來畫畫了,在.NET 中Pen類就是起到筆的作用,在構(gòu)造函數(shù)中可以指定筆的顏色和粗細(xì),有了筆之后就是開始畫圖了,在.NET中也同樣提供了一些方法來完成畫圖,如DrawRectangle方法——畫矩形

4. 從 “當(dāng)鼠標(biāo)左鍵按下時(shí),即代表開始截圖,并我們可以移動(dòng)鼠標(biāo)來改變截圖的大小,鼠標(biāo)彈起時(shí)即代表結(jié)束截圖,此時(shí)我們可以雙擊矩形區(qū)域完全截圖,并且可以通過粘貼操作把截取的圖片粘貼到聊天窗口的發(fā)送區(qū),鼠標(biāo)右鍵點(diǎn)擊則是退出截圖”這些描述中可以抽象為——鼠標(biāo)的移動(dòng),按下,彈起等操作,在程序角度來說,也就是實(shí)現(xiàn)截圖窗體的MouseMove事件(對(duì)應(yīng)于鼠標(biāo)移動(dòng)),MouseDown事件(對(duì)應(yīng)于鼠標(biāo)左鍵按下),MouseClick事件(對(duì)應(yīng)于鼠標(biāo)右鍵結(jié)束截圖)、MouseUp(對(duì)應(yīng)于鼠標(biāo)彈起結(jié)束截圖)和MouseDoubleClick(鼠標(biāo)雙擊矩形區(qū)域完全截圖,并可以通過粘貼操作把截取的圖片粘貼到聊天窗口的發(fā)送區(qū),既然可以進(jìn)行粘貼操作來獲得截取圖片,所以必須在該事件中對(duì)剪切板設(shè)置截圖圖片),3和4的分析過程也是截圖功能的核心實(shí)現(xiàn),對(duì)應(yīng)于下面的代碼(代碼中有詳細(xì)解釋,并且大家理解的時(shí)候可以結(jié)合3和4的分析):

 /// <summary>
 /// 鼠標(biāo)右鍵點(diǎn)擊結(jié)束截圖
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void Cutter_MouseClick(object sender, MouseEventArgs e)
 {
 if (e.Button == MouseButtons.Right)
 {
 this.DialogResult = DialogResult.OK;
 this.Close();
 }
 }

 /// <summary>
 /// 鼠標(biāo)按下事件處理程序
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void Cutter_MouseDown(object sender, MouseEventArgs e)
 {
 // 鼠標(biāo)左鍵按下是開始畫圖,也就是截圖
 if (e.Button == MouseButtons.Left)
 {
 // 如果捕捉?jīng)]有開始
 if (!CatchStart)
 { 
 CatchStart = true;
 // 保存此時(shí)鼠標(biāo)按下坐標(biāo)
 DownPoint = new Point(e.X, e.Y);
 }
 }
 }

 /// <summary>
 /// 鼠標(biāo)移動(dòng)事件處理程序,即用戶改變截圖大小的處理
 /// 這個(gè)方法是截圖功能的核心方法,也就是繪制截圖
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void Cutter_MouseMove(object sender, MouseEventArgs e)
 {
 // 確保截圖開始
 if (CatchStart)
 {
 // 新建一個(gè)圖片對(duì)象,讓它與屏幕圖片相同
 Bitmap copyBmp = (Bitmap)originBmp.Clone();

 // 獲取鼠標(biāo)按下的坐標(biāo)
 Point newPoint = new Point(DownPoint.X, DownPoint.Y);

 // 新建畫板和畫筆
 Graphics g = Graphics.FromImage(copyBmp);
 Pen p = new Pen(Color.Red, 1);

 // 獲取矩形的長(zhǎng)寬
 int width = Math.Abs(e.X - DownPoint.X);
 int height = Math.Abs(e.Y-DownPoint.Y);
 if (e.X < DownPoint.X)
 {
 newPoint.X = e.X;
 }
 if (e.Y < DownPoint.Y)
 {
 newPoint.Y = e.Y;
 }

 CatchRectangle = new Rectangle(newPoint, new Size(width,height));
 
 // 將矩形畫在畫板上
 g.DrawRectangle(p, CatchRectangle);

 // 釋放目前的畫板
 g.Dispose();
 p.Dispose();
 // 從當(dāng)前窗體創(chuàng)建新的畫板
 Graphics g1 = this.CreateGraphics();
 
 // 將剛才所畫的圖片畫到截圖窗體上
 // 為什么不直接在當(dāng)前窗體畫圖呢?
 // 如果自己解決將矩形畫在窗體上,會(huì)造成圖片抖動(dòng)并且有無數(shù)個(gè)矩形
 // 這樣實(shí)現(xiàn)也屬于二次緩沖技術(shù)
 g1.DrawImage(copyBmp, new Point(0, 0));
 g1.Dispose();
 // 釋放拷貝圖片,防止內(nèi)存被大量消耗
 copyBmp.Dispose();
 }
 }

 /// <summary>
 /// 鼠標(biāo)左鍵彈起事件
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void Cutter_MouseUp(object sender, MouseEventArgs e)
 {
 if (e.Button == MouseButtons.Left)
 {
 // 如果截圖已經(jīng)開始,鼠標(biāo)左鍵彈起設(shè)置截圖完成
 if (CatchStart)
 {
 CatchStart = false;
 CatchFinished = true;
 }
 }
 }

 /// <summary>
 /// 鼠標(biāo)雙擊事件,如果鼠標(biāo)位于矩形內(nèi),則將矩形內(nèi)的圖片保存到剪切板中
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void Cutter_MouseDoubleClick(object sender, MouseEventArgs e)
 {
 if (e.Button == MouseButtons.Left && CatchFinished)
 {
 // 新建一個(gè)與矩形一樣大小的空白圖片
 Bitmap CatchedBmp = new Bitmap(CatchRectangle.Width, CatchRectangle.Height);

 Graphics g = Graphics.FromImage(CatchedBmp);

 // 把originBmp中指定部分按照指定大小畫到空白圖片上
 // CatchRectangle指定originBmp中指定部分
 // 第二個(gè)參數(shù)指定繪制到空白圖片的位置和大小
 // 畫完后CatchedBmp不再是空白圖片了,而是具有與截取的圖片一樣的內(nèi)容
 g.DrawImage(originBmp, new Rectangle(0, 0, CatchRectangle.Width, CatchRectangle.Height), CatchRectangle, GraphicsUnit.Pixel);

 // 將圖片保存到剪切板中
 Clipboard.SetImage(CatchedBmp);
 g.Dispose();
 CatchFinished = false;
 this.BackgroundImage = originBmp;
 CatchedBmp.Dispose();
 this.DialogResult = DialogResult.OK;
 this.Close();
 }
 }

5、到第4點(diǎn)為止,截圖的功能已經(jīng)分析完了,之后就是當(dāng)我們使用QQ截圖的時(shí)候,我們除了可以點(diǎn)擊聊天窗口中的截圖按鈕來進(jìn)行截圖外,還可以通過按下Alt+Ctrl+A來進(jìn)行截圖,要實(shí)現(xiàn)這個(gè)功能的思路也很簡(jiǎn)單——即當(dāng)聊天窗體加載的時(shí)候?qū)徭I(程序中我定義的熱鍵是“Alt+Ctrl+C”)進(jìn)行注冊(cè)(此時(shí)調(diào)用了Win32中RegisterHotKey方法來完成熱鍵的注冊(cè)),當(dāng)聊天窗體關(guān)閉時(shí)進(jìn)行對(duì)熱鍵的卸載,防止對(duì)熱鍵進(jìn)行多次注冊(cè),此時(shí)調(diào)用Win32中的UnregisterHotKey方法來完成,具體的實(shí)現(xiàn)代碼為:

 /// <summary>
 /// 窗體加載事件處理
 /// 在窗體加載時(shí)注冊(cè)熱鍵
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void 聊天窗體_Load(object sender, EventArgs e)
 {
 uint ctrlHotKey = (uint)(KeyModifiers.Alt|KeyModifiers.Ctrl);
 // 注冊(cè)熱鍵為Alt+Ctrl+C, "100"為唯一標(biāo)識(shí)熱鍵
 HotKey.RegisterHotKey(Handle, 100, ctrlHotKey, Keys.C);
 }

 /// <summary>
 /// 窗體關(guān)閉時(shí)處理程序
 /// 窗體關(guān)閉時(shí)取消熱鍵注冊(cè)
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void 聊天窗體_FormClosing(object sender, FormClosingEventArgs e)
 {
 // 卸載熱鍵
 HotKey.UnregisterHotKey(Handle, 100);
 }

 #endregion

 // 熱鍵按下執(zhí)行的方法
 private void GlobalKeyProcess()
 {
 this.WindowState = FormWindowState.Minimized;
 // 窗口最小化也需要一定時(shí)間
 Thread.Sleep(200);
 btnCutter.PerformClick();
 }

 /// <summary>
 /// 重寫WndProc()方法,通過監(jiān)視系統(tǒng)消息,來調(diào)用過程
 /// 監(jiān)視Windows消息
 /// </summary>
 /// <param name="m"></param>
 protected override void WndProc(ref Message m)
 {
 //如果m.Msg的值為0x0312那么表示用戶按下了熱鍵
 const int WM_HOTKEY = 0x0312;
 switch (m.Msg)
 {
 case WM_HOTKEY:
 if (m.WParam.ToString() == "100")
 {
 GlobalKeyProcess();
 }

 break;
 }

 // 將系統(tǒng)消息傳遞自父類的WndProc
 base.WndProc(ref m); 
 }

實(shí)現(xiàn)效果
上面已經(jīng)介紹了實(shí)現(xiàn)QQ截圖的一個(gè)思路的,朋友們是不是迫不及待想看看該程序的一個(gè)效果了?下面就通過一個(gè)動(dòng)畫來讓大家更形象地看到程序的運(yùn)行效果的:

QQ截圖工具下載:下載地址

總結(jié)

到這里QQ截圖的介紹部分就到這里了,本工具的實(shí)現(xiàn)自認(rèn)為講解的非常通俗易懂的,希望大家可以這樣覺得并且可以更清晰地明白QQ截圖的實(shí)現(xiàn)思路。

相關(guān)文章

  • 一文帶你了解WPF中的附加事件

    一文帶你了解WPF中的附加事件

    附加事件可用于在非元素類中定義新的 路由事件 ,并在樹中的任何元素上引發(fā)該事件。本文通過簡(jiǎn)單的示例為大家講解一下WPF附加事件的用法,需要的可以參考一下
    2022-12-12
  • 12306奇葩驗(yàn)證碼引發(fā)思考之C#實(shí)現(xiàn)驗(yàn)證碼程序

    12306奇葩驗(yàn)證碼引發(fā)思考之C#實(shí)現(xiàn)驗(yàn)證碼程序

    春運(yùn)最高峰來了!明天通過網(wǎng)絡(luò)將能買到小年夜的車票,本周四就將開售除夕日車票,但不少人被首次在春運(yùn)期間使用的圖片驗(yàn)證碼搞得很火大,小編也正在對(duì)驗(yàn)證碼進(jìn)行研究,編寫了由C#實(shí)現(xiàn)驗(yàn)證碼程序,分享給大家
    2015-12-12
  • 如何用C#獲取計(jì)算機(jī)詳細(xì)的軟件和硬件信息

    如何用C#獲取計(jì)算機(jī)詳細(xì)的軟件和硬件信息

    我們應(yīng)該都知道System.Management提供的類可以用于讀取本地計(jì)算機(jī)設(shè)備的各種數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于如何用C#獲取計(jì)算機(jī)詳細(xì)的軟件和硬件信息的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • C#實(shí)現(xiàn)自定義雙擊事件

    C#實(shí)現(xiàn)自定義雙擊事件

    這篇文章主要介紹了C#實(shí)現(xiàn)自定義雙擊事件,需要的朋友可以參考下
    2014-08-08
  • C#實(shí)現(xiàn)的海盜分金算法實(shí)例

    C#實(shí)現(xiàn)的海盜分金算法實(shí)例

    這篇文章主要介紹了C#實(shí)現(xiàn)的海盜分金算法,結(jié)合具體實(shí)例形式分析了海盜分金算法的原理與C#相應(yīng)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-07-07
  • C#中委托和事件在觀察者模式中的應(yīng)用實(shí)例

    C#中委托和事件在觀察者模式中的應(yīng)用實(shí)例

    這篇文章主要介紹了C#中委托和事件在觀察者模式中的應(yīng)用,需要的朋友可以參考下
    2014-08-08
  • c#如何顯式實(shí)現(xiàn)接口成員

    c#如何顯式實(shí)現(xiàn)接口成員

    這篇文章主要介紹了c#如何顯式實(shí)現(xiàn)接口成員,幫助大家更好的利用c#處理接口,感興趣的朋友可以了解下
    2020-10-10
  • C#子線程執(zhí)行完后通知主線程的方法

    C#子線程執(zhí)行完后通知主線程的方法

    下面小編就為大家?guī)硪黄狢#子線程執(zhí)行完后通知主線程的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • C# 字符串處理小工具

    C# 字符串處理小工具

    本文主要介紹C#字符串處理小工具,實(shí)現(xiàn)功能包括:轉(zhuǎn)換為大寫;轉(zhuǎn)換為小寫;反轉(zhuǎn)字符串;匹配某字符串出現(xiàn)次數(shù);正則匹配;base64加密;base64解密;ROT13加密解密;MD5 32位加密。具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • C#實(shí)現(xiàn)winform漸變效果的方法

    C#實(shí)現(xiàn)winform漸變效果的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)winform漸變效果的方法,涉及到窗體的設(shè)計(jì)與屬性的修改等技巧,需要的朋友可以參考下
    2014-10-10

最新評(píng)論