C#實現(xiàn)QQ截圖功能及相關(guān)問題
對于QQ截圖,肯定是早就有認識了,只是一直沒有去認真觀察這個操作的具體實現(xiàn)步驟。所以這里將自己的記憶中的步驟簡單的寫一下:
習慣性用QQ或者TIM的人,一般是使用Ctrl+Alt+A 快捷鍵(熱鍵)快速實現(xiàn)截圖。
- Ctrl+Alt+A 進入截圖模式
- 鼠標左鍵點擊
- 鼠標拖動對截圖去進行選取
- 鼠標左鍵彈起
- 雙擊截圖區(qū)域 保存圖片到剪貼板
- 鼠標右鍵點擊
- 退出截圖模式

因為考慮到截圖模式的時候 一般只能顯示一個窗體 所以就考慮使用單例模式 在ScreenBody窗體中實現(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;
}
進一步討論一下在Main窗體中的調(diào)用 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);
//創(chuàng)建一個畫板 讓我們可以在畫板上畫圖 大小和屏幕大小一樣大
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();
}
對于窗體ScreenBody
聲明全局變量
private bool CatchStart;//判斷鼠標是否按下 private bool CatchFinished;//判斷矩形是否繪制完成 private Point DownPoint;//鼠標按下的點 private Image baseMap;//最基本的圖片 private Rectangle CatchRectangle;
必須要實現(xiàn)的那幾個事件
鼠標按下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();
//從當前窗體創(chuàng)建新的畫板
Graphics g1 = this.CreateGraphics();
//將剛剛所畫的圖片畫到截圖窗體上去
//為什么不直接在當前窗體畫圖呢???
//如果直接解決將矩形畫在窗體上,會造成圖片抖動而且有多個矩形
//這樣實現(xiàn)也屬于二次緩沖技術(shù)
g1.DrawImage(copyBmp, new Point(0, 0));
g1.Dispose();
//釋放拷貝圖片 防止內(nèi)存被大量的消耗
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)
{
//如果截圖已經(jīng)開始,鼠標左鍵彈起設(shè)置截圖完成
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中指定的部分
//第二個參數(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();
}
}
鼠標右鍵 退出截圖
/// <summary>
/// 鼠標右鍵點擊結(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();
}
}
最復雜的熱鍵注冊 自己也是去網(wǎng)上看的 Main窗體中
聲明枚舉
[FlagsAttribute]
public enum KeyModifiers
{
None = 0,
Alt = 1,
Ctrl = 2,
Shift = 4,
WindowsKey = 8
}
然后在類中編輯一下代碼
//在C#中引用命名空間System.Runtime.InteropServices;來加載非托管類user32.dll
/*
* RegisterHotKey函數(shù)原型及說明:
* 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為你自己定義的一個ID值
* 對一個線程來講其值必需在0x0000 - 0xBFFF范圍之內(nèi),十進制為0~49151
* 對DLL來講其值必需在0xC000 - 0xFFFF 范圍之內(nèi),十進制為49152~65535
* 在同一進程內(nèi)該值必須唯一參數(shù) fsModifiers指明與熱鍵聯(lián)合使用按鍵
* 可取值為:MOD_ALT MOD_CONTROL MOD_WIN MOD_SHIFT參數(shù),或數(shù)字0為無,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 window
int id, // hot key identifier
uint fsModifiers, // key-modifier options
Keys vk // virtual-key code
);
[System.Runtime.InteropServices.DllImport("user32.dll")] //申明API函數(shù)
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);
}
//熱鍵按下執(zhí)行的方法
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);
}
熱鍵的功能就能實現(xiàn)。但是我遇到了很多問題 首先是basemap 沒有初始化值


這些問題 還有待解決!?。?/p>
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#如何將List<string>轉(zhuǎn)換為List<double>
這篇文章主要介紹了C#如何將List<string>轉(zhuǎn)換為List<double>問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
Jquery+Ajax+Json+存儲過程實現(xiàn)高效分頁
C#使用CryptoStream類加密和解密字符串的實現(xiàn)

