• 保存Graphics对象到Bitmap对象


        最近在尝试为软件增加截取屏幕的功能,为此学习了System.Drawing命名空间的Graphics、Image、Bitmap等GDI+类,这些类都很方便使用。但是它们大多都是对原有GDI API的封装,也增加了一些新的东西;不过封装得并不彻底,有些功能还是需要调用GDI API才能实现。我武断的认为Image、Bitmap、Metafile跟HBITMAP对应,Graphics跟HDC对应。

        在GDI+中,我们可以很方便的用Graphics.FromImage方法来操作Image中的内容,并将其保存回图片文件。那么,我们怎么才能保存Graphics到图片文件呢?创建一个Bitmap对象,复制Graphics g1的内容到Bitmap的Graphics g2,然后保存Bitmap对象到文件。复制过程我们必须通过PINVOKE调用BitBlt函数来实现。下面是该函数的声明:

    [DllImport("gdi32.dll", CharSet=CharSet.Auto, SetLastError=true, ExactSpelling=true)]
    public static extern int BitBlt(HandleRef hDC, int x, int y, int nWidth, int nHeight, HandleRef hSrcDC, int xSrc, int ySrc, int dwRop);
    参数中的各种DC可以用Graphics.GetHdc得到;最后一个参数光栅操作码很多,截取屏幕用的SRCCOPY值是0xcc0020,完整的光栅操作码可以查看MSDN的“Ternary Raster Operations”部分。

    示例代码如下:

    //这里假设要保存一个窗体的内容

    int width=800;     //获取宽度

    int height=600;     //获取高度

    const int SRCCOPY=0xcc0020;     //复制图块的光栅操作码

    Bitmap bmSave=new Bitmap(width,height);     //用于保存图片的位图对象

    Graphics gSave=Graphics.FromImage(bmSave);     //创建该位图的Graphics对象

    HandleRef hDcSave=new HandleRef(null,gSave.GetHdc());     //得到句柄

    Graphics gSrc=formMain.CreateGraphics();     //创建窗体的Graphics对象

    HandleRef hDcSrc=new HandleRef(null,gSrc.GetHdc());

    BitBlt(hDcSave,0,0,width,height,hDcSrc,0,0,SRCCOPY);

    gSrc.ReleaseHdc();

    gSave.ReleaseHdc();

    bmSave.Save(@"C:\test.bmp");

    gSrc.Dispose();

    gSave.Dispose();

    bmSave.Dispose();

     关于Graphics.CopyFromScreen方法

         该方法在内部其实也使用BitBlt来进行图块复制,但是它只是固定的复制屏幕的内容,我们不能指定复制的源。

    如果您需要截取屏幕的内容,可以使用以下代码:

    int screenWidth=System.Windows.Forms.SystemInformation.VirtualScreen.Width;     //屏幕宽度

    int screenHeight=System.Windows.Forms.SystemInformation.VirtualScreen.Height;     //屏幕高度

    Bitmap bmSave=new Bitmap(screenWidth,screenHeight);

    Graphics g=Graphics.FromImage(bmSave);

    g.CopyFromScreen(0,0,0,0,new Size(screenWidth,screenHeight),CopyPixelOperation.SourceCopy);

    bmSave.Save(@"C:\test.bmp");

    g.Dispose();

    bmSave.Dispose();

    如果需要复制顶层窗体的可见部分,也可以使用Graphics.CopyFromScreen,但是需要用PointToScreen方法先得到屏幕坐标。

    如果需要复制任意的窗体或者控件,先用Control.Handle得到控件句柄,然后再用GetDC()函数得到HDC,再用BitBlt进行图块复制。

  • 相关阅读:
    .NET生成CSV文件
    Codeforces Round #552 (Div. 3) A题
    位运算介绍
    Codeforces Round #552 (Div. 3) F题
    POJ—1321(棋盘问题)
    Codeforces Round #552 (Div. 3) C题
    Codeforces Round #553 (Div. 2) A题
    Codeforces Round #553 (Div. 2) C题
    Codeforces Round #553 (Div. 2) B题
    Codeforces Round #552 (Div. 3) D题
  • 原文地址:https://www.cnblogs.com/xrwang/p/1273685.html
Copyright © 2020-2023  润新知