这篇文章主要为大家详细介绍了C#实现QQ截图功能及相关问题,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
对于QQ截图,肯定是早就有认识了,只是一直没有去认真观察这个操作的具体实现步骤。所以这里将自己的记忆中的步骤简单的写一下:
习惯性用QQ或者TIM的人,一般是使用Ctrl+Alt+A 快捷键(热键)快速实现截图。
- Ctrl+Alt+A 进入截图模式
- 鼠标左键点击
- 鼠标拖动对截图去进行选取
- 鼠标左键弹起
- 双击截图区域 保存图片到剪贴板
- 鼠标右键点击
- 退出截图模式
因为考虑到截图模式的时候 一般只能显示一个窗体 所以就考虑使用单例模式 在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 没有初始化值
这些问题 还有待解决!!!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程学习网。
本文标题为:C#实现QQ截图功能及相关问题
基础教程推荐
- winform把Office转成PDF文件 2023-06-14
- C# List实现行转列的通用方案 2022-11-02
- C# 调用WebService的方法 2023-03-09
- C#类和结构详解 2023-05-30
- linux – 如何在Debian Jessie中安装dotnet core sdk 2023-09-26
- ZooKeeper的安装及部署教程 2023-01-22
- unity实现动态排行榜 2023-04-27
- 一个读写csv文件的C#类 2022-11-06
- C# windows语音识别与朗读实例 2023-04-27
- C#控制台实现飞行棋小游戏 2023-04-22