加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 05:47:59 所属栏目:百科 来源:网络整理
导读:对于QQ截图,肯定是早就有认识了,只是一直没有去认真观察这个操作的具体实现步骤。所以这里将自己的记忆中的步骤简单的写一下: 习惯性用QQ或者TIM的人,一般是使用Ctrl+Alt+A 快捷键(热键)快速实现截图。 Ctrl+Alt+A 进入截图模式 鼠标左键点击 鼠标拖动

对于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,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,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,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  没有初始化值

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读