2015-10-24 93 views
2

我使用C#開發一個捕獲一塊屏幕並將其放入PicBox的工具,我已經能夠獲取屏幕截圖,但我在某一點上遇到了麻煩。我拍攝的照片是從屏幕開始拍攝的,我想給出拍攝開始位置的座標(X,Y)。 這是我的代碼,任何sugestions?捕獲一塊屏幕並放入PictureBox

#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 

    } 

非常感謝,我可能錯過了一些愚蠢的東西,請給我一個亮點。

+0

'CopyFromScreen'是'Graphics'的一種方法,更易於使用。 'nXDest'和'nYDest'實際上應該是0,0,以將複製區域放在目標圖像'shotTook'的角落。它是'nXSrc'和'nYSrc',它控制你想要捕獲區域開始的屏幕的位置。 – SimpleVar

+0

當你打電話給'BitBlt' – SimpleVar

+0

@YoryeNathan時,你實際上會把0放到所有這些參數中。「我試着用」.CopyFromScreen()「,但我不知道它爲什麼不被識別。我認爲這是因爲它是緊湊的框架(可能)。 –

回答

4

問題是您的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 /調用,並減少了捕捉代碼:

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));  
+0

是的,那是我在開始的想法,但我試過了,結果是一樣的。也許我沒有解釋清楚我的問題,問題是矩形從屏幕上獲得點(0,0),我想獲取ImageOriginalPicBox原點位置。 無論如何,非常感謝,至少現在我知道我的想法沒有錯。 –

+0

謝謝,我很懶:3 – SimpleVar

+0

@Marcelo - 增加了一些關於如何在屏幕座標中獲取控件位置的信息。 – theB

1

我它的答案几乎是正確的,問題是我必須使用他所說的內容,並在將點傳遞給構造函數時使用.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); 

    } 

而現在它工作正常。謝謝你們的幫助。你使編碼變得更容易。