I want to save the snapshot of a window with the title ending in - Scrivener
in a PNG file. To do this, I wrote following method (based on this answer):
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
private void button1_Click(object sender, EventArgs e)
{
Process[] processes = Process.GetProcesses();
Process scrivenerProcess = null;
foreach (Process curProcess in processes)
{
Console.WriteLine("Name: " + curProcess.ProcessName + ", title: " + curProcess.MainWindowTitle);
if (curProcess.MainWindowTitle.EndsWith("- Scrivener"))
{
scrivenerProcess = curProcess;
break;
}
}
if (scrivenerProcess == null)
{
Console.WriteLine("Scrivener not found");
return;
}
var rect = new RECT();
GetWindowRect(new HandleRef(this, scrivenerProcess.MainWindowHandle), out rect);
int width = rect.Right - rect.Left;
int height = rect.Bottom - rect.Top;
var bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bmp);
graphics.CopyFromScreen(rect.Left, rect.Top, 0, 0, new System.Drawing.Size(width, height), CopyPixelOperation.SourceCopy);
bmp.Save("C:\\usr\\dp\\ref\\marcomm\\2020_04_22_wordCounter\\2020-04-24-TestScreenshot.png", ImageFormat.Png);
Console.WriteLine("Heyo!");
}
There are several problems with this code:
First, if the application I want to capture (Scrivener) is not in the foreground while I'm calling that code, the resulting screenshot is empty.
Second, if the Scrivener window is in the foreground, I get the screenshot of the parent window (see below).
How do I need to change my code in order for it to
a. work even when the window is not in foreground and
b. only capture the word count window (not its parent)?
Here is the code.
Here's your problem:
scrivenerProcess.MainWindowHandle
From the documentation:
The main window is the window opened by the process that currently has the focus
In your screenshot, the window you're after does not have Focus (it has a white background with grey text, indicating it's inactive).
Unfortunately, to enumerate a process' other windows you need to use P/Invoke as they aren't exposed via the Process
class. Use EnumWindows
or EnumChildWindows
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With