zoukankan      html  css  js  c++  java
  • 制作类似QQ截图软件

        最近在学习GDI,发现网上几篇文章在讲截图软件制作方法,学习了一点知识,在这里分享一下.  

        主要是调用WinAPI中的函数来完成主要功能.关键的函数有2个,一个是CreateDC,利用这个函数来创建一个显示器屏幕的DC(设备环境),作为源DC,再创建一个Image图像,通过这个图像的Graphics.GetHdc()方法来获取另一个DC,作为目标DC,这2个DC主要是留给第二个函数用的;第二个函数是BitBlt,这个函数将源DC上的像素扫描到目标DC中,在这里就是将显示器屏幕的像素扫描到我们创建的Image图片上.

        扫描完成之后得到的Image图像就是现在的全屏图,可以将图片保存或者拷贝待用.这就实现了全屏截图的功能.

        接下来是实现局部截图.首先将全屏截图Image通过画图画在Winform窗体上,这个可以用窗体的Paint事件来实现,当窗体改变的时候,Paint事件就会被触发.局部截图就是在已经画上了全屏图片的Winform窗体上面再画矩形,然后调用Graphics的方法DrawImage,将矩形区域的截图保存在开始创建的Image中,这样就得到了局部截图,可以将图片保存或者拷贝待用.

        功能基本上就实现了.需要注意的是,在窗体中画的矩形是可反转矩形,调用的是ControlPaint.DrawReversibleFrame()方法,这个方法需要执行2次才能画出矩形.

        主窗口代码:

        public partial class Form1 : Form
    {
    //*******************Global Varibles******************
    private Bitmap MyImage = null;
    private bool StartedCrop = false;

    Point StartPoint = new Point(0, 0);
    Rectangle SelectRect = new Rectangle();
    int DeltaX = 0;
    int DeltaY = 0;
    //****************************************************

    [DllImport("gdi32.dll", EntryPoint = "BitBlt")]
    public static extern int BitBlt(
    IntPtr hDestDC,
    int x,
    int y,
    int nWidth,
    int nHeight,
    IntPtr hSrcDC,
    int xSrc,
    int ySrc,
    System.Int32 dwRop
    );
    [DllImport("gdi32.dll", EntryPoint = "CreateDC")]
    public static extern IntPtr CreateDC(
    string lpDriverName,
    string lpDeviceName,
    string lpOutput,
    IntPtr lpInitData
    );

    public Form1()
    {
    InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    this.Visible = false;
    Thread.Sleep(100);
    IntPtr dc1 = CreateDC("DISPLAY", null, null, (IntPtr)null);
    Graphics g1 = Graphics.FromHdc(dc1);
    MyImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, g1);
    Graphics g2 = Graphics.FromImage(MyImage);
    //Visible = false;
    dc1 = g1.GetHdc();
    IntPtr dc2 = g2.GetHdc();
    BitBlt(dc2, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height,
    dc1, 0, 0, 13369376);

    g1.ReleaseHdc(dc1);
    g2.ReleaseHdc(dc2);
    this.Visible = true;
    this.SetBounds(0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
    this.Cursor = Cursors.Cross;
    }

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
    if (StartedCrop == false)
    {
    DeltaX = 0;
    DeltaY = 0;
    }
    StartedCrop = true;
    StartPoint = new Point(e.X,e.Y);
    SelectRect.Width = 0;
    SelectRect.Height = 0;
    SelectRect.X = e.X;
    SelectRect.Y = e.Y;
    Invalidate();
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
    Form thisform = (Form)sender;
    if (StartedCrop)
    {
    DeltaX = e.X - StartPoint.X;
    if (DeltaX < 0)
    DeltaX = 0;
    DeltaY = e.Y - StartPoint.Y;
    if (DeltaY < 0)
    DeltaY = 0;
    ControlPaint.DrawReversibleFrame(thisform.RectangleToScreen(SelectRect), Color.Black, FrameStyle.Dashed);
    SelectRect.Width = e.X - SelectRect.X;
    SelectRect.Height = e.Y - SelectRect.Y;
    ControlPaint.DrawReversibleFrame(thisform.RectangleToScreen(SelectRect), Color.Black, FrameStyle.Dashed);
    }
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
    if (DeltaX == 0 || DeltaY == 0)
    {
    return;
    }

    StartedCrop = false;
    SelectRect.X = e.X - StartPoint.X;
    SelectRect.Y = e.Y - StartPoint.Y;
    this.Cursor = Cursors.Cross;


    Bitmap theImage = new Bitmap(DeltaX, DeltaY);
    Graphics g = Graphics.FromImage(theImage);
    Rectangle destRect = new Rectangle(0, 0, DeltaX, DeltaY);
    g.DrawImage(MyImage, destRect, StartPoint.X, StartPoint.Y, theImage.Width, theImage.Height, GraphicsUnit.Pixel);
    MyImage = (Bitmap)theImage.Clone();
    this.SetBounds(0, 0, MyImage.Width, MyImage.Height);
    this.Visible = false;

    frmOptions optionsForm = new frmOptions();
    optionsForm.imageToSaveOrCopy = MyImage;
    optionsForm.ShowDialog();
    }

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
    if (MyImage != null)
    e.Graphics.DrawImage(MyImage, ClientRectangle, 0, 0, MyImage.Width, MyImage.Height, GraphicsUnit.Pixel);
    }

    private void Form1_Resize(object sender, EventArgs e)
    {
    Invalidate();
    }

    private void Form1_DoubleClick(object sender, EventArgs e)
    {
    Application.Exit();
    }
    }

        选项窗口代码(frmOptions)主要有2个按钮,用来保存或者拷贝截取的图片:

        public partial class frmOptions : Form
    {
    public Image imageToSaveOrCopy;

    public frmOptions()
    {
    InitializeComponent();
    }

    private void frmOptions_Load(object sender, EventArgs e)
    {

    }

    private void btnSave_Click(object sender, EventArgs e)
    {
    if (imageToSaveOrCopy == null) {
    MessageBox.Show("You have not choose the image! Please restart this program!");
    Application.Exit();
    }

    SaveFileDialog sfd = new SaveFileDialog();
    sfd.Filter = "*.jpg|*.jpg";
    sfd.AddExtension = true;
    sfd.FileName = "1.jpg";
    if (sfd.ShowDialog() == DialogResult.OK)
    {
    imageToSaveOrCopy.Save(sfd.FileName);
    }
    Application.Exit();
    }

    private void btnCopy_Click(object sender, EventArgs e)
    {
    if (imageToSaveOrCopy == null)
    {
    MessageBox.Show("You have not choose the image! Please restart this program!");
    Application.Exit();
    }
    try
    {
    Clipboard.SetImage(imageToSaveOrCopy);
    }
    catch (Exception ex)
    {
    MessageBox.Show("Copy to clipboard error:\r\n"+ex.Message);
    }
    Application.Exit();
    }
    }

        由于局部截图的时候需要在屏幕上面画图,而要想屏幕位置(Point)和我们主窗体的位置一一对应起来,就需要将主窗体最大化到全屏幕,为了效果好点,可以将
    窗体的BorderStyle属性设置为None.这样整个工作就完成了.

  • 相关阅读:
    JAVA 多态
    win10 快捷键
    MSTAR SETBOX 常用API
    MSTAR GUI
    APACHE2 服务器配置 (一)
    MSTAR SERVICE结构
    各个国家 不同字符集的unicode 编码范围
    PhpStorm中如何配置SVN,详细操作方法
    PHP/Javascript 数组定义 及JSON中的使用 ---OK
    The "Run One Program Only" Phenomenon
  • 原文地址:https://www.cnblogs.com/johnsmith/p/2309775.html
Copyright © 2011-2022 走看看