滚动截图转载

C# 截取控件图,有滚动截图功能
public class ControlImage
{
#region API
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SCROLLINFO
{
    public uint cbSize;
    public uint fMask;
    public int nMin;
    public int nMax;
    public uint nPage;
    public int nPos;
    public int nTrackPos;
}

public enum ScrollBarInfoFlags
{
    SIF_RANGE = 0x0001,
    SIF_PAGE = 0x0002,
    SIF_POS = 0x0004,
    SIF_DISABLENOSCROLL = 0x0008,
    SIF_TRACKPOS = 0x0010,
    SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
}

public enum ScrollBarRequests
{
    SB_LINEUP = 0,
    SB_LINELEFT = 0,
    SB_LINEDOWN = 1,
    SB_LINERIGHT = 1,
    SB_PAGEUP = 2,
    SB_PAGELEFT = 2,
    SB_PAGEDOWN = 3,
    SB_PAGERIGHT = 3,
    SB_THUMBPOSITION = 4,
    SB_THUMBTRACK = 5,
    SB_TOP = 6,
    SB_LEFT = 6,
    SB_BOTTOM = 7,
    SB_RIGHT = 7,
    SB_ENDSCROLL = 8
}

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetScrollInfo(IntPtr hwnd, int bar, ref SCROLLINFO si);

[DllImport("user32")]
public static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool Rush);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(HandleRef hWnd, int msg, IntPtr wParam, IntPtr lParam);

[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern bool BitBlt(HandleRef hDC, int x, int y, int nWidth, int nHeight, HandleRef hSrcDC, int xSrc, int ySrc, int dwRop);
#endregion

private ControlImage() { }

private static int verticalScrollBarWidth = SystemInformation.VerticalScrollBarWidth;
private static int horizontalScrollBarHeight = SystemInformation.HorizontalScrollBarHeight;

/// <summary>
/// 支持呈现到指定的位图。
/// </summary>
public static void DrawToBitmap(Control control, Bitmap bitmap, Rectangle targetBounds)
{
    if (bitmap == null)
    {
        throw new ArgumentNullException("bitmap");
    }
    if (((targetBounds.Width <= 0) || (targetBounds.Height <= 0)) || ((targetBounds.X < 0) || (targetBounds.Y < 0)))
    {
        throw new ArgumentException("targetBounds");
    }
    Bitmap image = new Bitmap(control.Width, control.Height, bitmap.PixelFormat);
    using (Graphics graphics = Graphics.FromImage(image))
    {
        IntPtr hdc = graphics.GetHdc();
        SendMessage(new HandleRef(control, control.Handle), 0x317, hdc, (IntPtr)30);
        using (Graphics graphics2 = Graphics.FromImage(bitmap))
        {
            IntPtr handle = graphics2.GetHdc();
            BitBlt(new HandleRef(graphics2, handle), 0, 0, control.Width, control.Height, new HandleRef(graphics, hdc), targetBounds.X, targetBounds.Y, 0xcc0020);
            graphics2.ReleaseHdcInternal(handle);
        }
        graphics.ReleaseHdcInternal(hdc);
    }
}

/// <summary>
/// 获取图形 有滚动截图功能
/// </summary>
public static Bitmap GetImage(Control control)
{
    Point scrollMaxInfo = GetScrollPoint(control);
    Size controlMaxSize = GetControlSize(control, scrollMaxInfo);

    Bitmap bitmap = new Bitmap(controlMaxSize.Width, controlMaxSize.Height);
    if (scrollMaxInfo.IsEmpty)
    {
        DrawToBitmap(control, bitmap, new Rectangle(0, 0, control.Width, control.Height));
        return bitmap;
    }

    Graphics g = Graphics.FromImage(bitmap);
    Bitmap tempBitmap = new Bitmap(control.Width - verticalScrollBarWidth, control.Height - horizontalScrollBarHeight);

    int stepWidth = GetScrollNumber(control.Width - verticalScrollBarWidth, scrollMaxInfo.X);
    int stepHeight = GetScrollNumber(control.Height - horizontalScrollBarHeight, scrollMaxInfo.Y);
    int widthPos = 0;
    int heightPos = 0;
    MoveBar(0, 0, control);

    for (int i = 0; i < stepWidth; i++)
    {
        heightPos = 0;
        MoveBar(1, 0, control);
        for (int z = 0; z < stepHeight; z++)
        {
            control.DrawToBitmap(tempBitmap, new Rectangle(0, 0, control.Width - verticalScrollBarWidth, control.Height - horizontalScrollBarHeight));
            g.DrawImage(tempBitmap, widthPos, heightPos);
            MoveBar(1, control.Height - horizontalScrollBarHeight + heightPos, control);
            heightPos = GetScrollPoint(1, control);
        }
        MoveBar(0, control.Width - verticalScrollBarWidth + widthPos, control);
        widthPos = GetScrollPoint(0, control);
    }
    g.Dispose();
    tempBitmap.Dispose();
    return bitmap;
}

/// <summary>
/// 获取目前滚动条位置 
/// </summary>
/// <param name="bar"></param>
/// <param name="control"></param>
/// <returns></returns>
private static int GetScrollPoint(int bar, Control control)
{
    SCROLLINFO scrollInfo = new SCROLLINFO();
    scrollInfo.cbSize = (uint)Marshal.SizeOf(scrollInfo);
    scrollInfo.fMask = (uint)ScrollBarInfoFlags.SIF_ALL;
    GetScrollInfo(control.Handle, bar, ref scrollInfo);
    return scrollInfo.nPos;
}

/// <summary>
/// 获取循环几次获得图形 
/// </summary>
private static int GetScrollNumber(int controlNumber, int scrollMaxInfoNumber)
{
    return (int)Math.Ceiling(scrollMaxInfoNumber / (double)controlNumber) + 1;
}

/// <summary>
/// 获得控件不需要滚动条的宽和高(最终图形大小) 
/// </summary>
private static Size GetControlSize(Control control, Point scrollMaxInfo)
{
    return new Size(control.Size.Width + scrollMaxInfo.X - verticalScrollBarWidth,
        control.Size.Height + scrollMaxInfo.Y - horizontalScrollBarHeight);
}

/// <summary>
/// 获取控件滚动条数据 
/// </summary>
private static Point GetScrollPoint(Control control)
{
    verticalScrollBarWidth = SystemInformation.VerticalScrollBarWidth;
    horizontalScrollBarHeight = SystemInformation.HorizontalScrollBarHeight;

    Point maxScroll = new Point();
    SCROLLINFO scrollInfo = new SCROLLINFO();
    scrollInfo.cbSize = (uint)Marshal.SizeOf(scrollInfo);
    scrollInfo.fMask = (uint)ScrollBarInfoFlags.SIF_ALL;

    GetScrollInfo(control.Handle, 1, ref scrollInfo);
    if ((int)scrollInfo.nPage == 0)
    {
        maxScroll.Y = 0;
        verticalScrollBarWidth = 0;
    }
    else
    {
        maxScroll.Y = scrollInfo.nMax - (int)scrollInfo.nPage;
    }

    GetScrollInfo(control.Handle, 0, ref scrollInfo);
    if ((int)scrollInfo.nPage == 0)
    {
        maxScroll.X = 0;
        horizontalScrollBarHeight = 0;
    }
    else
    {
        maxScroll.X = scrollInfo.nMax - (int)scrollInfo.nPage;
    }
    return maxScroll;
}

/// <summary>
/// 移动控件滚动条位置 
/// </summary>
private static void MoveBar(int bar, int nPose, Control control)
{
    if (bar == 0)
    {
        SetScrollPos(control.Handle, 0, nPose, true);
        SendMessage(control.Handle, 0x0114, (int)ScrollBarRequests.SB_THUMBPOSITION, 0);
    }
    else
    {
        SetScrollPos(control.Handle, 1, nPose, true);
        SendMessage(control.Handle, 0x0115, (int)ScrollBarRequests.SB_THUMBPOSITION, 0);
    }
}
}
Last modification:May 6th, 2019 at 01:40 pm
如果觉得我的文章对你有用,请随意赞赏

One comment

  1. 罗锡卫

    我觉得最新版的qq里面的滚动截图要比其他的截图软件更方便。您可以参考一下

Leave a Comment