服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#实现QQ截图功能及相关问题

C#实现QQ截图功能及相关问题

2022-01-25 13:59Audient C#

这篇文章主要为大家详细介绍了C#实现QQ截图功能及相关问题,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

对于qq截图,肯定是早就有认识了,只是一直没有去认真观察这个操作的具体实现步骤。所以这里将自己的记忆中的步骤简单的写一下:

习惯性用qq或者tim的人,一般是使用ctrl+alt+a  快捷键(热键)快速实现截图。

  • ctrl+alt+a  进入截图模式
  • 鼠标左键点击
  • 鼠标拖动对截图去进行选取
  • 鼠标左键弹起
  • 双击截图区域  保存图片到剪贴板
  • 鼠标右键点击
  • 退出截图模式

C#实现QQ截图功能及相关问题

因为考虑到截图模式的时候  一般只能显示一个窗体  所以就考虑使用单例模式  在screenbody窗体中实现以下代码

1:创建单例 

?
1
private static screenbody screenbody=null;

2:私有化构造函数

?
1
2
3
4
private screenbody()
{
initializecomponent();
}

3:创建静态方法

?
1
2
3
4
5
6
7
8
private static screenbody getsingle()
{
if(screenbody==null)
{
screenbody=new screenbody();
}
return screenbody;
}

进一步讨论一下在main窗体中的调用  main中添加了一个button 命名为btncutter 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

声明全局变量

?
1
2
3
4
5
private bool catchstart;//判断鼠标是否按下
private bool catchfinished;//判断矩形是否绘制完成
private point downpoint;//鼠标按下的点
private image basemap;//最基本的图片
private rectangle catchrectangle; 

必须要实现的那几个事件

鼠标按下mousedown

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/// <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;
   }
  }
 }

鼠标双击

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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();
  }
 }

鼠标右键 退出截图

?
1
2
3
4
5
6
7
8
9
10
11
12
13
/// <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窗体中

声明枚举

?
1
2
3
4
5
6
7
8
9
[flagsattribute]
 public enum keymodifiers
 {
  none = 0,
  alt = 1,
  ctrl = 2,
  shift = 4,
  windowskey = 8
 }

然后在类中编辑一下代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//在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
 );

再接着

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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截图功能及相关问题C#实现QQ截图功能及相关问题

这些问题  还有待解决!!!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://www.cnblogs.com/Audient/p/7684922.html

延伸 · 阅读

精彩推荐
  • C#VS2012 程序打包部署图文详解

    VS2012 程序打包部署图文详解

    VS2012虽然没有集成打包工具,但它为我们提供了下载的端口,需要我们手动安装一个插件InstallShield。网上有很多第三方的打包工具,但为什么偏要使用微软...

    张信秀7712021-12-15
  • C#深入理解C#的数组

    深入理解C#的数组

    本篇文章主要介绍了C#的数组,数组是一种数据结构,详细的介绍了数组的声明和访问等,有兴趣的可以了解一下。...

    佳园9492021-12-10
  • C#三十分钟快速掌握C# 6.0知识点

    三十分钟快速掌握C# 6.0知识点

    这篇文章主要介绍了C# 6.0的相关知识点,文中介绍的非常详细,通过这篇文字可以让大家在三十分钟内快速的掌握C# 6.0,需要的朋友可以参考借鉴,下面来...

    雨夜潇湘8272021-12-28
  • C#利用C#实现网络爬虫

    利用C#实现网络爬虫

    这篇文章主要介绍了利用C#实现网络爬虫,完整的介绍了C#实现网络爬虫详细过程,感兴趣的小伙伴们可以参考一下...

    C#教程网11852021-11-16
  • C#SQLite在C#中的安装与操作技巧

    SQLite在C#中的安装与操作技巧

    SQLite,是一款轻型的数据库,用于本地的数据储存。其优点有很多,下面通过本文给大家介绍SQLite在C#中的安装与操作技巧,感兴趣的的朋友参考下吧...

    蓝曈魅11162022-01-20
  • C#C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    这篇文章主要介绍了C#设计模式之Strategy策略模式解决007大破密码危机问题,简单描述了策略模式的定义并结合加密解密算法实例分析了C#策略模式的具体使用...

    GhostRider10972022-01-21
  • C#如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    这篇文章主要给大家介绍了关于如何使用C#将Tensorflow训练的.pb文件用在生产环境的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴...

    bbird201811792022-03-05
  • C#C#微信公众号与订阅号接口开发示例代码

    C#微信公众号与订阅号接口开发示例代码

    这篇文章主要介绍了C#微信公众号与订阅号接口开发示例代码,结合实例形式简单分析了C#针对微信接口的调用与处理技巧,需要的朋友可以参考下...

    smartsmile20127762021-11-25