首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >c#阻止UserControl的屏幕捕获

c#阻止UserControl的屏幕捕获
EN

Stack Overflow用户
提问于 2015-03-18 02:58:20
回答 3查看 3.1K关注 0票数 0

我公司的管理人员希望我们的ui有一个特殊的自定义控件,以最大限度地防止屏幕截图。我在应用程序的顶层使用SetWindowDisplayAffinityDWMEnableComposition实现了一个巧妙的解决方案,以防止整个应用程序的屏幕截图,但前面提到的高管对此并不满意。他们只想要特定的UserControl来阻止屏幕截图,而不是整个应用程序。

该自定义控件是包装在4.5WPF窗口控件所包含的4.5WPF WindowsFormsHost中的.NET 2.0 Windows.Forms.UserControl。

在我告诉高管们下一步该怎么做之前,我想确定没有一种合理的方式来实现这一点。

那么,我的问题是:如何实现.NET 2.0 UserControl的屏幕截图保护?

谢谢

EN

回答 3

Stack Overflow用户

发布于 2020-05-08 04:46:49

我有一个想法:用户点击"PrintScreen",从我的程序中截取的是copy to ClipBoard。所以,所有我需要的:捕捉剪贴板,检查他是否包含图像。如果是:我从剪贴板中删除图像。

代码:

代码语言:javascript
运行
复制
//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
        }

*但它可以避免程序运行时的任何时间。(你需要知道你的程序是否是前台的,然后检查剪贴板);

票数 1
EN

Stack Overflow用户

发布于 2015-03-18 03:13:53

You 也许能够捕捉到击键。

下面是我使用的一个方法,但它的成功是有限的:

代码语言:javascript
运行
复制
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中的自定义图像查看器创建的包装器

代码语言:javascript
运行
复制
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) { }
      }
    }
  }
}

这是我几年前写的,我现在不在那里工作了。源代码仍然在我的云驱动器中,这样我就可以利用我曾经学过(但忘记了)的技能。

这些代码并不是为了让您完全完成任务,而只是向您展示了一种完成任务的方法。如果你需要任何帮助,请告诉我。

票数 0
EN

Stack Overflow用户

发布于 2015-03-18 06:31:40

不是银弹,但可以成为战略的一部分。如果您担心windows截取工具或其他已知的截取工具,您可以订阅Windows事件来捕获SnippingTool.exe启动时的通知,然后隐藏您的应用程序,直到它关闭:

代码语言:javascript
运行
复制
        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这样的东西至少会使屏幕捕获变得困难。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29107503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档