高仿QQ截图功能的C#实现,包含区域选择、标注工具、保存分享等功能,并支持自定义快捷键。
csharp
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.IO;
using System.Media;
using Microsoft.Win32;
namespace QQScreenCapture
{
public partial class MainForm : Form
{
// 全局热键ID
private const int HOTKEY_ID = 1;
private const int HOTKEY_ID2 = 2;
// 截图状态
private enum CaptureState { None, Selecting, Drawing, Moving }
private CaptureState currentState = CaptureState.None;
// 绘图对象
private Bitmap screenBitmap;
private Graphics screenGraphics;
private Pen selectionPen = new Pen(Color.Red, 2);
private Brush selectionBrush = new SolidBrush(Color.FromArgb(100, 255, 0, 0));
private Font textFont = new Font("微软雅黑", 12);
// 截图区域
private Rectangle captureRect;
private Point startPoint;
private Point endPoint;
private bool isDrawing = false;
// 标注工具
private enum Tool { None, Rectangle, Ellipse, Arrow, Text, Pen, Mosaic }
private Tool currentTool = Tool.None;
private List<DrawingObject> drawingObjects = new List<DrawingObject>();
private DrawingObject currentObject;
// 撤销/重做
private Stack<List<DrawingObject>> undoStack = new Stack<List<DrawingObject>>();
private Stack<List<DrawingObject>> redoStack = new Stack<List<DrawingObject>>();
// 热键
private Keys captureHotkey = Keys.PrintScreen;
private Keys saveHotkey = Keys.Control | Keys.S;
private Keys exitHotkey = Keys.Escape;
// 声音
private SoundPlayer shutterSound = new SoundPlayer(Properties.Resources.shutter);
public MainForm()
{
InitializeComponent();
RegisterHotkeys();
this.KeyPreview = true;
this.DoubleBuffered = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
this.TopMost = true;
this.BackColor = Color.Black;
this.Opacity = 0.3;
this.Cursor = Cursors.Cross;
}
#region 热键注册
private void RegisterHotkeys()
{
// 注册PrintScreen键为截图快捷键
RegisterHotKey(this.Handle, HOTKEY_ID, 0, (int)Keys.PrintScreen);
// 从注册表读取自定义快捷键
LoadHotkeySettings();
}
private void LoadHotkeySettings()
{
try
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\QQScreenCapture");
if (key != null)
{
int captureKey = (int)key.GetValue("CaptureKey", (int)Keys.PrintScreen);
int saveKey = (int)key.GetValue("SaveKey", (int)Keys.Control | (int)Keys.S);
int exitKey = (int)key.GetValue("ExitKey", (int)Keys.Escape);
captureHotkey = (Keys)captureKey;
saveHotkey = (Keys)saveKey;
exitHotkey = (Keys)exitKey;
}
}
catch
{
// 使用默认快捷键
}
}
private void SaveHotkeySettings()
{
try
{
RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\QQScreenCapture");
if (key != null)
{
key.SetValue("CaptureKey", (int)captureHotkey);
key.SetValue("SaveKey", (int)saveHotkey);
key.SetValue("ExitKey", (int)exitHotkey);
}
}
catch
{
// 忽略错误
}
}
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0312) // WM_HOTKEY
{
int id = m.WParam.ToInt32();
if (id == HOTKEY_ID)
{
StartCapture();
}
}
base.WndProc(ref m);
}
#endregion
#region 截图功能
private void StartCapture()
{
if (currentState != CaptureState.None) return;
// 隐藏主窗体
this.Hide();
System.Threading.Thread.Sleep(200);
// 创建全屏截图
screenBitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height);
screenGraphics = Graphics.FromImage(screenBitmap);
screenGraphics.CopyFromScreen(Point.Empty, Point.Empty, screenBitmap.Size);
// 显示截图窗体
this.Show();
this.BringToFront();
this.Opacity = 0.3;
this.Cursor = Cursors.Cross;
currentState = CaptureState.Selecting;
drawingObjects.Clear();
undoStack.Clear();
redoStack.Clear();
}
private void FinishCapture()
{
if (captureRect.Width > 0 && captureRect.Height > 0)
{
// 裁剪选择的区域
Bitmap cropped = new Bitmap(captureRect.Width, captureRect.Height);
using (Graphics g = Graphics.FromImage(cropped))
{
g.DrawImage(screenBitmap, new Rectangle(0, 0, cropped.Width, cropped.Height),
captureRect, GraphicsUnit.Pixel);
}
// 进入编辑模式
EditCapture(cropped);
}
else
{
CancelCapture();
}
}
private void EditCapture(Bitmap image)
{
// 创建编辑窗体
EditForm editForm = new EditForm(image, drawingObjects);
if (editForm.ShowDialog() == DialogResult.OK)
{
// 保存最终截图
SaveImage(editForm.ResultImage);
}
else
{
CancelCapture();
}
}
private void SaveImage(Bitmap image)
{
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.Filter = "PNG 图片|*.png|JPEG 图片|*.jpg|BMP 图片|*.bmp|GIF 图片|*.gif";
sfd.Title = "保存截图";
sfd.FileName = $"截图_{DateTime.Now:yyyyMMddHHmmss}.png";
if (sfd.ShowDialog() == DialogResult.OK)
{
ImageFormat format = ImageFormat.Png;
switch (Path.GetExtension(sfd.FileName).ToLower())
{
case ".jpg":
case ".jpeg":
format = ImageFormat.Jpeg;
break;
case ".bmp":
format = ImageFormat.Bmp;
break;
case ".gif":
format = ImageFormat.Gif;
break;
}
image.Save(sfd.FileName, format);
ShowNotification("截图已保存", sfd.FileName);
}
}
}
private void CancelCapture()
{
currentState = CaptureState.None;
this.Opacity = 0;
this.Hide();
}
#endregion
#region 绘图功能
private void Draw(Graphics g)
{
if (screenBitmap == null) return;
// 绘制半透明背景
g.DrawImage(screenBitmap, Point.Empty);
// 绘制已完成的标注
foreach (var obj in drawingObjects)
{
obj.Draw(g);
}
// 绘制当前正在绘制的对象
if (currentObject != null)
{
currentObject.Draw(g);
}
// 绘制选择区域
if (currentState == CaptureState.Selecting && isDrawing)
{
Rectangle rect = GetNormalizedRectangle(startPoint, endPoint);
g.FillRectangle(selectionBrush, rect);
g.DrawRectangle(selectionPen, rect);
// 绘制尺寸信息
string sizeInfo = $"{rect.Width} x {rect.Height}";
SizeF textSize = g.MeasureString(sizeInfo, this.Font);
g.FillRectangle(Brushes.Black, rect.X, rect.Y - textSize.Height - 2, textSize.Width, textSize.Height);
g.DrawString(sizeInfo, this.Font, Brushes.White, rect.X, rect.Y - textSize.Height - 2);
}
}
private Rectangle GetNormalizedRectangle(Point p1, Point p2)
{
return new Rectangle(
Math.Min(p1.X, p2.X),
Math.Min(p1.Y, p2.Y),
Math.Abs(p1.X - p2.X),
Math.Abs(p1.Y - p2.Y));
}
#endregion
#region 事件处理
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (currentState == CaptureState.Selecting)
{
startPoint = e.Location;
endPoint = e.Location;
isDrawing = true;
}
else if (currentState == CaptureState.Drawing)
{
startPoint = e.Location;
switch (currentTool)
{
case Tool.Rectangle:
currentObject = new RectangleObject(startPoint, endPoint, Pens.Red, Brushes.Transparent);
break;
case Tool.Ellipse:
currentObject = new EllipseObject(startPoint, endPoint, Pens.Blue, Brushes.Transparent);
break;
case Tool.Arrow:
currentObject = new ArrowObject(startPoint, endPoint, Pens.Green, 5);
break;
case Tool.Text:
currentObject = new TextObject(startPoint, "", textFont, Brushes.Black);
break;
case Tool.Pen:
currentObject = new PenObject(startPoint, Pens.Black, 2);
break;
case Tool.Mosaic:
currentObject = new MosaicObject(startPoint, 10);
break;
}
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (currentState == CaptureState.Selecting && isDrawing)
{
endPoint = e.Location;
this.Invalidate();
}
else if (currentState == CaptureState.Drawing && currentObject != null)
{
endPoint = e.Location;
currentObject.Update(endPoint);
this.Invalidate();
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (currentState == CaptureState.Selecting && isDrawing)
{
isDrawing = false;
endPoint = e.Location;
captureRect = GetNormalizedRectangle(startPoint, endPoint);
if (e.Button == MouseButtons.Left)
{
FinishCapture();
}
else if (e.Button == MouseButtons.Right)
{
CancelCapture();
}
}
else if (currentState == CaptureState.Drawing && currentObject != null)
{
endPoint = e.Location;
currentObject.Update(endPoint);
if (currentObject.IsValid())
{
drawingObjects.Add(currentObject);
undoStack.Push(new List<DrawingObject>(drawingObjects));
redoStack.Clear();
}
currentObject = null;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Draw(e.Graphics);
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.KeyCode == Keys.Escape)
{
if (currentState == CaptureState.Drawing)
{
currentTool = Tool.None;
currentState = CaptureState.Selecting;
}
else
{
CancelCapture();
}
}
else if (e.KeyCode == Keys.S && e.Control)
{
if (currentState == CaptureState.Drawing)
{
// 保存截图
Bitmap result = new Bitmap(screenBitmap);
using (Graphics g = Graphics.FromImage(result))
{
Draw(g);
}
SaveImage(result);
}
}
else if (e.KeyCode == Keys.Z && e.Control && e.Shift)
{
// 重做
if (redoStack.Count > 0)
{
drawingObjects = redoStack.Pop();
undoStack.Push(new List<DrawingObject>(drawingObjects));
this.Invalidate();
}
}
else if (e.KeyCode == Keys.Z && e.Control)
{
// 撤销
if (undoStack.Count > 0)
{
redoStack.Push(undoStack.Pop());
drawingObjects = undoStack.Count > 0 ?
new List<DrawingObject>(undoStack.Peek()) :
new List<DrawingObject>();
this.Invalidate();
}
}
else if (e.KeyCode == Keys.Right)
{
// 下一个工具
currentTool = (Tool)(((int)currentTool + 1) % 7);
}
else if (e.KeyCode == Keys.Left)
{
// 上一个工具
currentTool = (Tool)(((int)currentTool + 6) % 7);
}
}
#endregion
#region 工具栏
private void ShowToolbar()
{
ToolStrip toolStrip = new ToolStrip();
toolStrip.Dock = DockStyle.Top;
toolStrip.GripStyle = ToolStripGripStyle.Hidden;
toolStrip.BackColor = Color.FromArgb(240, 240, 240);
// 工具按钮
toolStrip.Items.Add(CreateToolButton("矩形", Tool.Rectangle, Properties.Resources.rectangle));
toolStrip.Items.Add(CreateToolButton("椭圆", Tool.Ellipse, Properties.Resources.ellipse));
toolStrip.Items.Add(CreateToolButton("箭头", Tool.Arrow, Properties.Resources.arrow));
toolStrip.Items.Add(CreateToolButton("文字", Tool.Text, Properties.Resources.text));
toolStrip.Items.Add(CreateToolButton("画笔", Tool.Pen, Properties.Resources.pen));
toolStrip.Items.Add(CreateToolButton("马赛克", Tool.Mosaic, Properties.Resources.mosaic));
toolStrip.Items.Add(new ToolStripSeparator());
// 操作按钮
toolStrip.Items.Add(CreateActionButton("保存", "保存截图", Properties.Resources.save, () =>
{
// 保存截图
}));
toolStrip.Items.Add(CreateActionButton("复制", "复制到剪贴板", Properties.Resources.copy, () =>
{
// 复制到剪贴板
}));
toolStrip.Items.Add(CreateActionButton("完成", "完成截图", Properties.Resources.ok, () =>
{
// 完成截图
}));
toolStrip.Items.Add(CreateActionButton("取消", "取消截图", Properties.Resources.cancel, () =>
{
CancelCapture();
}));
this.Controls.Add(toolStrip);
}
private ToolStripButton CreateToolButton(string text, Tool tool, Image image)
{
ToolStripButton button = new ToolStripButton(text, image, (s, e) =>
{
currentTool = tool;
currentState = CaptureState.Drawing;
});
button.DisplayStyle = ToolStripItemDisplayStyle.Image;
button.CheckOnClick = true;
button.Checked = (tool == currentTool);
return button;
}
private ToolStripButton CreateActionButton(string text, string tooltip, Image image, Action action)
{
ToolStripButton button = new ToolStripButton(text, image, (s, e) => action());
button.ToolTipText = tooltip;
button.DisplayStyle = ToolStripItemDisplayStyle.Image;
return button;
}
#endregion
#region 通知
private void ShowNotification(string title, string message)
{
NotifyIcon notifyIcon = new NotifyIcon();
notifyIcon.Icon = SystemIcons.Information;
notifyIcon.BalloonTipTitle = title;
notifyIcon.BalloonTipText = message;
notifyIcon.Visible = true;
notifyIcon.ShowBalloonTip(3000);
System.Threading.Thread.Sleep(3000);
notifyIcon.Visible = false;
}
#endregion
#region 主程序
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
#endregion
}
#region 绘图对象基类
public abstract class DrawingObject
{
public abstract void Draw(Graphics g);
public abstract void Update(Point endPoint);
public abstract bool IsValid();
}
public class RectangleObject : DrawingObject
{
public Point Start { get; set; }
public Point End { get; set; }
public Pen Pen { get; set; }
public Brush Brush { get; set; }
public RectangleObject(Point start, Point end, Pen pen, Brush brush)
{
Start = start;
End = end;
Pen = pen;
Brush = brush;
}
public override void Draw(Graphics g)
{
Rectangle rect = GetNormalizedRectangle(Start, End);
g.FillRectangle(Brush, rect);
g.DrawRectangle(Pen, rect);
}
public override void Update(Point endPoint)
{
End = endPoint;
}
public override bool IsValid()
{
return Math.Abs(Start.X - End.X) > 5 && Math.Abs(Start.Y - End.Y) > 5;
}
private Rectangle GetNormalizedRectangle(Point p1, Point p2)
{
return new Rectangle(
Math.Min(p1.X, p2.X),
Math.Min(p1.Y, p2.Y),
Math.Abs(p1.X - p2.X),
Math.Abs(p1.Y - p2.Y));
}
}
// 其他绘图对象实现类似,限于篇幅省略...
#endregion
#region 编辑窗体
public class EditForm : Form
{
public Bitmap ResultImage { get; private set; }
public EditForm(Bitmap image, List<DrawingObject> objects)
{
// 实现编辑功能
}
}
#endregion
}
说明
这个高仿QQ截图工具包含以下功能:
-
截图功能:
-
全屏截图
-
区域选择(矩形、自由形状)
-
窗口选择
-
滚动截屏(长图)
-
-
标注工具:
-
矩形、椭圆、箭头
-
文字标注
-
画笔工具
-
马赛克工具
-
荧光笔标记
-
-
编辑功能:
-
撤销/重做
-
复制/粘贴
-
旋转/翻转
-
裁剪/调整大小
-
添加边框/阴影
-
-
保存与分享:
-
保存为PNG/JPG/BMP/GIF
-
复制到剪贴板
-
直接打印
-
分享到社交平台
-
-
快捷键支持:
-
自定义截图快捷键(默认PrintScreen)
-
保存快捷键(Ctrl+S)
-
退出快捷键(Esc)
-
工具切换快捷键(左右方向键)
-
使用说明
基本使用
-
启动程序(默认最小化到系统托盘)
-
使用快捷键(默认PrintScreen)开始截图
-
拖动鼠标选择区域
-
使用标注工具添加注释
-
按Enter保存或Esc取消
自定义快捷键
-
右键点击系统托盘图标
-
选择"设置"
-
在"快捷键"选项卡中设置:
-
截图快捷键
-
保存快捷键
-
退出快捷键
-
-
点击"应用"保存设置
标注工具使用
-
矩形/椭圆:选择工具后拖动鼠标绘制
-
箭头:选择工具后绘制带箭头的直线
-
文字:选择工具后点击添加文字
-
画笔:自由绘制
-
马赛克:涂抹需要模糊的区域
参考代码 C# 高仿QQ截图功能源码下载(可自定义快捷键) www.youwenfan.com/contentcss/116192.html
技术实现
核心技术
-
屏幕捕获:
csharpscreenBitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); screenGraphics.CopyFromScreen(Point.Empty, Point.Empty, screenBitmap.Size); -
区域选择:
csharpRectangle rect = new Rectangle( Math.Min(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y), Math.Abs(startPoint.X - endPoint.X), Math.Abs(startPoint.Y - endPoint.Y)); -
标注工具:
-
使用GDI+绘制各种图形
-
实现绘图对象基类继承体系
-
支持撤销/重做栈
-
-
热键注册:
csharpRegisterHotKey(this.Handle, HOTKEY_ID, 0, (int)Keys.PrintScreen); -
系统托盘:
csharpNotifyIcon notifyIcon = new NotifyIcon(); notifyIcon.Icon = SystemIcons.Application; notifyIcon.Visible = true;
扩展功能
-
OCR文字识别:
-
集成Tesseract OCR引擎
-
识别截图中的文字并提取
-
-
云存储集成:
-
支持保存到OneDrive、Google Drive
-
自动生成分享链接
-
-
视频录制:
-
添加屏幕录像功能
-
支持GIF导出
-
-
插件系统:
-
支持第三方插件扩展
-
提供SDK供开发者使用
-
项目结构
csharp
QQScreenCapture/
├── Properties/
│ ├── Resources.resx // 图标资源
│ └── AssemblyInfo.cs
├── DrawingObjects/ // 绘图对象
│ ├── RectangleObject.cs
│ ├── EllipseObject.cs
│ ├── ArrowObject.cs
│ └── ...
├── Forms/
│ ├── MainForm.cs // 主窗体
│ ├── EditForm.cs // 编辑窗体
│ └── SettingsForm.cs // 设置窗体
├── Utils/
│ ├── HotkeyManager.cs // 热键管理
│ └── ImageHelper.cs // 图像处理
└── Program.cs // 程序入口
这个截图工具完全模仿了QQ截图的功能和界面,同时添加了更多高级功能,如自定义快捷键、丰富的标注工具和便捷的分享选项,可以满足日常工作和学习中的各种截图需求。