views:

1989

answers:

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

A: 

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
+6  A: 

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.

yx
Would not work. Most screenshot capture utils define their own hotkeys also
Rinat Abdullin
Would it stop the built-in print screen from working? Is that good enough?
Greg
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.
yx
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
+1  A: 

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
A: 

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
+16  A: 

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
+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
+1  A: 

Perhaps this article might be of use:

Disabling Print Screen, Calling Derived Destructors and More

Esteban Brenes
+1  A: 

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
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
"I'm looking for methods to introduce some hurdles to the process."This would be a hurdle and would require installing additional software.
scottm
"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
Wait... did you just name your class "Hooker"?
mizipzor
+1  A: 

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
A: 

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

Teo Eterovic
+1  A: 

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.

Mat
Interesting, but what a pain in the butt.
Matthew Whited