10

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

15 Answers15

23

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.

FryGuy
  • 8,614
  • 3
  • 33
  • 47
  • 2
    +1 for the digital camera. The user could have an old polaroid somewhere in the attic. Bonus points for users capturing the screen with an etch-a-sketch :-) – Leonel Feb 11 '10 at 15:37
  • would this prevent me taking a screenshot from a machine emulating another with the program? – Diego Castro Dec 01 '10 at 16:20
  • I assume you mean a virtual machine. I don't know how those are implemented. It's possible it would work, but I doubt it. Also, it seems like the windows 7 rendering mode means that this isn't possible anymore. – FryGuy Dec 01 '10 at 23:04
  • At least the answers below provide relatively clear means of making screen capture harder. – Ben Bryant Jul 18 '12 at 18:48
9

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.

Liam
  • 27,717
  • 28
  • 128
  • 190
z -
  • 7,130
  • 3
  • 40
  • 68
  • 1
    Would not work. Most screenshot capture utils define their own hotkeys also – Rinat Abdullin Jan 15 '09 at 19:33
  • Would it stop the built-in print screen from working? Is that good enough? – Greg Jan 15 '09 at 19:41
  • That's pretty much along my thoughts. Disabling print screen would remove a good majority of screen captures. Heck, if they REALLY wanted to capture the screen, they can easily take a digital camera and get it that way. – z - Jan 15 '09 at 19:43
  • 2
    I tested with slimKEYS, mapping PrintScreen to something else (open notepad), and it worked. That means that calling RegisterHotkey with the PrintScreen vkey code WILL WORK for you. I also tested Alt-PrintScreen. You'll have to register both, but it won't prevent other apps from capturing... – Martin Plante Jan 16 '09 at 02:40
  • Anyone can provide code sample for this? I'm trying to do this but I don't really know how. – David Brunelle Oct 24 '12 at 17:42
2

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)

bondar
  • 484
  • 1
  • 3
  • 16
2

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));
            }
        }
    }
}
scottm
  • 27,829
  • 22
  • 107
  • 159
  • 2
    Of course absolutely no use against any of the 1,000,000 screen-grabber applications (including the Windows 7 built-in one), and likely to get your application flagged by paranoid AVs as a keylogger. So that's nice. – bobince Jan 16 '09 at 00:20
  • "I'm looking for methods to introduce some hurdles to the process." This would be a hurdle and would require installing additional software. – scottm Jan 16 '09 at 01:24
  • "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." -- it's still "easy" to capture the screen. – FryGuy Jan 16 '09 at 02:21
  • 10
    Wait... did you just name your class "Hooker"? – Mizipzor May 19 '10 at 13:30
1

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.

Matthew Whited
  • 22,160
  • 4
  • 52
  • 69
Mat
  • 19
  • 1
1

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.)

Michael Todd
  • 16,679
  • 4
  • 49
  • 69
  • I have downvoted this because the information is misleading -- even though you are correct in that the application thread or its windows won't receive directed key events while the windows are out of focus, the documented WinAPI procedure [`RegisterHotKey`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646309(v=vs.85).aspx) allows caller to capture keys regardless of focus -- i.e. "system wide", which should be OPs primary interest. In other words, whether the windows are in out of focus are of little practical consequence here and certainly nothing OP should worry about. – Armen Michaeli Sep 26 '16 at 19:07
1

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.

Jeff Yates
  • 61,417
  • 20
  • 137
  • 189
1

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.

Aif
  • 11,015
  • 1
  • 30
  • 44
0

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!

Eric Grange
  • 5,931
  • 1
  • 39
  • 61
0

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

0

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?

Andrei Krotkov
  • 5,556
  • 3
  • 33
  • 36
0

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.

0

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

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

Form keypreview should be TRUE

0

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);

DAC84
  • 421
  • 1
  • 8
  • 20
-3

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();
Scott
  • 21,211
  • 8
  • 65
  • 72
  • 4
    This looks like a very inefficient solution. An `interval=1` will trigger 1000 times per second. Apart from rendering standard copy and paste functions useless, this will hog the system resources. – Scott Sep 18 '12 at 14:58
  • Some Times It's very important to prevent screen capture and you have to determine whether or not consume system resource or waste some thing valuable in screen !!! – Alireza Sep 19 '12 at 16:55
  • I don't doubt that preventing screen capture can be important. But there are definitely more efficient ways to do it. Even setting the `interval` to 1500 would be a significant improvement to your code, although I still feel your approach lacks finesse. – Scott Sep 19 '12 at 17:04