2017-10-27 5 views
0

화면의 일부를 캡처하여 확대/축소하는 화면 확대/축소 기능을 만들고 싶습니다. 아래 코드는 이제 화면을 캡처하여 PictureBox에서 재생할 수 있습니다. 그러나 나는 프로그램을 여는 동안 내 기억이 계속 자라나는이 문제를 안고있다. 나는 공개되지 않은 자원이 있어야한다고 나는 그것을 풀어 놓는 방법을 모른다.PictureBox 리소스 릴리스

저는 미디어 플레이어처럼 보이게 만들고 있지만 비디오를 재생하는 대신 현재 화면의 일부를 재생합니다.

public partial class Form1 : Form 
{ 

    PictureBox picBox; 
    Bitmap bit; 
    Graphics g; 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     picBox = pictureBox; 
    } 

    private void CopyScreen() 
    { 

     bit = new Bitmap(this.Width, this.Height); 
     g = Graphics.FromImage(bit as Image); 

     Point upperLeftSource = new Point(
      Screen.PrimaryScreen.Bounds.Width/2 - this.Width/2, 
      Screen.PrimaryScreen.Bounds.Height/2 - this.Height/2); 

     g.CopyFromScreen(upperLeftSource, new Point(0, 0), bit.Size); 

     picBox.Image = Image.FromHbitmap(bit.GetHbitmap()); 

     bit.Dispose(); 
     g.Dispose(); 
    } 

    private void timer_Tick(object sender, EventArgs e) 
    { 
     CopyScreen(); 
    } 
+0

https://stackoverflow.com/questions/1831732/c-sharp-picturebox-memory-releasing-problem –

+0

@mjwills에서 작동합니다 ... 메모리가 계속 성장합니다. –

+0

@mjwills 타이머 간격을 설정했습니다. ~ 20 정도로 초당 10MB와 같이 메모리가 매우 빠르게 증가합니다. –

답변

1

문제는 GetHbitmap의 사용, 당신은 PictureBox에 새 Image를 할당 할 때 이전 Image 폐기되지 않는다는 사실이다.

https://msdn.microsoft.com/en-us/library/1dz311e4(v=vs.110).aspx 상태 :

당신은 GDI 비트 맵 객체에 의해 사용되는 메모리를 해제하기 위해 GDI DeleteObject 매크로 메서드를 호출 할 책임이 있습니다. (당신이하고 있지 않습니다)

(그리고 Dispose 이전 Image에)에 GetHbitmap 전화의 필요성을 피하기 위해 코드를 변경하는 것이 좋습니다 :

private void CopyScreen() 
{ 
    bit = new Bitmap(this.Width, this.Height); 
    g = Graphics.FromImage(bit); 

    Point upperLeftSource = new Point(
     Screen.PrimaryScreen.Bounds.Width/2 - this.Width/2, 
     Screen.PrimaryScreen.Bounds.Height/2 - this.Height/2); 

    g.CopyFromScreen(upperLeftSource, new Point(0, 0), bit.Size); 

    var oldImage = picBox.Image; 
    picBox.Image = bit; 
    oldImage?.Dispose(); 

    g.Dispose(); 
} 

을 단순화하기 위해 클래스 상단에서 선언 한 입력란을 삭제하고 다음을 사용하십시오.

private void CopyScreen() 
{ 
    var picBox = pictureBox; 
    var bit = new Bitmap(this.Width, this.Height); 

    using (var g = Graphics.FromImage(bit)) 
    { 
     var upperLeftSource = new Point(
      Screen.PrimaryScreen.Bounds.Width/2 - this.Width/2, 
      Screen.PrimaryScreen.Bounds.Height/2 - this.Height/2); 

     g.CopyFromScreen(upperLeftSource, new Point(0, 0), bit.Size); 

     var oldImage = picBox.Image; 
     picBox.Image = bit; 
     oldImage?.Dispose(); 
    } 
} 
+1

시간을내어 도와 주셔서 감사합니다! 여러분과 여러분 모두가 기여하고있는 사람들은 Stack Overflow를 프로그래머가 질문 할 수있는 최고의 장소로 만듭니다! 나는 너를 존경하고 내가 할 수있는 한 다른 사람들을 돕기 위해 최선을 다할 것이다. 가난한 영어에 대해 미안해. –