Background:
I have a requirement to create a dimming effect on another monitor. I think I solved it by using a WPF Window that takes up the entire screen dimensions with Topmost and AllowsTransparency = True. It has an inner black glow effect and has the style WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW applied to it (among other things) to allow users to click through to the apps behind it.
I monitor for EVENT_OBJECT_REORDER events in Windows and call SetWindowPos to force the Topmost state above other Topmost windows. It seems to work well so far in my proof of concept testing.
The problem I found was this dimming (window) would cover the task bar, but not if I click the Start Menu. I'm currently testing with Windows 10. If I click the Start Menu, it causes the Start Menu and Taskbar to appear above the dimming (window). I wanted everything to remain dim, always.
I solved this issue by setting uiAccess=true in the app manifest, generating a self-signed cert, and copying the exe over to "c:\program files*". This allows me to force a Topmost state for my window, even above the Start Menu.
My questions:
Is there a way to position a window over the Start Menu without uiAccess? Or even another way to force dimness to a screen without using a window (but not dependent on monitor drivers or hardware capabilities)?
If not, what considerations do I need to keep in mind when distributing a WPF app (via a WiX setup project or something similar) that is to bypass UIPI restrictions with uiAccess=True? Can I simply install my self signed cert during the setup process? Will the user run into any additional hurdles? Will I, as a developer, run into any additional hurdles while building this (aside from what I've already mentioned)?
Thank you!
I monitor for EVENT_OBJECT_REORDER events
You are using SetWinEventHook(). This scenario fails the classic "what if two programs do this" bracket. Raymond Chen discussed this pretty well in this blog post, giving your approach a dedicated post.
This is a lot more common than you might assume. Every Windows machine has a program that does this for example, run Osk.exe, the on-screen keyboard program. Interesting experiment, I predict it will flicker badly for a while but assume it will eventually give up. Not actually sure it does, last time I tried this was at Vista time and it wouldn't, please let us know.
Fairly sure you will conclude that this isn't the right way to go about it so uiAccess is moot as well. You needed it here to bypass UIPI and make SetWindowPos() work. An aspect of UAC that blocks attempts by a program to hijack an elevated program's capabilities. Covering the Start window qualifies as a DOS attack. Bigger problem here is that your self-signed certificate isn't going to work, you'll have to buy a real one. Sets you back several hundred dollars every ~7 years.
Controlling monitor brightness with software isn't that easy to do correctly. Everybody reaches for SetDeviceGammaRamp() and that is what you should do as well. The MSDN docs will give you plenty of FUD but afaik every mainstream video adapter driver implements it. It was popular in games. One unavoidable limitation is that it is only active for the desktop in which your program runs. So not for the secure desktop (screen saver and Ctrl+Alt+Del) and not for other login sessions unless they start your program as well.
WMI is too flaky to consider. Not so sure why it fails so often, I assume it has something to do with the often less-than-stellar I2C interconnect between the video adapter and the monitor. Or laptops that want to control brightness with an Fn keystroke, that feature always wins. Or the Windows feature that automatically adjusts brightness based on ambient light, invariably the more desirable way to do this and a hard act to follow.
Most common outcome is likely to be a shrug at your program and a curse of the user at the clumsy monitor controls. But he'll fiddle with it and figure it out. Sorry.
This won't answer anything about uiAccess=true, but...
Dimming the Screen
As an alternative way to dim the screen, you could try using SetDeviceGammaRamp to dim all screens at once (if that's desired).
For example, take the following helper class:
/// <summary> Allows changing the gamma of the displays. </summary>
public static class GammaChanger
{
/// <summary>
/// Retrieves the current gamma ramp data so that it can be restored later.
/// </summary>
/// <param name="gamma"> [out] The current gamma. </param>
/// <returns> true if it succeeds, false if it fails. </returns>
public static bool GetCurrentGamma(out GammaRampRgbData gamma)
{
gamma = GammaRampRgbData.Create();
return GetDeviceGammaRamp(GetDC(IntPtr.Zero), ref gamma);
}
public static bool SetGamma(ref GammaRampRgbData gamma)
{
// Now set the value.
return SetDeviceGammaRamp(GetDC(IntPtr.Zero), ref gamma);
}
public static bool SetBrightness(int gamma)
{
GammaRampRgbData data = new GammaRampRgbData
{
Red = new ushort[256],
Green = new ushort[256],
Blue = new ushort[256]
};
int wBrightness = gamma; // reduce the brightness
for (int ik = 0; ik < 256; ik++)
{
int iArrayValue = ik * (wBrightness + 128);
if (iArrayValue > 0xffff)
{
iArrayValue = 0xffff;
}
data.Red[ik] = (ushort)iArrayValue;
data.Green[ik] = (ushort)iArrayValue;
data.Blue[ik] = (ushort)iArrayValue;
}
return SetGamma(ref data);
}
[DllImport("gdi32.dll")]
private static extern bool SetDeviceGammaRamp(IntPtr hdc, ref GammaRampRgbData gammaRgbArray);
[DllImport("gdi32.dll")]
private static extern bool GetDeviceGammaRamp(IntPtr hdc, ref GammaRampRgbData gammaRgbArray);
[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hWnd);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct GammaRampRgbData
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public UInt16[] Red;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public UInt16[] Green;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public UInt16[] Blue;
/// <summary> Creates a new, initialized GammaRampRgbData object. </summary>
/// <returns> A GammaRampRgbData. </returns>
public static GammaRampRgbData Create()
{
return new GammaRampRgbData
{
Red = new ushort[256],
Green = new ushort[256],
Blue = new ushort[256]
};
}
}
}
Combined with the following in a static void Main(), and the program will change the brightness until the user exits the application:
GammaChanger.GammaRampRgbData originalGamma;
bool success = GammaChanger.GetCurrentGamma(out originalGamma);
Console.WriteLine($"Originally: {success}");
success = GammaChanger.SetBrightness(44);
Console.WriteLine($"Setting: {success}");
Console.ReadLine();
success = GammaChanger.SetGamma(ref originalGamma);
Console.WriteLine($"Restoring: {success}");
Console.ReadLine();
Do note however, that this is applying a global solution to a local problem
If you do go this route, I'd suggest really making sure that you're restoring the user's gamma before exiting, otherwise they'll be left with a less than steller experience that your app crashed and the screen is no permanently dimmed.
Sources:
Discussion of the usage of SetGammaRamp, which is where a bulk of the algorithm comes from
An alternative implementation of the above solution.
Related
How to detect if screen reader is running (JAWS)?
As I understand in .NET 4 we can use AutomationInteropProvider.ClientsAreListening from System.Windows.Automation.Provider namespace, but what if I have to do it for .NET 2.0?
I tried to inspect ClientsAreListening source code, it calls external RawUiaClientsAreListening method from UIAutomationCore.dll library.
Do you have any ideas how to implement JAWS detection in .NET 2.0?
Use the SystemParametersInfo function passing a uiAction of SPI_GETSCREENREADER.
You will need to use P/Invoke for this, for example:
internal class UnsafeNativeMethods
{
public const uint SPI_GETSCREENREADER = 0x0046;
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref bool pvParam, uint fWinIni);
}
public static class ScreenReader
{
public static bool IsRunning
{
get
{
bool returnValue = false;
if (!UnsafeNativeMethods.SystemParametersInfo(UnsafeNativeMethods.SPI_GETSCREENREADER, 0, ref returnValue, 0))
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "error calling SystemParametersInfo");
}
return returnValue;
}
}
}
This is possibly better than using the ClientsAreListening property as this property appears to return true for any automation client, not just screen readers.
Also see:
Using SystemParametersInfo from C# (SPI_GETSCREENREADER SPI_SETSCREENREADER) (Stack Overflow)
INFO: How Clients and Servers Should Use SPI_SETSCREENREADER and SPI_GETSCREENREADER (Microsoft KB)
You should also listen for the WM_SETTINGCHANGE message to detect if a screen reader starts / stops running.
Update (in response to BrendanMcK's comments):
Although this is never explicitly documented in as many words, looking at the description of the flag I think the purpose of this flag is relatively clear:
Determines whether a screen reviewer utility is running. A screen reviewer utility directs textual information to an output device, such as a speech synthesizer or Braille display. When this flag is set, an application should provide textual information in situations where it would otherwise present the information graphically.
What this is saying is that applications set this flag whenever an application wishes the UI to behave as if a screen reader is running, regardless of whether or not that application is actually a screen reader or not.
Suitable things to do in response to this flag is to add text in order to "read" otherwise intuitive UI state to the user. If radical changes are needed to make your UI screen reader accessible then the chances are that your UI also isn't that intuitive to sigted users and could probably do with a re-think.
It takes some time for my program to finish computation, so I would like to run it, read some web pages meanwhile, and when the screen flashes (notification of finished computation), I would get back to my program.
The only missing part is -- how to flash entire screen in C#? I use WPF if this matters.
Please note -- my program is not visible, the other program (web browser for example) takes entire screen (that is the point of the problem, because otherwise, I wouldn't need any notification at all).
Flash = blink.
my first approach would be: on completion of the computation have your program open a new topmost window with transparent background and set it to some color (white) for some brief intervals and close the window again. mind you, while the window is on top you'll not be able to interact with underlying windows during the flashing because the window will eat those events. Alternatively, you could do what most other windows applications (like outlook or messenger) do: display a brief notification box that is clickable to get you to the associated application (your program).
i think a more 'normal' practice would be to install the app as a sys tray icon - then you can change that upon any status change.
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern Int16 FlashWindowEx(ref FLASHWINFO pwfi);
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct FLASHWINFO {
public UInt32 cbSize;
public IntPtr hwnd;
public UInt32 dwFlags;
public UInt32 uCount;
public UInt32 dwTimeout;
}
public const UInt32 FLASHW_STOP = 0;
public const UInt32 FLASHW_CAPTION = 1;
public const UInt32 FLASHW_TRAY = 2;
public const UInt32 FLASHW_ALL = 3;
public void Flash() {
FLASHWINFO flashInfo = new FLASHWINFO();
flashInfo.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(flashInfo);
flashInfo.hwnd = this.Handle; // get the window handle
flashInfo.dwFlags = FLASHW_TIMERNOFG | FLASHW_ALL;
flashInfo.uCount = UInt32.MaxValue;
flashInfo.dwTimeout = 0;
FlashWindowEx(ref flashInfo);
}
I don't think that you can technically flash your screen with WPF. Maybe with a Win32 function. But would it be a possibility to make a screenshot and show a Windows that shows a modified version of that screenshot? This window would have to be declared as TopMost and cover your screen and your image could be modified by increasing the alpha channel over the time.
Edit: OK, I think I misunderstood "flash". If you just want to show a flashing rectangle with one color have a look at the thread which Mamta Dalal posted.
Using David Brown's downloadable sample at ImplicitOperator I've put together an often working GraphViz renderer of a DOT file to an in-memory image.
Unfortunately, my version fails at a guestimated rate of 1 in 8 executions from with the IIS 7 ASP.NET web application I've got it in. I know that the DOT file data is consistent because I've compared the failing instances against the working instances and they are identical.
As David's site seems to suggest that the blog's future is uncertain, I'll reprint the interop pieces here. Hope he doesn't mind. The failure is toward the end of the sample, within RenderImage at the third statement set. I've noted the failing line with // TODO: .... The failure always happens there (if it happens at all). By this line, g and gvc pointers are non-zero and the layout string is correctly populated.
I don't really expect anyone to debug this at runtime. Rather, I hope that some static analysis of the interop code might reveal the problem. I can't think of any advanced marshaling techniques available here - two IntPtrs and a string shouldn't need a lot of help, right?
Thanks!
Side note: I've looked at a trial of MSAGL and I'm not impressed - for $99 from Microsoft, I'd expect more features for node layout and/or documentation explaining what I'm missing. Maybe my rapid port from QuickGraph to AGL unfairly biases my experience because of some fundamental differences in the approaches (edge-centric vs node-centric, for example).
public static class Graphviz
{
public const string LIB_GVC = "gvc.dll";
public const string LIB_GRAPH = "graph.dll";
public const int SUCCESS = 0;
/// <summary>
/// Creates a new Graphviz context.
/// </summary>
[DllImport(LIB_GVC)]
public static extern IntPtr gvContext();
/// <summary>
/// Releases a context's resources.
/// </summary>
[DllImport(LIB_GVC)]
public static extern int gvFreeContext(IntPtr gvc);
/// <summary>
/// Reads a graph from a string.
/// </summary>
[DllImport(LIB_GRAPH)]
public static extern IntPtr agmemread(string data);
/// <summary>
/// Releases the resources used by a graph.
/// </summary>
[DllImport(LIB_GRAPH)]
public static extern void agclose(IntPtr g);
/// <summary>
/// Applies a layout to a graph using the given engine.
/// </summary>
[DllImport(LIB_GVC)]
public static extern int gvLayout(IntPtr gvc, IntPtr g, string engine);
/// <summary>
/// Releases the resources used by a layout.
/// </summary>
[DllImport(LIB_GVC)]
public static extern int gvFreeLayout(IntPtr gvc, IntPtr g);
/// <summary>
/// Renders a graph to a file.
/// </summary>
[DllImport(LIB_GVC)]
public static extern int gvRenderFilename(IntPtr gvc, IntPtr g,
string format, string fileName);
/// <summary>
/// Renders a graph in memory.
/// </summary>
[DllImport(LIB_GVC)]
public static extern int gvRenderData(IntPtr gvc, IntPtr g,
string format, out IntPtr result, out int length);
public static Image RenderImage(string source, string layout, string format)
{
// Create a Graphviz context
IntPtr gvc = gvContext();
if (gvc == IntPtr.Zero)
throw new Exception("Failed to create Graphviz context.");
// Load the DOT data into a graph
IntPtr g = agmemread(source);
if (g == IntPtr.Zero)
throw new Exception("Failed to create graph from source. Check for syntax errors.");
// Apply a layout
if (gvLayout(gvc, g, layout) != SUCCESS) // TODO: Fix AccessViolationException here
throw new Exception("Layout failed.");
IntPtr result;
int length;
// Render the graph
if (gvRenderData(gvc, g, format, out result, out length) != SUCCESS)
throw new Exception("Render failed.");
// Create an array to hold the rendered graph
byte[] bytes = new byte[length];
// Copy the image from the IntPtr
Marshal.Copy(result, bytes, 0, length);
// Free up the resources
gvFreeLayout(gvc, g);
agclose(g);
gvFreeContext(gvc);
using (MemoryStream stream = new MemoryStream(bytes))
{
return Image.FromStream(stream);
}
}
}
Visual Studio 2010 added a "PInvokeStackImbalance" detection that I think helped me fix the problem. While the image would still get generated, I would get this error several times.
By specifying CallingConvention = CallingConvention.Cdecl on all the LIBGVC PInvoke sigantures, the error and crashes disappear.
[DllImport(LIB_GVC, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr gvContext();
[DllImport(LIB_GVC, CallingConvention = CallingConvention.Cdecl)]
public static extern int gvFreeContext(IntPtr gvc);
...
I've had no crashes since making this change, so I'll mark this as the new answer, for now.
I remember running into problems like this while I was working on the article and posted questions about them here and here (the second of which you appear to have commented on; my apologies for not seeing the comment earlier).
The first question is probably not directly related to this because I was writing a test application in C, not C#, and gvLayout was failing every single time instead of just every now and then. Regardless, make sure your application does have access to the Graphviz configuration file (copy it alongside your executable or place the Graphviz bin directory in your system PATH).
The second question is more relevant, except it applies to agmemread and not gvLayout. However, it's very possible that both are caused by the same issue. I was never able to figure out a solution, so I sent the Graphviz team a bug report. Unfortunately, it hasn't been resolved.
The Graphviz API is very simple, so it's unlikely that the issue is caused by the interop code. There is one thing that I neglected to mention in the article: the result pointer needs to be freed. I don't know if this will fix your issue, but it's still a good idea to add it anyway:
[DllImport("msvcrt.dll", SetLastError = true)]
private static extern void free(IntPtr pointer);
// After Marshal.Copy in RenderImage
free(result);
As far as I know, this issue is related to how Graphivz recovers from internal errors, so until the bug is addressed, I'm not sure there's anything you or I can do. But, I'm not an interop expert, so hopefully someone else can help you out a little more.
changing the calling convention DOESN'T help!!
Yes, it works when a simple (actually not that simple) dot source, but it ALWAYS crash if the dot source containing unicode character (simplified chinese).
I need to show form as top level system-wide, e.g. over /all/ other windows on screen. I do realize this is usually /bad UI practice/, but I have very specific scenario in mind.
We intend to use normal Windows PCs for POS cash registrators. There is an option on the screen to open cash drawer. It would be rather bad for someone just to press something on a screen and get access to money when clerk isn't looking. So we equiped PCs with RFID readers and each clerk has his/her own RFID card which will be used for authentication.
I need however an mechanism to lock the computer (or make it unusable) when clerk goes away. Logging off seems too much of a nuisance.
Any ideas welcome.
LP,
Dejan
Well, after a day of trial and error I came to sort of solution.
It involves the following steps:
1.
When "Lock" button is pressed new (empty) /desktop/ is created.
Program is run in this desktop with full screen form and login procedure.
There is nothing else to switch to or run on this desktop.
2.
Task manager is disabled via registry.
Of course, somebody uninvited can still access the Ctrl-Alt-Delete menu, but there is nothing of particular harm he can do there.
3.
Alt-F4 and such are disabled.
4.
When authentication is made, program switches back to original desktop and everything proceeds as normal.
There is some P/Invoking required, of course.
If someone wants to do something similar, perhaps s/he will find my bare bones example helpful - link text
LP,
Dejan
I think you'll need to look into calling down to the Win32 API to achieve this.
You'll need to look into:
ShowWindow
and
SetWindowPos
and invoke them with code similar to the following (note this is pseudo-code):
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void ShowTopmost(Form frm)
{
ShowWindow(frm.Handle, SW_SHOWMAXIMIZED);
SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
0, 0, [width of desktop], [height of desktop],
SWP_SHOWWINDOW);
}
Form has a TopMost property.
set Form.TopMost = true
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
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.
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.
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));
}
}
}
}
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)
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.)
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.
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.
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.
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?
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
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!
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.
In windows form application, Use this code in form keyup event,
if (e.KeyCode == Keys.PrintScreen)
{
Clipboard.Clear();
}
Form keypreview should be TRUE
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);
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();