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

對於QQ截圖,確定是早就有認識了,只是一直沒有去認真觀察這個操做的具體實現步驟。因此這裏將本身的記憶中的步驟簡單的寫一下:ide

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

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

由於考慮到截圖模式的時候  通常只能顯示一個窗體  因此就考慮使用單例模式  在ScreenBody窗體中實現如下代碼ui

1:建立單例  this

private static ScreenBody screenBody=null;

2:私有化構造函數spa

private ScreenBody()
{
InitializeComponent();
}

3:建立靜態方法線程

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

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

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();

}

 對於窗體ScreenBodyorm

聲明全局變量blog

        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  沒有初始化值

  • 這些問題  還有待解決!!!
相關文章
相關標籤/搜索