好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

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

原文链接:http://HdhCmsTestcnblogs测试数据/Audient/p/7684922.html

dy("nrwz");

查看更多关于C#实现QQ截图功能及相关问题的详细内容...

  阅读:45次