如何在没有非托管代码 user32.dll 的情况下捕获屏幕截图
How to capture screenshot without user32.dll which is unmanaged code
概览
我正在尝试捕获外部应用程序的屏幕截图并将图像加载到 .NET PictureBox。
user32.dll 非托管代码
有很多使用 user32.dll 的示例,我正在寻找不使用 user32.dll 文件的 .NET 答案。
应用 #1
我在下面提供了用于演示目的的示例代码。执行程序时,它会解析进程并将具有有效 window 标题的进程保存到 drop-down 列表中。
当您从 drop-down 列表中 select 应用程序名称并单击按钮时,它会尝试捕获屏幕截图应用程序并加载到 .NET PictureBox 中。
Form1.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
Dictionary<string, IntPtr> apps = new Dictionary<string, IntPtr>();
public Form1()
{
InitializeComponent();
foreach (Process process in Process.GetProcesses())
{
if (string.IsNullOrEmpty(process.MainWindowTitle))
continue;
apps.Add(process.MainWindowTitle, process.MainWindowHandle);
comboBox1.Items.Add(process.MainWindowTitle);
}
}
private void button1_Click(object sender, EventArgs e)
{
IntPtr intptr = apps[comboBox1.Items[comboBox1.SelectedIndex].ToString()];
Graphics g = Graphics.FromHwnd(intptr);
// get width and height of app #2
int width = (int)g.VisibleClipBounds.Width;
int height = (int)g.VisibleClipBounds.Height;
Size s = new Size(width, height);
// create new bitmap
Bitmap wincapture = new Bitmap(width, height, g);
// code tried.
//g.CopyFromScreen(0, 0, 0, 0, new Size(width, height));
//g.DrawImage(wincapture, 0, 0, width, height);
// once App #2 has been captured, show image in picture box.
pictureBox1.Image = wincapture;
}
}
}
Form1.Designer.cs
namespace WindowsFormsApplication3
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.button1 = new System.Windows.Forms.Button();
this.comboBox1 = new System.Windows.Forms.ComboBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(13, 13);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(267, 183);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
//
// button1
//
this.button1.Location = new System.Drawing.Point(102, 227);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(82, 23);
this.button1.TabIndex = 2;
this.button1.Text = "View Ext App";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// comboBox1
//
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(13, 202);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(267, 21);
this.comboBox1.TabIndex = 3;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 256);
this.Controls.Add(this.comboBox1);
this.Controls.Add(this.button1);
this.Controls.Add(this.pictureBox1);
this.Name = "Form1";
this.Text = "App #1";
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.ComboBox comboBox1;
}
}
这是我在不使用 user32.dll 的情况下截取应用程序屏幕截图的代码。
激活应用程序,并等待 20 以确保它已完成。
Microsoft.VisualBasic.Interaction.AppActivate(ProcessId);
Threading.Thread.Sleep(20);
为了捕获活动 window,我使用了以下内容。添加了 200 的延迟,然后将剪贴板对象转换为图像。
SendKeys.SendWait("%{PRTSC}");
Threading.Thread.Sleep(200);
IDataObject objData = Clipboard.GetDataObject();
概览 我正在尝试捕获外部应用程序的屏幕截图并将图像加载到 .NET PictureBox。
user32.dll 非托管代码 有很多使用 user32.dll 的示例,我正在寻找不使用 user32.dll 文件的 .NET 答案。
应用 #1 我在下面提供了用于演示目的的示例代码。执行程序时,它会解析进程并将具有有效 window 标题的进程保存到 drop-down 列表中。
当您从 drop-down 列表中 select 应用程序名称并单击按钮时,它会尝试捕获屏幕截图应用程序并加载到 .NET PictureBox 中。
Form1.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
Dictionary<string, IntPtr> apps = new Dictionary<string, IntPtr>();
public Form1()
{
InitializeComponent();
foreach (Process process in Process.GetProcesses())
{
if (string.IsNullOrEmpty(process.MainWindowTitle))
continue;
apps.Add(process.MainWindowTitle, process.MainWindowHandle);
comboBox1.Items.Add(process.MainWindowTitle);
}
}
private void button1_Click(object sender, EventArgs e)
{
IntPtr intptr = apps[comboBox1.Items[comboBox1.SelectedIndex].ToString()];
Graphics g = Graphics.FromHwnd(intptr);
// get width and height of app #2
int width = (int)g.VisibleClipBounds.Width;
int height = (int)g.VisibleClipBounds.Height;
Size s = new Size(width, height);
// create new bitmap
Bitmap wincapture = new Bitmap(width, height, g);
// code tried.
//g.CopyFromScreen(0, 0, 0, 0, new Size(width, height));
//g.DrawImage(wincapture, 0, 0, width, height);
// once App #2 has been captured, show image in picture box.
pictureBox1.Image = wincapture;
}
}
}
Form1.Designer.cs
namespace WindowsFormsApplication3
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.button1 = new System.Windows.Forms.Button();
this.comboBox1 = new System.Windows.Forms.ComboBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(13, 13);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(267, 183);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
//
// button1
//
this.button1.Location = new System.Drawing.Point(102, 227);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(82, 23);
this.button1.TabIndex = 2;
this.button1.Text = "View Ext App";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// comboBox1
//
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(13, 202);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(267, 21);
this.comboBox1.TabIndex = 3;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 256);
this.Controls.Add(this.comboBox1);
this.Controls.Add(this.button1);
this.Controls.Add(this.pictureBox1);
this.Name = "Form1";
this.Text = "App #1";
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.ComboBox comboBox1;
}
}
这是我在不使用 user32.dll 的情况下截取应用程序屏幕截图的代码。
激活应用程序,并等待 20 以确保它已完成。
Microsoft.VisualBasic.Interaction.AppActivate(ProcessId);
Threading.Thread.Sleep(20);
为了捕获活动 window,我使用了以下内容。添加了 200 的延迟,然后将剪贴板对象转换为图像。
SendKeys.SendWait("%{PRTSC}");
Threading.Thread.Sleep(200);
IDataObject objData = Clipboard.GetDataObject();