捕获一块屏幕并放入PictureBox中

本文关键字:PictureBox 屏幕 一块 | 更新日期: 2023-09-27 18:19:00

我正在使用c#开发一个工具,用于捕获屏幕的一部分并将其放入PicBox中,我已经能够获得屏幕截图,但我在一点上遇到了麻烦。我拍摄的镜头是从屏幕的开始拍摄的,我想要给出镜头应该开始的坐标(X,Y)。这是我的代码,有什么建议吗?

#region DLLIMPORTS
    enum RasterOperation : uint { SRC_COPY = 0x00CC0020 }
    [DllImport("coredll.dll")]
    static extern int BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, RasterOperation rasterOperation);
    [DllImport("coredll.dll")]
    private static extern IntPtr GetDC(IntPtr hwnd);
    [DllImport("coredll.dll")]
    private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
    #endregion
    public PrtScreenFrm()
    {
        InitializeComponent();
    }
    private void MakeLayout()
    {
        this.imageOriginalPicBox.Image = PrtScreenProjectCF.Properties.Resources.testImage;
        this.imageOriginalPicBox.SizeMode = PictureBoxSizeMode.StretchImage;
    }
    private void PrtScreenFrm_Load(object sender, EventArgs e)
    {
        this.MakeLayout();
    }
    private void TakeScreenShot(Point _start, Point _end)
    {
        Rectangle boundsOfShot = new Rectangle((int)_start.X, (int)_start.Y, (int)(_end.X - _start.X), (int)(_end.Y - _start.Y));
        IntPtr hdc = GetDC(IntPtr.Zero);
        Bitmap shotTook = new Bitmap(boundsOfShot.Width, boundsOfShot.Height, PixelFormat.Format16bppRgb565);
        using (Graphics draw = Graphics.FromImage(shotTook))
        {
            IntPtr dstHdc = draw.GetHdc();
            BitBlt(dstHdc, 0, 0, boundsOfShot.Width, boundsOfShot.Height, hdc, 0, 0,
            RasterOperation.SRC_COPY);
            draw.ReleaseHdc(dstHdc);
        }
        imagePrintedPicBox.Image = shotTook;
        imagePrintedPicBox.SizeMode = PictureBoxSizeMode.StretchImage;
        ReleaseDC(IntPtr.Zero, hdc);
    }
    private void takeShotMenuItem_Click(object sender, EventArgs e)
    {
        Point start = new Point(3, 3);    //here I am forcing the rectangle
        Point end = new Point(237, 133);  //to start where the picBox starts 
        TakeScreenShot(start, end);       //but it doesn't work
    }

非常感谢,我可能错过了一些愚蠢的东西,请给我一个灯

捕获一块屏幕并放入PictureBox中

问题是您的BitBlt指定(0,0)作为源X-Y位置。修改这一行:

BitBlt(dstHdc, 0, 0, boundsOfShot.Width, boundsOfShot.Height, hdc, 
       0, 0, RasterOperation.SRC_COPY);

BitBlt(dstHdc, 0, 0, boundsOfShot.Width, boundsOfShot.Height, hdc, 
       _start.X, _start.Y, RasterOperation.SRC_COPY);

修复了代码中的问题。

如果您需要一个控件的屏幕位置,它与Location属性不同,您可以使用:

Point _start = this.imageOriginalPicBox.PointToScreen(this.imageOriginalPicBox.Location);

上面的解决方案适用于紧凑的框架,但如果你使用完整的框架,它就有点过于复杂了。为了完整起见,这里有两种更好的方法。

正如Yorye Nathan在评论中指出的,更简单的方法是使用Graphics类的CopyFromScreen方法。这将删除所有的p/invoke,并将捕获代码减少为:

Rectangle boundsOfShot = new Rectangle(_start.X, _start.Y,
                                       _end.X - _start.X, _end.Y - _start.Y);
Bitmap shotTook = new Bitmap(boundsOfShot.Width, boundsOfShot.Height,
                             PixelFormat.Format16bppRgb565);
using (Graphics draw = Graphics.FromImage(shotTook))
{
    draw.CopyFromScreen(_start, new Point(0, 0), boundsOfShot.Size);
}

或者,如果您试图捕获您自己的控件之一的位图:

Bitmap b = new Bitmap(this.imageOriginalPicBox.Width, this.imageOriginalPicBox.Height);
this.imageOriginalPicBox.DrawToBitmap(b, 
      new Rectangle(new Point(0, 0), this.imageOriginalPicBox.Size));    

我明白了,b的答案几乎是正确的,问题是我必须使用他所说的加上使用。pointtoscreen (Point.Empty),同时将点传递给构造函数。所以,不是:

private void takeShotMenuItem_Click(object sender, EventArgs e)
{
    Point start = new Point(3, 3);   
    Point end = new Point(237, 133);  
    TakeScreenShot(start, end);       
}

我需要调用这个方法:

private void takeShotMenuItem_Click(object sender, EventArgs e)
    {
        Point start = imageOriginalPicBox.PointToScreen(Point.Empty);
        Point end = new Point(imageOriginalPicBox.PointToScreen(Point.Empty).X + imageOriginalPicBox.Width, imageOriginalPicBox.PointToScreen(Point.Empty).Y + imageOriginalPicBox.Height);
        TakeScreenShot(start, end);
    }

现在它工作得很好。谢谢你们的帮助。