C#中實現QQ截圖的功能及相關問題

来源:http://www.cnblogs.com/Audient/archive/2017/10/18/7684922.html
-Advertisement-
Play Games

對於QQ截圖,肯定是早就有認識了,只是一直沒有去認真觀察這個操作的具體實現步驟。所以這裡將自己的記憶中的步驟簡單的寫一下: 習慣性用QQ或者TIM的人,一般是使用Ctrl+Alt+A 快捷鍵(熱鍵)快速實現截圖。 因為考慮到截圖模式的時候 一般只能顯示一個窗體 所以就考慮使用單例模式 在Screen ...


對於QQ截圖,肯定是早就有認識了,只是一直沒有去認真觀察這個操作的具體實現步驟。所以這裡將自己的記憶中的步驟簡單的寫一下:

習慣性用QQ或者TIM的人,一般是使用Ctrl+Alt+A  快捷鍵(熱鍵)快速實現截圖。

  1. Ctrl+Alt+A  進入截圖模式
  2. 滑鼠左鍵點擊
  3. 滑鼠拖動對截圖去進行選取
  4. 滑鼠左鍵彈起
  5. 雙擊截圖區域  保存圖片到剪貼板
  6. 滑鼠右鍵點擊
  7. 退出截圖模式

因為考慮到截圖模式的時候  一般只能顯示一個窗體  所以就考慮使用單例模式  在ScreenBody窗體中實現以下代碼

1:創建單例  

private static ScreenBody screenBody=null;

2:私有化構造函數

private ScreenBody()
{
InitializeComponent();
}

3:創建靜態方法

private static ScreenBody GetSingle()
{
if(screenBody==null)
{
screenBody=new ScreenBody();
}
return screenBody;
}

進一步討論一下在Main窗體中的調用  Main中添加了一個button 命名為btnCutter  

private void btnCutter_Click(object sender,EventArgs e)
{
 //新建一個和屏幕大小相同的圖片img  也可以用BitMap
image img=new Bitmap(Screen.AllScreens[0].Bounds.Width,Screen.AllScreens[0].Bounds.Height);
//創建一個畫板 讓我們可以在畫板上畫圖  大小和屏幕大小一樣大
Graphics g=Graphics.FromImage(img);
 //將屏幕圖片拷貝到空白圖片img
g.CopyFromScreen(new Point(0,0),new Point(0,0),Screen.AllScreens[0].Bounds.Size);
//創建截圖窗體
ScreenBody body=ScreenBody.GetSingle();
//指示窗體的背景圖片為屏幕圖片
body.BackGroundImage=img;
body.ShowDialog();

}

 對於窗體ScreenBody

聲明全局變數

        private bool CatchStart;//判斷滑鼠是否按下
        private bool CatchFinished;//判斷矩形是否繪製完成
        private Point DownPoint;//滑鼠按下的點
        private Image baseMap;//最基本的圖片
        private Rectangle CatchRectangle;    

 

 

  必須要實現的那幾個事件

  • 滑鼠按下MouseDown
  •  private void ScreenBody_MouseDown(object sender, MouseEventArgs e)
            {
                //滑鼠左鍵按下就是開始畫圖,也就是截圖
                if (e.Button == MouseButtons.Left)
                {
                    if (CatchStart == false)
                    {
                        CatchStart = true;
                        //保存此時的坐標
                        DownPoint = new Point(e.X, e.Y);
                    }
                }
            }

    滑鼠移動 MouseMove

  •  private void ScreenBody_MouseMove(object sender, MouseEventArgs e)
            {
                //確保截圖開始
                if (CatchStart)
                {
                    //新建一個圖片,讓它與屏幕圖片相同
                    Bitmap copyBmp = (Bitmap)baseMap.Clone();
                    //滑鼠按下時的坐標
                    Point newPoint = new Point(DownPoint.X, DownPoint.Y);
    
                    //新建畫板和畫筆
                    Graphics g = Graphics.FromImage(copyBmp);
                    Pen p = new Pen(Color.Azure, 1);//畫筆的顏色為azure 寬度為1
    
                    //獲取矩形的長度 
                    int width = Math.Abs(e.X - DownPoint.Y);
                    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();
    
                    //從當前窗體創建新的畫板
                    Graphics g1 = this.CreateGraphics();
                    //將剛剛所畫的圖片畫到截圖窗體上去
                    //為什麼不直接在當前窗體畫圖呢???
                    //如果直接解決將矩形畫在窗體上,會造成圖片抖動而且有多個矩形
                    //這樣實現也屬於二次緩衝技術
                    g1.DrawImage(copyBmp, new Point(0, 0));
                    g1.Dispose();
    
                    //釋放拷貝圖片 防止記憶體被大量的消耗
                    copyBmp.Dispose();
                }

    滑鼠彈起 Mouseup

  •   /// <summary>
            /// 滑鼠左鍵彈起事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void ScreenBody_MouseUp(object sender, MouseEventArgs e)
            {
                if (e.Button == MouseButtons.Left)
                {
                    //如果截圖已經開始,滑鼠左鍵彈起設置截圖完成
                    if (CatchStart)
                    {
                        CatchStart = false;
                        CatchFinished = true;
                    }
                }
            }

    滑鼠雙擊

  •  private void ScreenBody_MouseDoubleClick(object sender, MouseEventArgs e)
            {
                if (e.Button==MouseButtons.Left&&CatchFinished)
                {
                    //新建一個矩形大小相同的空白圖片
                    Bitmap CatcheBmp = new Bitmap(CatchRectangle.Width, CatchRectangle.Height);
                    Graphics g = Graphics.FromImage(CatcheBmp); ;
               
                    //把basemap中指定的部分按照指定大小畫到空白圖片上
                    //CatchRectangle指定的baseMap中指定的部分
                    //第二個參數指定繪製到空白圖片的位置和大小
                    //畫完後CatchedBmp不再是空白圖片,而是具有與截取的圖片一樣的內容
                    g.DrawImage(baseMap, new Rectangle(0, 0, CatchRectangle.Width, CatchRectangle.Height));
    
                    //將圖片保存到剪切板中
                    Clipboard.SetImage(CatcheBmp);
                    g.Dispose();
    
                    CatchFinished = false;
                    this.BackgroundImage = baseMap;
                    CatcheBmp.Dispose();
                    this.DialogResult = DialogResult.OK;
                    this.Close();
                }
            }

    滑鼠右鍵 退出截圖

  •  /// <summary>
            /// 滑鼠右鍵點擊結束截圖
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void ScreenBody_MouseClick(object sender, MouseEventArgs e)
            {
                if (e.Button == MouseButtons.Right)
                {
                    this.DialogResult = DialogResult.OK;
                    this.Close();
                }
            }

    最複雜的熱鍵註冊  自己也是去網上看的  Main窗體中

  • 聲明枚舉
     [FlagsAttribute]
        public enum KeyModifiers
        {
            None = 0,
            Alt = 1,
            Ctrl = 2,
            Shift = 4,
            WindowsKey = 8
        }
    

      然後在類中編輯一下代碼

  •  //在C#中引用命名空間System.Runtime.InteropServices;來載入非托管類user32.dll
            /*
            * RegisterHotKey函數原型及說明:
            * BOOL RegisterHotKey(
            * HWND hWnd,         // window to receive hot-key notification
            * int id,            // identifier of hot key
            * UINT fsModifiers, // key-modifier flags
            * UINT vk            // virtual-key code);
            * 參數 id為你自己定義的一個ID值
            * 對一個線程來講其值必需在0x0000 - 0xBFFF範圍之內,十進位為0~49151
            * 對DLL來講其值必需在0xC000 - 0xFFFF 範圍之內,十進位為49152~65535
            * 在同一進程內該值必須唯一參數 fsModifiers指明與熱鍵聯合使用按鍵
            * 可取值為:MOD_ALT MOD_CONTROL MOD_WIN MOD_SHIFT參數,或數字0為無,1為Alt,2為Control,4為Shift,8為Windows
            * vk指明熱鍵的虛擬鍵碼
            */
            [System.Runtime.InteropServices.DllImport("user32.dll")] //申明API函數
            public static extern bool RegisterHotKey(
             IntPtr hWnd, // handle to window
             int id, // hot key identifier
             uint fsModifiers, // key-modifier options
             Keys vk // virtual-key code
            );
    
            [System.Runtime.InteropServices.DllImport("user32.dll")] //申明API函數
            public static extern bool UnregisterHotKey(
             IntPtr hWnd, // handle to window
             int id // hot key identifier
            );

    再接著

     private void Form1_Load(object sender, EventArgs e)
            {
                uint ctrlHotKey = (uint)(KeyModifiers.Alt | KeyModifiers.Ctrl);
                // 註冊熱鍵為Alt+Ctrl+C, "100"為唯一標識熱鍵
                RegisterHotKey(Handle, 100, ctrlHotKey, Keys.A);
            }
            //熱鍵按下執行的方法
            private void GlobalKeyProcess()
            {
                this.WindowState = FormWindowState.Minimized;
                //視窗最小化需要一定的時間  使用線程
                Thread.Sleep(200);
                btnCutter.PerformClick();
            }
    
            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;
                    default:
                        break;
                }
                base.WndProc(ref m);
            }
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                // 卸載熱鍵
                UnregisterHotKey(Handle, 100);
            }

    熱鍵的功能就能實現。但是我遇到了很多問題  首先是basemap  沒有初始化值

  • 這些問題  還有待解決!!!

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、需求分析 1.前端需支持更大的訪問量,單台Web伺服器已無法滿足需求了,則需擴容Web伺服器; 2.雖然動態內容可交由後端的PHP伺服器執行,但靜態頁面還需要Web伺服器自己解析,那是否意味著多台Web伺服器都需要在各自的系統中都存有一份靜態頁面數據呢?那麼如果能將靜態頁面集中存放,所有Web服 ...
  • 1、軟體包管理簡介 1.軟體包分類 源碼包 腳本安裝包 二進位包(RPM包、系統預設包) 2.源碼包 源碼包的優點是: 開源,如果有足夠的能力,可以修改源代碼 可以自由選擇所需要的功能 軟體設計編譯安裝,所以更加適合自己的系統,更加穩定有效 卸載方便 源碼包的缺點: 安裝過程步驟較多,尤其是安裝較大 ...
  • 什麼是HTML l HTML(HyperText Mark-up Language)即超文本標記語言或超文本標簽語言。 l 何為超文本:“超文本”可以實現頁面內可以包含圖片、鏈接,甚至音樂、程式等。 l 網頁文件本身是一種文本文件,它通過標記符號來標記要顯示的網頁中的各個部分。 l 何為標記:當瀏覽 ...
  • 這是本人第一次寫博客,若有什麼錯誤的地方或者不對的地方,還請各位不吝賜教!!! 一、磁碟配額的概念 由於Linux是一個多用戶管理的操作系統,而Linux預設情況下並不限制每個用戶使用磁碟空間的大小,假如某個用戶疏忽或者惡意占滿磁碟空間,將導致系統磁碟無法寫入甚至崩潰;為了保證系統磁碟的有足夠的剩餘 ...
  • 買了Bandwagon的vps,連接上預設terminal是英文的,有時沒有中文方便,所以想讓其支持中文。 主要步驟為以下兩步: 1. 安裝中文包 chinese-support: 安裝非常簡單,如是其他版本linux系統,使用相應的線上升級命令即可,如apt-get 2.修改字元編碼配置文件 可以 ...
  • 1.背景介紹 作為運維,在公司經常遇到一些機械性重覆工作要做,例如:為新機器裝系統,一臺兩台機器裝系統,可以用光碟、U盤等介質安裝,1小時也完成了,但是如果有成百台的伺服器還要用光碟、U盤去安裝,就顯得有些力不從心了。PXE技術就能很好的解決這個問題,本文將會對PXE的工作原理有所介紹,而cobbl ...
  • ubuntu16.04,Apache2,modsecurity,自定義規則,開源WAF,示例,實驗 ...
  • 僅以此篇謹記自己,以後加油 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...