我公司的管理人员希望我们的ui有一个特殊的自定义控件,以最大限度地防止屏幕截图。我在应用程序的顶层使用SetWindowDisplayAffinity和DWMEnableComposition实现了一个巧妙的解决方案,以防止整个应用程序的屏幕截图,但前面提到的高管对此并不满意。他们只想要特定的UserControl来阻止屏幕截图,而不是整个应用程序。
该自定义控件是包装在4.5WPF窗口控件所包含的4.5WPF WindowsFormsHost中的.NET 2.0 Windows.Forms.UserControl。
在我告诉高管们下一步该怎么做之前,我想确定没有一种合理的方式来实现这一点。
那么,我的问题是:如何实现.NET 2.0 UserControl的屏幕截图保护?
谢谢
发布于 2020-05-08 04:46:49
我有一个想法:用户点击"PrintScreen",从我的程序中截取的是copy to ClipBoard。所以,所有我需要的:捕捉剪贴板,检查他是否包含图像。如果是:我从剪贴板中删除图像。
代码:
//definition a timer
public static Timer getImageTimer = new Timer();
[STAThread]
static void Main()
{
getImageTimer.Interval = 500;
getImageTimer.Tick += GetImageTimer_Tick;
getImageTimer.Start();
......
}
private static void GetImageTimer_Tick(object sender, EventArgs e)
{
if (Clipboard.ContainsImage())//if clipboard contains an image
Clipboard.Clear();//delete
}*但它可以避免程序运行时的任何时间。(你需要知道你的程序是否是前台的,然后检查剪贴板);
发布于 2015-03-18 03:13:53
You 也许能够捕捉到击键。
下面是我使用的一个方法,但它的成功是有限的:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if ((m_parent != null) && m_parent.ScreenCapture(ref msg)) {
return true;
} else {
return base.ProcessCmdKey(ref msg, keyData);
}
}
protected override bool ProcessKeyEventArgs(ref Message msg) {
if ((m_parent != null) && m_parent.ScreenCapture(ref msg)) {
return true;
} else {
return base.ProcessKeyEventArgs(ref msg);
}
}返回"True“应该告诉系统PrintScreen例程已被处理,但它通常仍然在剪贴板上找到数据。
相反,正如您可以从对m_parent.ScreenCapture的调用中看到的,我所做的是将捕获保存到一个文件中,然后在我自己的自定义图像查看器中显示它。
如果有帮助,下面是我为m_parent.ScreenCapture中的自定义图像查看器创建的包装器
public bool ScreenCapture(ref Message msg) {
var WParam = (Keys)msg.WParam;
if ((WParam == Keys.PrintScreen) || (WParam == (Keys.PrintScreen & Keys.Alt))) {
ScreenCapture(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
msg = new Message(); // erases the data
return true;
}
return false;
}
public void ScreenCapture(string initialDirectory) {
this.Refresh();
var rect = new Rectangle(Location.X, Location.Y, Size.Width, Size.Height);
var imgFile = Global.ScreenCapture(rect);
//string fullName = null;
string filename = null;
string extension = null;
if ((imgFile != null) && imgFile.Exists) {
filename = Global.GetFilenameWithoutExt(imgFile.FullName);
extension = Path.GetExtension(imgFile.FullName);
} else {
using (var worker = new BackgroundWorker()) {
worker.DoWork += delegate(object sender, DoWorkEventArgs e) {
Thread.Sleep(300);
var bmp = new Bitmap(rect.Width, rect.Height);
using (var g = Graphics.FromImage(bmp)) {
g.CopyFromScreen(Location, Point.Empty, rect.Size); // WinForm Only
}
e.Result = bmp;
};
worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) {
if (e.Error != null) {
var err = e.Error;
while (err.InnerException != null) {
err = err.InnerException;
}
MessageBox.Show(err.Message, "Screen Capture", MessageBoxButtons.OK, MessageBoxIcon.Stop);
} else if (e.Cancelled) {
} else if (e.Result != null) {
if (e.Result is Bitmap) {
var bitmap = (Bitmap)e.Result;
imgFile = new FileInfo(Global.GetUniqueFilenameWithPath(m_screenShotPath, "Screenshot", ".jpg"));
filename = Global.GetFilenameWithoutExt(imgFile.FullName);
extension = Path.GetExtension(imgFile.FullName);
bitmap.Save(imgFile.FullName, ImageFormat.Jpeg);
}
}
};
worker.RunWorkerAsync();
}
}
if ((imgFile != null) && imgFile.Exists && !String.IsNullOrEmpty(filename) && !String.IsNullOrEmpty(extension)) {
bool ok = false;
using (SaveFileDialog dlg = new SaveFileDialog()) {
dlg.Title = "ACP Image Capture: Image Name, File Format, and Destination";
dlg.FileName = filename;
dlg.InitialDirectory = m_screenShotPath;
dlg.DefaultExt = extension;
dlg.AddExtension = true;
dlg.Filter = "PNG Image|*.png|Jpeg Image (JPG)|*.jpg|GIF Image (GIF)|*.gif|Bitmap (BMP)|*.bmp" +
"|EWM Image|*.emf|TIFF Image|*.tif|Windows Metafile (WMF)|*.wmf|Exchangable image file|*.exif";
dlg.FilterIndex = 0;
if (dlg.ShowDialog(this) == DialogResult.OK) {
imgFile = imgFile.CopyTo(dlg.FileName, true);
m_screenShotPath = imgFile.DirectoryName;
ImageFormat fmtStyle;
switch (dlg.FilterIndex) {
case 2: fmtStyle = ImageFormat.Jpeg; break;
case 3: fmtStyle = ImageFormat.Gif; break;
case 4: fmtStyle = ImageFormat.Bmp; break;
case 5: fmtStyle = ImageFormat.Emf; break;
case 6: fmtStyle = ImageFormat.Tiff; break;
case 7: fmtStyle = ImageFormat.Wmf; break;
case 8: fmtStyle = ImageFormat.Exif; break;
default: fmtStyle = ImageFormat.Png; break;
}
ok = true;
}
}
if (ok) {
string command = string.Format(@"{0}", imgFile.FullName);
try { // try default image viewer
var psi = new ProcessStartInfo(command);
Process.Start(psi);
} catch (Exception) {
try { // try IE
ProcessStartInfo psi = new ProcessStartInfo("iexplore.exe", command);
Process.Start(psi);
} catch (Exception) { }
}
}
}
}这是我几年前写的,我现在不在那里工作了。源代码仍然在我的云驱动器中,这样我就可以利用我曾经学过(但忘记了)的技能。
这些代码并不是为了让您完全完成任务,而只是向您展示了一种完成任务的方法。如果你需要任何帮助,请告诉我。
发布于 2015-03-18 06:31:40
不是银弹,但可以成为战略的一部分。如果您担心windows截取工具或其他已知的截取工具,您可以订阅Windows事件来捕获SnippingTool.exe启动时的通知,然后隐藏您的应用程序,直到它关闭:
var applicationStartWatcher = new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
applicationStartWatcher.EventArrived += (sender, args) =>
{
if (args.NewEvent.Properties["ProcessName"].Value.ToString().StartsWith("SnippingTool"))
{
Dispatcher.Invoke(() => this.Visibility = Visibility.Hidden);
}
};
applicationStartWatcher.Start();
var applicationCloseWatcher = new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStopTrace"));
applicationCloseWatcher.EventArrived += (sender, args) =>
{
if (args.NewEvent.Properties["ProcessName"].Value.ToString().StartsWith("SnippingTool"))
{
Dispatcher.Invoke(() =>
{
this.Visibility = Visibility.Visible;
this.Activate();
});
}
};
applicationCloseWatcher.Start();您可能需要以管理员身份运行此代码才能工作。ManagementEventWatcher位于System.Management程序集中。
这再加上一些处理print screen键的策略:例如,像this这样的东西至少会使屏幕捕获变得困难。
https://stackoverflow.com/questions/29107503
复制相似问题