1,目的:
2,知识点:
[DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, Keys vk);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
[DllImport("user32.dll")]
public static extern IntPtr CopyIcon(IntPtr hIcon);
[DllImport("user32.dll", EntryPoint = "GetCursorInfo")]
public static extern bool GetCursorInfo(ref CURSORINFO cInfo);
[DllImport("user32.dll", EntryPoint = "GetIconInfo")]
public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO iInfo);
[DllImport("kernel32")]
public static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")]
public static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retval, int size, string filePath);
- 系统消息的重写。(Message相关链接:Message类的Msg属性所关联的所有ID_msg=0x001a-CSDN博客)
protected override void WndProc(ref Message m)
{
//WM_HOTKEY=0x0312,热键关联的消息ID
const int WM_HOTKEY = 0x0312;
//按快捷键
switch (m.Msg)
{
case WM_HOTKEY:
switch (m.WParam.ToInt32())
{
case 81: //按下的是Shift+F
string ss = "";
CaptureImage(ref ss);
break;
}
break;
}
base.WndProc(ref m);
}
3,效果展示:
![C#实现带光标的截图_第1张图片](http://img.e-com-net.com/image/info8/6c07f31a815b4d8e8e876eff8db8e94e.jpg)
![C#实现带光标的截图_第2张图片](http://img.e-com-net.com/image/info8/51893eb955934d9387dac97abf632ae7.jpg)
![C#实现带光标的截图_第3张图片](http://img.e-com-net.com/image/info8/04b5cc1171284843b58ee9791132b5ea.jpg)
4代码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
bool isCaptureIcon = false;
string savePath;
private void Form1_Load(object sender, EventArgs e)
{
//判断是否存在配置文件如果不存在则创建,如果存在则读取
string configPath = Path.GetFullPath("../../config.ini");
if (File.Exists(configPath))
{
savePath = ReadFromINI(configPath, "Configuration", "Location");
string str = ReadFromINI(configPath, "Configuration", "CaptureIcon");
bool result;
if (bool.TryParse(str, out result))
{
isCaptureIcon = result;
}
else
{
isCaptureIcon = false;
}
}
else
{
File.Create(configPath);
isCaptureIcon = false;
}
if (string.IsNullOrEmpty(savePath))
{
//获取当前启动位置的盘
string startLocation = Application.StartupPath;
string defaultLocation = Directory.GetDirectoryRoot(startLocation);
savePath = defaultLocation;
}
textBox1.Text = savePath;
checkBox1.Checked = isCaptureIcon;
//进行热键注册
APIHelper.RegisterHotKey(this.Handle, 81, KeyModifiers.Shift, Keys.C);
}
//设置截图存储路径
private void btnOpenF_Click(object sender, EventArgs e)
{
using (FolderBrowserDialog fbd = new FolderBrowserDialog())
{
if (fbd.ShowDialog() == DialogResult.OK)
{
savePath = textBox1.Text = fbd.SelectedPath;
}
}
}
//保存配置
private void btnSave_Click(object sender, EventArgs e)
{
string iniPath = Path.GetFullPath("../../config.ini");
if (!File.Exists(iniPath))
{
File.Create(iniPath);
}
WriteToINI(iniPath, "Configuration", "Location", textBox1.Text);
WriteToINI(iniPath, "Configuration", "CaptureIcon", isCaptureIcon.ToString());
MessageBox.Show("已保存", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
isCaptureIcon = checkBox1.Checked;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//热键注销
APIHelper.UnregisterHotKey(this.Handle, 81);
}
//隐藏窗口
private void btnHide_Click(object sender, EventArgs e)
{
this.Hide();
}
private void btnCapture_Click(object sender, EventArgs e)
{
string filePath = "";
if (CaptureImage(ref filePath))
{
MessageBox.Show("已截图:" + filePath);
}
else
{
MessageBox.Show("截图失败");
}
}
//双击图标显示窗口
private void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
this.Show();
this.WindowState = FormWindowState.Normal;
this.Activate();
}
private void toolStripExit_Click(object sender, EventArgs e)
{
APIHelper.UnregisterHotKey(this.Handle, 81);
Application.Exit();
}
private void toolStripShow_Click(object sender, EventArgs e)
{
this.Visible = true;
}
//对接收的消息进行重写
protected override void WndProc(ref Message m)
{
//WM_HOTKEY=0x0312,热键关联的消息ID
const int WM_HOTKEY = 0x0312;
//按快捷键
switch (m.Msg)
{
case WM_HOTKEY:
switch (m.WParam.ToInt32())
{
case 81: //按下的是Shift+F
string ss = "";
CaptureImage(ref ss);
break;
}
break;
}
base.WndProc(ref m);
}
bool CaptureImage(ref string filePath)
{
Bitmap img;
if (!isCaptureIcon)
{
img = CaptureNoCursor();
string imgDir = Path.Combine(savePath, "Image", "NoCursor");
if (!Directory.Exists(imgDir))
{
Directory.CreateDirectory(imgDir);
}
string fileName = "IMG_" + DateTime.Now.ToString("HHmmss") + ".png";
filePath = Path.Combine(imgDir, fileName);
}
else
{
img = CaptureCursor();
string imgDir = Path.Combine(savePath, "Image", "Cursor");
if (!Directory.Exists(imgDir))
{
Directory.CreateDirectory(imgDir);
}
string fileName = "IMG_" + DateTime.Now.ToString("HHmmss") + ".png";
filePath = Path.Combine(imgDir, fileName);
}
if (img != null)
{
img.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);
return true;
}
else
{
return false;
}
}
///
/// 不含光标的截图
///
///
Bitmap CaptureNoCursor()
{
//获取屏幕尺寸
int width = APIHelper.GetSystemMetrics(0);
int height = APIHelper.GetSystemMetrics(1);
//创建图片
Bitmap img = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(img))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(width, height));
}
return img;
}
///
/// 包含光标的截图
///
///
Bitmap CaptureCursor()
{
//获取光标信息
CURSORINFO cursor = new CURSORINFO();
cursor.cbSize = Marshal.SizeOf(cursor);
if (APIHelper.GetCursorInfo(ref cursor))
{
//flags==1时光标处于显示中
if (cursor.flags == 1)
{
ICONINFO iconinfo;
//复制光标
IntPtr hwn = APIHelper.CopyIcon(cursor.hCursor);
//获取光标信息
if (APIHelper.GetIconInfo(hwn, out iconinfo))
{
Icon icon = Icon.FromHandle(hwn);
Point iconScreenPoint = new Point(cursor.ptScreenPos.X - iconinfo.xHotspot, cursor.ptScreenPos.Y - iconinfo.yHotspot);
//获取屏幕尺寸
int width = Screen.PrimaryScreen.Bounds.Width;
int height = Screen.PrimaryScreen.Bounds.Height;
//创建图片
Bitmap img = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(img))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(width, height));
g.DrawIcon(icon, iconScreenPoint.X, iconScreenPoint.Y);
}
return img;
}
}
}
return null;
}
public static string ReadFromINI(string filePath, string rootValue, string key, string defValue = "")
{
StringBuilder sb = new StringBuilder(1024);
APIHelper.GetPrivateProfileString(rootValue, key, defValue, sb, 1024, filePath);
return sb.ToString();
}
public static void WriteToINI(string filePath, string rootValue, string key, string newVal)
{
APIHelper.WritePrivateProfileString(rootValue, key, newVal, filePath);
}
}
///
/// 有关图标或光标的信息
///
[StructLayout(LayoutKind.Sequential)]
struct ICONINFO
{
///
/// 指定此结构是定义图标还是游标。 值为 TRUE 指定图标; FALSE 指定游标。
///
public bool fIcon;
///
/// 光标热点的 x 坐标。 如果此结构定义了图标,则热点始终位于图标的中心,并且忽略此成员。
///
public Int32 xHotspot;
///
/// 光标热点的 y 坐标。 如果此结构定义了图标,则热点始终位于图标的中心,并且忽略此成员。
///
public Int32 yHotspot;
///
/// 单色掩码 位图图标的句柄。
///
public IntPtr hbmMask;
///
/// 图标颜色 位图的句柄。
///
public IntPtr hbmColor;
}
///
/// 全局游标信息
///
[StructLayout(LayoutKind.Sequential)]
struct CURSORINFO
{
///
/// 结构大小(以字节为单位)。 调用方必须将此设置为 sizeof(CURSORINFO)。
///
public Int32 cbSize;
///
/// 游标状态。 此参数的取值可为下列值之一:0:光标处于隐藏。1:光标处于显示。2:Windows 8:取消光标。 此标志指示系统未绘制光标,因为用户是通过触摸或笔而不是鼠标提供输入。
///
public Int32 flags;
///
/// 光标的句柄。
///
public IntPtr hCursor;
///
/// 接收光标的屏幕坐标的结构。
///
public Point ptScreenPos;
}
[Flags()]
public enum KeyModifiers
{
None = 0,
Alt = 1,
Ctrl = 2,
Shift = 4,
WindowsKey = 8
}
class APIHelper
{
///
/// 获取与windows环境有关的信息
///
/// 指定获取信息
///
[DllImport("user32.dll")]
public static extern int GetSystemMetrics(int mVal);
///
/// 获取指定图标或者鼠标的一个副本
///
/// 欲复制的图标或指针的句柄
///
[DllImport("user32.dll")]
public static extern IntPtr CopyIcon(IntPtr hIcon);
[DllImport("user32.dll", EntryPoint = "GetCursorInfo")]
public static extern bool GetCursorInfo(ref CURSORINFO cInfo);
[DllImport("user32.dll", EntryPoint = "GetIconInfo")]
public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO iInfo);
[DllImport("kernel32")]
public static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")]
public static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retval, int size, string filePath);
///
/// 热键注册
///
/// 要定义热键的窗口的句柄
/// 定义热键ID(不能与其它ID重复)
/// 标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效
/// 定义热键的内容
/// 如果函数执行成功,返回值不为0。如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。
[DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, Keys vk);
///
/// 热键注销
///
/// 要取消热键的窗口的句柄
/// 要取消热键的ID
///
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
///
/// 从INI文件中读取数据
///
/// INI文件的全路径
/// 根节点值,例如根节点[ConnectString]的值为:ConnectString
/// 根节点下的键
/// 当标记值未设定或不存在时的默认值
///
}