답변

17

GetDesktopWindow() 함수를 시도했지만 제대로 작동하지 않습니다.

물론 아닙니다.

GetDesktopWindow 함수는 핸들을 바탕 화면에 반환합니다. 창문 이미지를 캡처하는 것과 아무런 관련이 없습니다.

게다가 데스크톱 창과 "전체 화면"은 다릅니다. 특히 데스크톱 창을 참조합니다. 자세한 내용 및이 함수에서 반환 한 핸들을 악용 할 때 잘못 될 수있는 내용은 this article을 참조하십시오.

저는 각 출력에 대해 1280x1024의 4 개의 출력 (모니터)이있는 시스템으로 작업하고 있습니다. 전체 데스크톱에서 스크린 샷이 필요하고 열려있는 모든 응용 프로그램이 필요합니다.

Graphics.CopyFromScreen 메서드를 사용하면 .NET Framework에서 비교적 간단합니다. P/Invoke를 할 필요가 없습니다!

이 경우 유일한 트릭은 적절한 치수를 전달하는 것입니다. 모니터가 4 개인 경우 기본 화면의 크기 만 전달하면 작동하지 않습니다. 모든 모니터가 포함 된 전체 가상 화면의 크기를 전달해야합니다. 가상 화면의 경계를 반환하는 SystemInformation.VirtualScreen 속성을 쿼리하여이를 검색합니다. 문서에서 알 수 있듯이 다중 모니터 시스템의 전체 데스크탑 경계입니다.

샘플 코드 :

// Determine the size of the "virtual screen", which includes all monitors. 
int screenLeft = SystemInformation.VirtualScreen.Left; 
int screenTop = SystemInformation.VirtualScreen.Top; 
int screenWidth = SystemInformation.VirtualScreen.Width; 
int screenHeight = SystemInformation.VirtualScreen.Height; 

// Create a bitmap of the appropriate size to receive the screenshot. 
using (Bitmap bmp = new Bitmap(screenWidth, screenHeight)) 
{ 
    // Draw the screenshot into our bitmap. 
    using (Graphics g = Graphics.FromImage(bmp)) 
    { 
     g.CopyFromScreen(screenLeft, screenTop, 0, 0, bmp.Size); 
    } 

    // Do something with the Bitmap here, like save it to a file: 
    bmp.Save(savePath, ImageFormat.Jpeg); 
} 

편집 :

주 스레드가 아닌 스레드에서 WPF 응용 프로그램과 솔루션을 확인하십시오. 나는 그것을 시험해 보았다. 그것은 작동하지 않습니다!

흠, 질문에 WPF 태그가 표시되지 않았거나 본문 어디에서나 언급되었습니다.

아무리 그래도. 적절한 참조를 추가하고 선언을 사용하는 한 내가 게시 한 코드는 WPF 응용 프로그램에서 올바르게 작동합니다. System.Windows.FormsSystem.Drawing이 필요합니다. 이 WinForms 어셈블리에 대한 종속성을 필요로하지 않는 더 많은 WPF-esque 방법이있을 수 있지만 그게 무엇인지는 알 수 없습니다.

다른 스레드에서도 작동합니다. UI 스레드가 필요한 것은 여기에 없습니다.

네, 테스트 해 보았습니다.여기에 내 전체 테스트 코드입니다 :

using System.Windows; 
using System.Windows.Forms; // also requires a reference to this assembly 
using System.Drawing;   // also requires a reference to this assembly 
using System.Drawing.Imaging; 
using System.Threading; 

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     // Create a new thread for demonstration purposes. 
     Thread thread = new Thread(() => 
     { 
     // Determine the size of the "virtual screen", which includes all monitors. 
     int screenLeft = SystemInformation.VirtualScreen.Left; 
    int screenTop = SystemInformation.VirtualScreen.Top; 
    int screenWidth = SystemInformation.VirtualScreen.Width; 
    int screenHeight = SystemInformation.VirtualScreen.Height; 

     // Create a bitmap of the appropriate size to receive the screenshot. 
     using (Bitmap bmp = new Bitmap(screenWidth, screenHeight)) 
     { 
      // Draw the screenshot into our bitmap. 
      using (Graphics g = Graphics.FromImage(bmp)) 
      { 
       g.CopyFromScreen(screenLeft, screenTop, 0, 0, bmp.Size); 
      } 

      // Do something with the Bitmap here, like save it to a file: 
      bmp.Save("G:\\TestImage.jpg", ImageFormat.Jpeg); 
     } 
     }); 
     thread.SetApartmentState(ApartmentState.STA); 
     thread.Start(); 
    } 
} 
+0

이 기능을 시도해 본 결과 이렇게 많은 해결책을 찾았습니다. 그러나 그들 모두는 나의 형태의 사진을 찍지 않고 단지 바탕 화면에서 다른 형태를 취한다 !! 내 wpf 응용 프로그램 및 내 funtion 내 주 스레드가 스레드에서 실행 원인이 될 수 있습니다. – mat

+0

주 스레드가 아닌 스레드에서 wpf 응용 프로그램으로 솔루션을 확인하십시오. 나는 그것을 시험해 보았다. 그것은 작동하지 않습니다! – mat

+0

@ user2251498 나는 그랬다. 나는 그것을 깨뜨릴 수 없다. 내 모니터 4 개가 모두 포함 된 그림이 저장되었습니다. (네, 그냥 내 dev에 machine에 4가 있습니다.) 내가 사용한 샘플 코드를 게시했습니다. 이 방법이 효과가 있습니까? –