我正在编写一个简单的Windows窗体实用程序来截取整个屏幕或活动窗口并保存文件。 winform有一个名为“Capture”的按钮,点击后会截取屏幕截图。
我的代码完全适用于整个屏幕,但无法找到活动窗口。
根据我当前的代码,如果我选择“活动窗口”,它最终会打印筛选应用程序本身,这不是我想要的。
这是我的代码(在Capture_Click方法下):
try
{
this.Hide();
bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
//bmpScreenshot = new Bitmap(this.Bounds.Width, this.Bounds.Height, PixelFormat.Format32bppArgb);
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
if (AltPrint.Checked)
{
gfxScreenshot.CopyFromScreen(this.Bounds.X, this.Bounds.Y, 0, 0, this.Bounds.Size, CopyPixelOperation.SourceCopy);
}
else
{
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
}
bmpScreenshot.Save(SaveLocation, ImageFormat.Png);
number++;
}
答案 0 :(得分:2)
在button_Click
方法中,为了捕获除捕获之外的窗口,我唯一可以看到的方法是使用user32
Windows API。
首先需要平台调用这样的方法:
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, GetWindowLongNIndex nIndex);
我建议www.pinvoke.net/了解更多相关信息。
以下是我自己的Window
课程(正在进行,但可以使用),欢迎您将其作为示例:http://pastebin.com/fj2tEaPY
那里有一些有用的属性:
AllWindows
TaskbarWindows
ForegroundWindow
您需要获取当前窗口的句柄(使用get ForegroundWindow
,然后使用Handle
属性),然后找到要捕获图像的窗口,可能使用代码与TaskbarWindows
中的类似。获得窗口后,您需要发送密钥Alt
+ PrtScn
(可能再次使用user32
API,但我不会进入。)然后使用静态{ {1}}属性,使用您在开始时保存的句柄将orignal窗口设置为forground。
答案 1 :(得分:1)
据我所知,您的代码使用自己的表单边界来捕获“活动”窗口。这可能不是你想要的。
如果您想使用鼠标“打印”一个窗口(而不是可能更容易实现的热键),您需要能够从您自己的表单中让用户指向另一个窗口进行捕获。这是一个描述如何做到这一点的想法:
您可能需要使用P / Invoke来获取有关桌面上所有顶级窗口的信息。
请注意,“鼠标捕获”与“屏幕捕获”非常不同。当应用程序“捕获鼠标”时,它将获得鼠标光标的所有权,并且即使将鼠标移动到应用程序窗口的边界之外也无法跟踪鼠标。
答案 2 :(得分:1)
您的评论似乎明白,一旦您的应用获得焦点(当您点击它时),另一个应用程序已经丢失并且不再“活跃”。
可能的替代方案:您的应用在获得焦点时会收到WM_SETFOCUS消息。该消息的wParam是一个句柄,可以处理刚刚放弃焦点的窗口 - 该窗口属于您要捕获的应用程序。
当然,该窗口只是一个子窗口或控件,但你可以找出哪个应用程序拥有该按钮。
答案 3 :(得分:1)
我最终采取了不同的路线。
我允许用户调整表单窗口的大小以准确覆盖他们需要截屏的区域,然后当他们单击按钮时,表单隐藏自身,截取其覆盖的区域并再次显示。与我最初的计划相反,我相信这会更有益,因为我的目标用户(我所参与的超频论坛的朋友)很少只截取一个窗口的屏幕截图。他们大多需要覆盖几个窗口(临时监控,时钟速度监控,稳定性测试等)。
感谢所有答案的人。他们肯定让我思考,让我意识到我的选择是什么。
如果其他人需要它,这是我用于仅捕获部分屏幕的按钮的代码:
try
{
this.Hide();
Thread.Sleep(250);
bmpScreenshot = new Bitmap(this.Bounds.Width, this.Bounds.Height, PixelFormat.Format32bppArgb);
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
gfxScreenshot.CopyFromScreen(this.Bounds.X, this.Bounds.Y, 0, 0, this.Bounds.Size, CopyPixelOperation.SourceCopy);
bmpScreenshot.Save(SaveLocation, ImageFormat.Png);
tbxStatus.AppendText(Environment.NewLine);
tbxStatus.AppendText(Environment.NewLine);
tbxStatus.AppendText("Screenshot saved at " + SaveLocation);
numSuffix++;
}
catch (Exception ex)
{
tbxStatus.AppendText(Environment.NewLine);
tbxStatus.AppendText(Environment.NewLine);
tbxStatus.AppendText("Unable to take screenshot. Exception: " + ex.ToString());
}
finally
{
this.Show();
}
答案 4 :(得分:0)
您需要借用商用屏幕捕获应用程序的设计,例如Psp。我认为您需要使用“热”键来触发活动窗口的捕获。而不是在Capture_Click事件上做它。这样,您可以隐藏应用程序的窗口,使其不会成为活动窗口。然后,当用户按下“热”键时,您可以捕获它。
答案 5 :(得分:0)
SendKeys怎么样?
Windows.Forms.SendKeys.Send("%{PRTSC}");
它会将当前选定的窗口复制到剪贴板对象中。
比打电话
BitmapSource image = Clipboard.GetImage();
你可以恢复你的形象