C# 屏幕截图中未捕获对话框和菜单更改

C# 屏幕截图中未捕获对话框和菜单更改,c#,.net,winforms,graphics,C#,.net,Winforms,Graphics,我正在构建一个WinForms应用程序,通过每500毫秒截图一次来记录外部进程的步骤。我正在使用以下代码: Bitmap bmp = new Bitmap(width, height,PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(bmp); g.CopyFromScreen(rect.left, rect.top, 0,

我正在构建一个WinForms应用程序,通过每500毫秒截图一次来记录外部进程的步骤。我正在使用以下代码:

Bitmap bmp = new Bitmap(width, height,PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(rect.left,
                 rect.top,
                 0,
                 0,
                 new Size(width, height),
                 CopyPixelOperation.SourceCopy);
代码工作正常,但唯一的问题是,当我从外部进程窗口打开对话框时(例如:在记事本中打开
另存为…
对话框),屏幕截图冻结到原始窗口,而不是显示对话框

我的理论是,由于我使用以下代码来检测应用程序是否失去焦点,然后恢复到上次保存的屏幕截图:

if (GetForegroundWindow() != proc.MainWindowHandle) //proc is just a process from system process list by Process.GetProcessesByName()
{
   return LastScreenShot;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetForegroundWindow();
但此代码仅用于向用户显示正在录制的应用程序,而不显示正在录制区域内拖动的任何其他应用程序或录制区域内的桌面部分。此外,当我单击菜单时,它有时会显示菜单冻结在褪色的位置,有时根本不显示,或者显示但导航高亮显示在屏幕截图中不可见

有什么办法可以解决这个问题吗

这里也有类似的问题 但这并不能解决我的问题,因为答案是使用相同的代码 我的应用程序并没有截取整个桌面的屏幕


除非你能掌握对话框窗口的句柄,并确定它是否是你所关心的句柄的子对象(不太可能),否则你基本上就必须使用它

您可以构建一个延迟,以便在对话框出现时允许在一段设定的时间内继续截图,希望控件在给定的时间段后返回到原始句柄,并且只有在该时间段后控件没有返回时才停止捕获过程

您可以使用以下内容获取窗口句柄的进程信息

。。。如果拥有的过程是相同的,那么应用程序可能仍然有焦点(除非发生了非常奇怪的事情)

但此代码对于仅向用户显示 正在录制而不是正在拖动的任何其他应用程序 在录制区域内或录制区域内的桌面部分 区域


我正在为儿童窗户安装把手,但问题是如何安装 将它们包含在主窗口的屏幕截图中

我认为在这种情况下,您唯一的选择是捕获两个屏幕(主窗口和对话框),并使用
BitBlt()
或类似的方法将它们组合起来

还要记住,对话框可以移动到主窗口区域之外,甚至可以移动到第二个屏幕。所以,即使你能在一次拍摄中捕捉到这两个镜头,那也可能不是你想要的。通过自己组合它们,您可以将对话框放回主屏幕的顶部

当然,您必须在窗口句柄(使用)上进行捕获,而不是在屏幕或桌面区域。有关如何执行此操作的一些示例,请参见和



这可能是对话框未被捕获的原因(即根本没有捕获),但即使您修复或删除了该对话框,也可能会在区域内拖动另一个窗口,即使对话框处于打开状态。

可能值得签出:。因此,也许您可以针对所有子窗口进行验证,而不是仅对proc进行验证。MainWindowHandle@Johan谢谢你的链接,但我已经读过了。我正在获取子窗口的句柄,但问题是如何将它们包含在主窗口的屏幕截图中?我也在验证,但是像OpenFileDialog和SaveFileDialog这样的对话框仍然没有出现在屏幕截图中。啊,好的。我的想法和你说的一样,你认为这可能是因为当主控点不是前台窗口时,你恢复到上次保存的屏幕截图。@Johan问题是,当我打开主菜单和对话框时,它们正在变成前台窗口。正如你说的,可能只是你的测试
GetForegroundWindow()!=无效的进程MainWindowHandle
。为什么不检查前台或模式窗口是否属于正在录制的进程?(您可以使用我这里的回答中的
GetModalWindow
)我尝试了这个
intactiveprocid,threadProcId;GetWindowThreadProcessId(proc.MainWindowHandle,out-activeProcId);GetWindowThreadProcessId(GetForegroundWindow(),OutThreadProcId);if(activeProcId==threadProcId)MessageBox.Show(“是,线程来自同一进程”)它适用于主窗口,但不适用于对话框。。。这意味着您可以在对话框中使用它。可能缺少某些设置或参数?请尝试以下操作。。。
if (GetForegroundWindow() != proc.MainWindowHandle)