为什么这个C#方法不能产生正确的截图?

问题描述 投票:1回答:1

我想保存一个窗口的快照,标题以 - Scrivener 在一个PNG文件中。要做到这一点,我写了以下内容 办法 (基于 这个 答案)。)

        [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!");
        }

这段代码有几个问题。

首先,如果我要捕获的应用程序(Scrivener)在我调用这段代码时不在前景中,那么得到的截图就是空的。

第二,如果Scrivener窗口在前景中,我得到的是父窗口的截图(见下图)。

Screenshot of parent and child window

我需要如何修改我的代码才能使它达到以下效果

a. 即使窗口不在前景中也能工作,并且

b. 只捕捉字数窗口(不是它的父窗口)?

这里是 是代码。

c# winforms screenshot screen-capture
1个回答
8
投票

这就是你的问题。

scrivenerProcess.MainWindowHandle

从文档中可以看到:

主窗口是当前有焦点的进程所打开的窗口。

在你的截图中,你要找的窗口确实是 有焦点(它有一个白色背景和灰色文字,表示它是不活动的)。

不幸的是,如果要枚举一个进程的其他窗口,你需要使用PInvoke,因为它们并没有通过 Process 类。使用 EnumWindowsEnumChildWindows.

© www.soinside.com 2019 - 2024. All rights reserved.