C#中实现QQ截图的功能及相关问题
對(duì)于QQ截圖,肯定是早就有認(rèn)識(shí)了,只是一直沒(méi)有去認(rèn)真觀察這個(gè)操作的具體實(shí)現(xiàn)步驟。所以這里將自己的記憶中的步驟簡(jiǎn)單的寫一下:
習(xí)慣性用QQ或者TIM的人,一般是使用Ctrl+Alt+A? 快捷鍵(熱鍵)快速實(shí)現(xiàn)截圖。
因?yàn)榭紤]到截圖模式的時(shí)候? 一般只能顯示一個(gè)窗體? 所以就考慮使用單例模式? 在ScreenBody窗體中實(shí)現(xiàn)以下代碼
1:創(chuàng)建單例??
private static ScreenBody screenBody=null;2:私有化構(gòu)造函數(shù)
private ScreenBody() { InitializeComponent(); }3:創(chuàng)建靜態(tài)方法
private static ScreenBody GetSingle() { if(screenBody==null) { screenBody=new ScreenBody(); } return screenBody; }進(jìn)一步討論一下在Main窗體中的調(diào)用? Main中添加了一個(gè)button 命名為btnCutter??
private void btnCutter_Click(object sender,EventArgs e) {//新建一個(gè)和屏幕大小相同的圖片img 也可以用BitMap image img=new Bitmap(Screen.AllScreens[0].Bounds.Width,Screen.AllScreens[0].Bounds.Height); //創(chuàng)建一個(gè)畫板 讓我們可以在畫板上畫圖 大小和屏幕大小一樣大 Graphics g=Graphics.FromImage(img);//將屏幕圖片拷貝到空白圖片img g.CopyFromScreen(new Point(0,0),new Point(0,0),Screen.AllScreens[0].Bounds.Size); //創(chuàng)建截圖窗體 ScreenBody body=ScreenBody.GetSingle(); //指示窗體的背景圖片為屏幕圖片 body.BackGroundImage=img; body.ShowDialog();}?對(duì)于窗體ScreenBody
聲明全局變量
private bool CatchStart;//判斷鼠標(biāo)是否按下private bool CatchFinished;//判斷矩形是否繪制完成private Point DownPoint;//鼠標(biāo)按下的點(diǎn)private Image baseMap;//最基本的圖片private Rectangle CatchRectangle;?
?
必須要實(shí)現(xiàn)的那幾個(gè)事件
- 鼠標(biāo)按下MouseDown
- private void ScreenBody_MouseDown(object sender, MouseEventArgs e){//鼠標(biāo)左鍵按下就是開(kāi)始畫圖,也就是截圖if (e.Button == MouseButtons.Left){if (CatchStart == false){CatchStart = true;//保存此時(shí)的坐標(biāo)DownPoint = new Point(e.X, e.Y);}}}
鼠標(biāo)移動(dòng) MouseMove
- private void ScreenBody_MouseMove(object sender, MouseEventArgs e){//確保截圖開(kāi)始if (CatchStart){//新建一個(gè)圖片,讓它與屏幕圖片相同Bitmap copyBmp = (Bitmap)baseMap.Clone();//鼠標(biāo)按下時(shí)的坐標(biāo)Point newPoint = new Point(DownPoint.X, DownPoint.Y);//新建畫板和畫筆Graphics g = Graphics.FromImage(copyBmp);Pen p = new Pen(Color.Azure, 1);//畫筆的顏色為azure 寬度為1//獲取矩形的長(zhǎng)度 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();//從當(dāng)前窗體創(chuàng)建新的畫板Graphics g1 = this.CreateGraphics();//將剛剛所畫的圖片畫到截圖窗體上去//為什么不直接在當(dāng)前窗體畫圖呢???//如果直接解決將矩形畫在窗體上,會(huì)造成圖片抖動(dòng)而且有多個(gè)矩形//這樣實(shí)現(xiàn)也屬于二次緩沖技術(shù)g1.DrawImage(copyBmp, new Point(0, 0));g1.Dispose();//釋放拷貝圖片 防止內(nèi)存被大量的消耗
copyBmp.Dispose();}
鼠標(biāo)彈起 Mouseup
- /// <summary>/// 鼠標(biāo)左鍵彈起事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void ScreenBody_MouseUp(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left){//如果截圖已經(jīng)開(kāi)始,鼠標(biāo)左鍵彈起設(shè)置截圖完成if (CatchStart){CatchStart = false;CatchFinished = true;}}}
鼠標(biāo)雙擊
- private void ScreenBody_MouseDoubleClick(object sender, MouseEventArgs e){if (e.Button==MouseButtons.Left&&CatchFinished){//新建一個(gè)矩形大小相同的空白圖片Bitmap CatcheBmp = new Bitmap(CatchRectangle.Width, CatchRectangle.Height);Graphics g = Graphics.FromImage(CatcheBmp); ;//把basemap中指定的部分按照指定大小畫到空白圖片上//CatchRectangle指定的baseMap中指定的部分//第二個(gè)參數(shù)指定繪制到空白圖片的位置和大小//畫完后CatchedBmp不再是空白圖片,而是具有與截取的圖片一樣的內(nèi)容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();}}
鼠標(biāo)右鍵 退出截圖
- /// <summary>/// 鼠標(biāo)右鍵點(diǎn)擊結(jié)束截圖/// </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();}}
最復(fù)雜的熱鍵注冊(cè)? 自己也是去網(wǎng)上看的? Main窗體中
- 聲明枚舉 [FlagsAttribute]public enum KeyModifiers{None = 0,Alt = 1,Ctrl = 2,Shift = 4,WindowsKey = 8}
然后在類中編輯一下代碼
- //在C#中引用命名空間System.Runtime.InteropServices;來(lái)加載非托管類user32.dll/** RegisterHotKey函數(shù)原型及說(shuō)明:* 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);* 參數(shù) id為你自己定義的一個(gè)ID值* 對(duì)一個(gè)線程來(lái)講其值必需在0x0000 - 0xBFFF范圍之內(nèi),十進(jìn)制為0~49151* 對(duì)DLL來(lái)講其值必需在0xC000 - 0xFFFF 范圍之內(nèi),十進(jìn)制為49152~65535* 在同一進(jìn)程內(nèi)該值必須唯一參數(shù) fsModifiers指明與熱鍵聯(lián)合使用按鍵* 可取值為:MOD_ALT MOD_CONTROL MOD_WIN MOD_SHIFT參數(shù),或數(shù)字0為無(wú),1為Alt,2為Control,4為Shift,8為Windows* vk指明熱鍵的虛擬鍵碼*/[System.Runtime.InteropServices.DllImport("user32.dll")] //申明API函數(shù)public static extern bool RegisterHotKey(IntPtr hWnd, // handle to windowint id, // hot key identifieruint fsModifiers, // key-modifier optionsKeys vk // virtual-key code
);[System.Runtime.InteropServices.DllImport("user32.dll")] //申明API函數(shù)public static extern bool UnregisterHotKey(IntPtr hWnd, // handle to windowint id // hot key identifier);
再接著
private void Form1_Load(object sender, EventArgs e){uint ctrlHotKey = (uint)(KeyModifiers.Alt | KeyModifiers.Ctrl);// 注冊(cè)熱鍵為Alt+Ctrl+C, "100"為唯一標(biāo)識(shí)熱鍵RegisterHotKey(Handle, 100, ctrlHotKey, Keys.A);}//熱鍵按下執(zhí)行的方法private void GlobalKeyProcess(){this.WindowState = FormWindowState.Minimized;//窗口最小化需要一定的時(shí)間 使用線程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);}熱鍵的功能就能實(shí)現(xiàn)。但是我遇到了很多問(wèn)題? 首先是basemap? 沒(méi)有初始化值
- 這些問(wèn)題? 還有待解決!!!
?
轉(zhuǎn)載于:https://www.cnblogs.com/Audient/p/7684922.html
總結(jié)
以上是生活随笔為你收集整理的C#中实现QQ截图的功能及相关问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: iOS - UIEvent事件及UIRe
- 下一篇: 高级软件工程2017第2次作业—— 个人