Wiem, że mogę uzyskać zrzut ekranu całego ekranu za pomocą Graphics.CopyFromScreen(). Co jednak, jeśli chcę tylko zrzut ekranu konkretnej aplikacji?Uzyskaj zrzut ekranu określonej aplikacji
Odpowiedz
Oto niektóre kodu do należy zacząć:
public void CaptureApplication(string procName)
{
var proc = Process.GetProcessesByName(procName)[0];
var rect = new User32.Rect();
User32.GetWindowRect(proc.MainWindowHandle, ref rect);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bmp);
graphics.CopyFromScreen(rect.left, rect.top, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy);
bmp.Save("c:\\tmp\\test.png", ImageFormat.Png);
}
private class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
}
To działa, ale wymaga poprawy:
- Można użyć innego mechanizmu, aby uzyskać dojście procesu (lub przynajmniej zrobić niektóre kodowanie defensywne)
- Jeśli twoje docelowe okno nie jest na pierwszym planie, otrzymasz zrzut ekranu o odpowiednim rozmiarze/pozycji, ale wypełni go wszystko, co jest na pierwszym planie (prawdopodobnie chcesz ciągnąć podane okno na th e pierwszym planie)
- Prawdopodobnie chcesz zrobić coś innego niż tylko zapisać BMP do katalogu temp
Możesz zajrzeć do P/Invoking sposobem na zrobienie tego win32, an article to this effect ... sort.
Zasadniczo, przechodź przez problem z ustawieniem DC na bitmapę i wyślij WM_PRINT do okna aplikacji, o którym mowa. To dość paskudne, wszystko powiedziane, ale może pracować dla ciebie. Dostępne są następujące funkcje: SendMessage, GetDC, CreateCompatibleBitmp i SelectObject.
Nie mogę powiedzieć, że kiedykolwiek to zrobiłem, ale w ten sposób zaatakowałbym problem. (Cóż, prawdopodobnie zrobiłbym to w czystym C, ale wciąż, w przybliżeniu sposób, w jaki go zaatakowałem).
podstawie odpowiedzi Alconja jest, zrobiłem kilka ulepszeń:
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hWnd);
private const int SW_RESTORE = 9;
[DllImport("user32.dll")]
private static extern IntPtr ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
public Bitmap CaptureApplication(string procName)
{
Process proc;
// Cater for cases when the process can't be located.
try
{
proc = Process.GetProcessesByName(procName)[0];
}
catch (IndexOutOfRangeException e)
{
return null;
}
// You need to focus on the application
SetForegroundWindow(proc.MainWindowHandle);
ShowWindow(proc.MainWindowHandle, SW_RESTORE);
// You need some amount of delay, but 1 second may be overkill
Thread.Sleep(1000);
Rect rect = new Rect();
IntPtr error = GetWindowRect(proc.MainWindowHandle, ref rect);
// sometimes it gives error.
while (error == (IntPtr)0)
{
error = GetWindowRect(proc.MainWindowHandle, ref rect);
}
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Graphics.FromImage(bmp).CopyFromScreen(rect.left,
rect.top,
0,
0,
new Size(width, height),
CopyPixelOperation.SourceCopy);
return bmp;
}
po przejrzeniu tego zauważyłem, że jeśli proces zakończy się podczas 'Thread.Sleep (1000); 'będziesz miał nieskończoną pętlę. –
@NicolasTyler ma rację. Aby wyjaśnić, problem polega na tym, że wywoływanie 'GetWindowRect' z nieistniejącym już HWND zawsze zwróci zero, co oznacza, że pętla' while' w tej odpowiedzi nigdy nie wyjdzie i po prostu wypali procesor na zawsze, co jest dość poważnym błędem. Ale poza tym myślę, że ta odpowiedź jest eleganckim rozwiązaniem. Może ograniczać się do ustalonej liczby prób, a może trochę spać. Lub nie spróbuj ponownie w tej metodzie. –
Ta odpowiedź nie powoduje również usunięcia obiektu 'Graphics'. –
PrintWindow win32 API przechwytywania okien bitmapy nawet jeśli okno jest przykryte przez inne okna lub, jeśli jest wyłączony ekran:
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);
public static Bitmap PrintWindow(IntPtr hwnd)
{
RECT rc;
GetWindowRect(hwnd, out rc);
Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
PrintWindow(hwnd, hdcBitmap, 0);
gfxBmp.ReleaseHdc(hdcBitmap);
gfxBmp.Dispose();
return bmp;
}
odniesienie do rect powyżej mogą być Reso lved z następujących klas:
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
private int _Left;
private int _Top;
private int _Right;
private int _Bottom;
public RECT(RECT Rectangle) : this(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom)
{
}
public RECT(int Left, int Top, int Right, int Bottom)
{
_Left = Left;
_Top = Top;
_Right = Right;
_Bottom = Bottom;
}
public int X {
get { return _Left; }
set { _Left = value; }
}
public int Y {
get { return _Top; }
set { _Top = value; }
}
public int Left {
get { return _Left; }
set { _Left = value; }
}
public int Top {
get { return _Top; }
set { _Top = value; }
}
public int Right {
get { return _Right; }
set { _Right = value; }
}
public int Bottom {
get { return _Bottom; }
set { _Bottom = value; }
}
public int Height {
get { return _Bottom - _Top; }
set { _Bottom = value + _Top; }
}
public int Width {
get { return _Right - _Left; }
set { _Right = value + _Left; }
}
public Point Location {
get { return new Point(Left, Top); }
set {
_Left = value.X;
_Top = value.Y;
}
}
public Size Size {
get { return new Size(Width, Height); }
set {
_Right = value.Width + _Left;
_Bottom = value.Height + _Top;
}
}
public static implicit operator Rectangle(RECT Rectangle)
{
return new Rectangle(Rectangle.Left, Rectangle.Top, Rectangle.Width, Rectangle.Height);
}
public static implicit operator RECT(Rectangle Rectangle)
{
return new RECT(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom);
}
public static bool operator ==(RECT Rectangle1, RECT Rectangle2)
{
return Rectangle1.Equals(Rectangle2);
}
public static bool operator !=(RECT Rectangle1, RECT Rectangle2)
{
return !Rectangle1.Equals(Rectangle2);
}
public override string ToString()
{
return "{Left: " + _Left + "; " + "Top: " + _Top + "; Right: " + _Right + "; Bottom: " + _Bottom + "}";
}
public override int GetHashCode()
{
return ToString().GetHashCode();
}
public bool Equals(RECT Rectangle)
{
return Rectangle.Left == _Left && Rectangle.Top == _Top && Rectangle.Right == _Right && Rectangle.Bottom == _Bottom;
}
public override bool Equals(object Object)
{
if (Object is RECT) {
return Equals((RECT)Object);
} else if (Object is Rectangle) {
return Equals(new RECT((Rectangle)Object));
}
return false;
}
}
Świetne rozwiązanie. Chcę tylko zwrócić uwagę, że czasami PixelFormat.Format32bppArgb daje białe artefakty. W takim przypadku po prostu spróbuj użyć innego formatu, takiego jak PixelFormat.Format24bppRgb – Dave
nie, jeśli jest on zminimalizowany, ale powoduje, że okno, na które celujesz, migocze, gdy używasz PrintWindow() –
jak korzystać z tej metody? PrintWindow ("co tu przekazać") –
- 1. Uzyskaj zrzut ekranu kontrolki przeglądarki?
- 2. Brakujący zrzut ekranu aplikacji na iOS
- 3. Jak programować zrzut ekranu?
- 4. Zrzut ekranu w Haskell?
- 5. jak zrobić zrzut ekranu?
- 6. Android wykonuje zrzut ekranu
- 7. Opóźnienie zrzut ekranu iOS
- 8. Zrzut ekranu pokazuje czarny
- 9. Jak zrobić zrzut ekranu z części UIView?
- 10. iPad 3 powolny zrzut ekranu
- 11. Zrzut ekranu Firebase Query zero?
- 12. Zrzut ekranu ignoruje niektóre okna
- 13. Zrzut ekranu z kamery internetowej
- 14. Zrzut ekranu okna z pytonem:
- 15. Biorąc zrzut ekranu z jednej aplikacji w widoku z JavaScript
- 16. Zrzut ekranu z zawartości OpenGL ES dla aplikacji Paint
- 17. Zrzut ekranu z całego ekranu przy użyciu html5/javascript?
- 18. Zrzut ekranu Circumvent dla iOS 4
- 19. Zrzut ekranu iOS SDWebage w UITableViewCell
- 20. Zrzut ekranu z animacją rdzenia na iPadzie
- 21. Zrzut ekranu panelu z otwartymi comboboxami
- 22. programowalny zrzut ekranu przedstawiający fałszywego sąsiada
- 23. Zrzut ekranu Pythona 2+ monitorów (Windows)
- 24. Tworzenie cały zrzut ekranu strony używając QWebPage
- 25. Jak wziąć zrzut ekranu Qt/QML
- 26. Jak programowo wykonać zrzut ekranu (Swift, SpriteKit)
- 27. Zyskaj zrzut ekranu na Windowsie z Pythonem?
- 28. Zrzut ekranu procesu w ramach usługi Windows
- 29. Zapisz pełny zrzut ekranu włączając sztaby
- 30. C#: jak zrobić zrzut części ekranu
to nie przyniesie okno dla wybranego procesu na pierwszy plan w win7, więc dostaniesz zrzut ekranu z aktywnym oknie – greenfeet
@alconja użyłem kodu, aby zrobić zdjęcie z notatnika., ale zrobiła migawkę wizualnego studia, które było aktywnym oknem. Czy możemy użyć tego do zrobienia zdjęcia żadnego aktywnego okna? –
@FastSnail - Zamierzałem zasugerować, aby wypróbować inną odpowiedź, ale widzę z komentarzy, że to też nie działa ... Inną opcją może być próba znalezienia metody pinvoke, która ściąga docelową aplikację/okno do pierwszy plan na pierwszym planie. Na przykład [SwitchToThisWindow] (http://www.pinvoke.net/default.aspx/user32.switchtothiswindow), może ... – Alconja