如何防止打印屏幕

发布于 2024-07-12 02:12:37 字数 134 浏览 7 评论 0原文

我有一个要求,我正在开发的应用程序阻止用户轻松捕获屏幕内容。

我已经表示,没有可行的方法可以完全防止这种情况发生,但我正在寻找方法来为这一过程引入一些障碍。

我正在使用 C#/.NET 2.0 和 WinForms

I have a requirement that an application I am working on prevent the user from being able to easily capture the contents of the screen.

I have communicated that there is no feasible way to completely prevent this from happening, but I'm looking for methods to introduce some hurdles to the process.

I'm using C#/.NET 2.0 and WinForms

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

差↓一点笑了 2024-07-19 02:12:38

你不能。

您能做的最好的事情就是在覆盖层上渲染到硬件加速设备,类似于视频播放器过去的做法。 基本上,您将整个窗口涂成蓝色,并将图形渲染到视频卡上,视频卡将在内部用图形替换蓝色。 这样做的缺点是您必须放弃使用 winforms 控件,而且我不知道有什么方法可以使用 .NET 轻松地做到这一点。 我认为如果您使用 DirectShow.NET,他们的示例之一是将您自己的图形放入流中。

即使完成所有这些操作后,仍然可以获得屏幕截图。 只需用数码相机拍摄屏幕照片即可。

You can't.

The best you can do is render to a hardware accelerated device on an overlay, similar to what video players used to do. Basically, you paint your entire window blue, and render your graphics onto the video card, and internally the video card will replace the blue with the graphics. The downside to this is you have to give up using winforms controls, and I don't know of any way to do this with .NET easily. I think if you use DirectShow.NET, one of their samples is putting your own graphics into a stream.

Even after doing all of that, it's still possible to get a screenshot. Just take a picture of the screen with a digital camera.

把时间冻结 2024-07-19 02:12:38

来自此处:

A. Windows 使用注册的热键实现打印屏幕。 视窗
使用预定义的热键 IDHOT_SNAPDESKTOP 和 IDHOT_SNAPWINDOW
处理打印屏幕。 这些对应于打印屏幕,它捕获
整个屏幕,以及 Alt+Print Screen,它仅捕获
活动窗口。 要禁用这些功能,您所要做的就是
注册热键,这会导致 Windows 向您的应用程序发送
当用户按下任一热键时发出 WM_HOTKEY 消息。 你的
实现可以忽略该消息以绕过默认值
屏幕捕获行为。 一个好的地方是在你的大型机中
类。

From here:

A. Windows implements Print Screen using a registered hotkey. Windows
uses the predefined hotkeys IDHOT_SNAPDESKTOP and IDHOT_SNAPWINDOW to
handle Print Screen. These correspond to Print Screen, which captures
the entire screen, and Alt+Print Screen, which captures only the
active window. To disable these functions all you have to do is
register the hotkeys, which causes Windows to send your app a
WM_HOTKEY message when the user presses either hotkey. Your
implementation can ignore the message to bypass the default
screen-capture behavior. A good place to do it is in your mainframe
class.

回首观望 2024-07-19 02:12:38

FWIW,这是可能的。 下面是一些代码:

这将是您创建的 dll,然后从应用程序中调用 HookKeyboard 方法。 我已经测试过它并且有效。 当然,如果有人用相机拍照也无济于事,但是,重点是。 呀!

    namespace KeyboardHook
    {
        public class Hooker
        {

            [StructLayout(LayoutKind.Sequential)]
            public struct KBDLLHOOKSTRUCT
            {
                public int vkCode;
                public int scanCode;
                public int flags;
                public int time

;
            public int extraInfo;
        }

        public delegate int HookProc(int nCode, int wParam, IntPtr ptrKBDLLHOOKSTRUCT);


        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        public static extern IntPtr SetWindowsHookEx(int idHook, HookProc callBack, IntPtr hMod, int threadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        public static extern int CallNextHookEx(IntPtr hhk, int nCode, int wParam, IntPtr lParam);

        private static IntPtr kbh_Handle;
        private static HookProc kbh_HookProc;

        private const int VK_SNAPSHOT = 0x2C;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_SYSKEYDOWN = 0x0104;
        private const int WH_KEYBOARD_LL = 13;

        private static int LowLevelKeyboardProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode < 0)
            {
                CallNextHookEx(kbh_Handle, nCode, wParam, lParam);
                return 0;
            }

            if (wParam == WM_KEYDOWN)
            {
                IntPtr kbdll = lParam;
                KBDLLHOOKSTRUCT kbdllstruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(kbdll, typeof(KBDLLHOOKSTRUCT));

                if (kbdllstruct.vkCode == VK_SNAPSHOT)
                    return -1;

            }

            return CallNextHookEx(kbh_Handle, nCode, wParam, lParam);
        }

        public static void HookKeyboard()
        {
            try
            {
                kbh_HookProc = LowLevelKeyboardProc;

                kbh_Handle = SetWindowsHookEx(WH_KEYBOARD_LL, kbh_HookProc, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);

                if (kbh_Handle != IntPtr.Zero)
                    System.Diagnostics.Debug.WriteLine(String.Format("It worked! HookHandle: {0}", kbh_Handle));
                else
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(String.Format("ERROR: {0}", ex.Message));
            }
        }
    }
}

FWIW, it is possible. Here's some code:

This would be a dll that you create, then call the HookKeyboard method from your application. I've tested it and it works. Granted, if someone takes a picture with a camera it can't help, but, point made. NYAH!

    namespace KeyboardHook
    {
        public class Hooker
        {

            [StructLayout(LayoutKind.Sequential)]
            public struct KBDLLHOOKSTRUCT
            {
                public int vkCode;
                public int scanCode;
                public int flags;
                public int time

;
            public int extraInfo;
        }

        public delegate int HookProc(int nCode, int wParam, IntPtr ptrKBDLLHOOKSTRUCT);


        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        public static extern IntPtr SetWindowsHookEx(int idHook, HookProc callBack, IntPtr hMod, int threadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        public static extern int CallNextHookEx(IntPtr hhk, int nCode, int wParam, IntPtr lParam);

        private static IntPtr kbh_Handle;
        private static HookProc kbh_HookProc;

        private const int VK_SNAPSHOT = 0x2C;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_SYSKEYDOWN = 0x0104;
        private const int WH_KEYBOARD_LL = 13;

        private static int LowLevelKeyboardProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode < 0)
            {
                CallNextHookEx(kbh_Handle, nCode, wParam, lParam);
                return 0;
            }

            if (wParam == WM_KEYDOWN)
            {
                IntPtr kbdll = lParam;
                KBDLLHOOKSTRUCT kbdllstruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(kbdll, typeof(KBDLLHOOKSTRUCT));

                if (kbdllstruct.vkCode == VK_SNAPSHOT)
                    return -1;

            }

            return CallNextHookEx(kbh_Handle, nCode, wParam, lParam);
        }

        public static void HookKeyboard()
        {
            try
            {
                kbh_HookProc = LowLevelKeyboardProc;

                kbh_Handle = SetWindowsHookEx(WH_KEYBOARD_LL, kbh_HookProc, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);

                if (kbh_Handle != IntPtr.Zero)
                    System.Diagnostics.Debug.WriteLine(String.Format("It worked! HookHandle: {0}", kbh_Handle));
                else
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(String.Format("ERROR: {0}", ex.Message));
            }
        }
    }
}
冷弦 2024-07-19 02:12:38

您可以尝试使用 msipc.dll 中提供的 IpcProtectWindow。

[DllImport("msipc.dll", SetLastError = false, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
internal static extern int IpcProtectWindow([In] IntPtr hwnd);

从 Microsoft 下载 SDK

调用函数并提供您想要保护的表单的句柄。 (Form.Handle 属性)

You can try using IpcProtectWindow provided in msipc.dll.

[DllImport("msipc.dll", SetLastError = false, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
internal static extern int IpcProtectWindow([In] IntPtr hwnd);

Download the SDK from Microsoft

Call the function above and provide the handle of the form you would like to protect. (Form.Handle property)

梦开始←不甜 2024-07-19 02:12:38

这里有两种情况需要您担心。 一种是当您的窗口/应用程序具有焦点时,另一种是当它没有焦点时。

当它没有焦点时,您无能为力,即,如果用户单击您的应用程序并单击到桌面,则密钥不会发送到您的应用程序,因此您永远不会看到它们。 在这种情况下,当您的应用程序失去焦点时,您可以最小化到托盘(或者,也许在表单上放置一个“空白”面板,以防止用户看到上面的任何内容,这也会阻止打印屏幕的使用)。

在另一种情况下,当您获得焦点时,捕获击键并检查它们。 如果按下 Alt 键并且按下 PrintScreen 键,请重置该值,以便不会出现打印屏幕。 (想想看,这可能行不通。我需要测试一下才能确定。)

You'll have two cases here that you need to worry about. One, when your window/application has focus, the other when it doesn't have focus.

When it doesn't have focus, there's not a whole lot you can do, i.e. if the user clicks off of your app and onto the desktop, keys aren't sent to your app so you'll never see them. In that case, you can minimize to the tray when your app loses focus (or, perhaps, place a "blank" panel over the form to prevent users from seeing anything on it which will also prevent a print-screen from being useful).

In the other case, when you have focus, capture keystrokes and examine them. If the Alt key is down and the PrintScreen key is down, reset the value so that a print-screen doesn't occur. (Come to think of it, that may not work. I'd need to test it to be sure.)

迷爱 2024-07-19 02:12:38

你可以看看电影演员是做什么的。 我相信它们直接渲染到硬件表面(通过 DirectX)。 我怀疑你需要这样做。

You could look into what movie players do. I believe they render directly to a hardware surface (via DirectX). I suspect that you'd need to do this.

一场信仰旅途 2024-07-19 02:12:38

这并不能真正回答问题,但请记住,存在捕获屏幕的工具,并且简单的相机会破坏一切。

我的意思是,好吧,你“必须”,但我会(但我很年轻,还是学生,所以我不知道该说什么)回答说这只是愚蠢的。

This doesn't really answer the questions, but keep in mind that there exists tools to capture screen, and that a simple camera breaks everything.

I mean ok you "have to", but I would (but I'm young and still student, so I don't know much about what can be said) answer that this is just stupid.

夜声 2024-07-19 02:12:38

查看新技术 - sivizion.com,它们一起阻止打印屏幕 - 无法绕过它。 如果有人能找到破解它的方法,请在这里发帖,我不能。 我认为他们也许可他们的技术,不确定,检查一下。

Check out the new tech - sivizion.com, they prevent print screen all together - no way to bypass it. If anyone will figure out a way how to hack it, please post here, I couldn't. I think they also license their tech, not sure, check it out.

心作怪 2024-07-19 02:12:38

好吧,您可以尝试捕获按钮,但我不确定这效果如何。

一直让我烦恼的一件事是,每当我播放一部电影时,它永远不会截图。 如果你可以通过单独的上下文进行渲染,那么拍摄它的照片就会变得非常烦人。 也许您可以通过类似的方式发送屏幕输出?

Well, you could try capturing the button, but I'm not sure how well that will work.

One thing that always annoyed me was that whenever I played a movie, it would never take screenshots of it. If you can render through a separate context, it would make it really annoying to take a picture of it. Perhaps you can send your screen output through something like that?

尬尬 2024-07-19 02:12:38

有些应用程序可以从 OpenGL 和 DirectX 应用程序捕获屏幕! (视情况而定(用于录制游戏影片)
附: windows aero 是 DirectX

http://www.fraps.com/
我认为这就是应用程序

There are applications that can capture the screen from OpenGL and DirectX apps ! (depending (they are used for recording game movies)
ps. windows aero is DirectX

http://www.fraps.com/
i think thats the application

话少情深 2024-07-19 02:12:38

您可以使用视觉密码术并利用视网膜持久性使任何随意的打印屏幕变得无用(请参阅此文章 了解详细信息,bit.ly/vcrypto 了解网络演示)。

这个想法是在两个或多个随机噪声图像之间以高频率交替,这些图像将通过视觉暂留结合起来以揭示内容。 屏幕截图只会抓取一张图像,带有毫无意义的随机噪声。

这是以闪烁和引起用户头痛为代价的,可以通过相机拍摄屏幕图片来解决,或者通过不太随意的了解 Photoshop 的用户来解决,但会解决任何类型的随意屏幕捕获或帧抓取。

从该术语的学术含义来看,偶尔可能有用!

You can make any casual Print Screen useless using Visual Cryptography and taking advantage of retinal persistence (see this article for details, and bit.ly/vcrypto for a web demo).

The idea is to alternate at high frequency between two or more random noise images, that will combine through persistence of vision to reveal the content. A screen capture will only grab one image, with meaningless random noise.

This comes at the cost of flickering and inducing user headaches, can be defeated by a camera taking a picture of the screen, or by a less casual user that knows photoshop, but will defeat any kind of casual screen capture or frame grabbing.

Might occasionally be useful, in an academic meaning of the term!

毁我热情 2024-07-19 02:12:38

为时已晚,但有一个快速解决办法,
只需以MDI形式使用即可
设置True表单的TopMost属性,然后在下面写入事件
private void frmMDI_Deactivate(object sender, EventArgs e){Clipboard.Clear();}

打印屏幕后用户必须最小化应用程序,当用户最小化应用程序时,我们正在清除剪贴板。

您可以在注销功能中或在屏幕移动或调整大小或任何其他所需的表单事件时使用此功能:)

如果 TopMost 属性为 true,则截图工具也无法通过此复制屏幕。

是的,我们无法阻止用户从电话或摄像头等外部设备捕获屏幕。

It is too late but there is a quick work around,
Simply use it in MDI form
Set TopMost Property of form True, then write below event
private void frmMDI_Deactivate(object sender, EventArgs e){Clipboard.Clear();}

after taking print screen user have to minimize the application, the moment user minimize the app, we are clearing clipboard.

you can use this in logout function or when screen move or resize or any other form event as required :)

Snipping tool also can't copy screens by this if TopMost Property is true.

Yes we can't stop user from capturing screen from external device like phone or cam.

默嘫て 2024-07-19 02:12:38

在 Windows 窗体应用程序中,在窗体 keyup 事件中使用此代码,

   if (e.KeyCode == Keys.PrintScreen)
                {
                    Clipboard.Clear();
                }

窗体 keypreview 应该为 TRUE

In windows form application, Use this code in form keyup event,

   if (e.KeyCode == Keys.PrintScreen)
                {
                    Clipboard.Clear();
                }

Form keypreview should be TRUE

风吹雨成花 2024-07-19 02:12:38

微软开发了一个名为SetWindowDisplayAffinity的API来支持窗口内容保护。 此功能使应用程序能够保护应用程序内容不被通过一组特定的公共操作系统功能和 API 捕获或复制
SetWindowDisplayAffinity(hWnd, WDA_MONITOR);

Microsoft has been developed an API named SetWindowDisplayAffinity to support the window content protection. This feature enables applications to protect application content from being captured or copied through a specific set of public operating system features and APIs
SetWindowDisplayAffinity(hWnd, WDA_MONITOR);

嘴硬脾气大 2024-07-19 02:12:38

我使用 Timer 对象和 Clipboard.Clear() 方法解决了这个问题。

首先使用 Interval=1 (非常快)将 Timer 添加到主窗体,然后在其事件中添加以下代码:

Clipboard.Clear();

I solved it using a Timer object and Clipboard.Clear() method.

First add a Timer to your main form with Interval=1 (Very fast), then add the following code in its event:

Clipboard.Clear();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文