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);
        }
    }
}

posted @ 2011-08-09 10:45  梦想(胡大利)  阅读(1993)  评论(0编辑  收藏  举报