1

This is my virgin post so please go easy on me !

I am writing a program in C# which I want to run maximized and always-on-top. The app will be translucent so that a user can still see everything that's going on behind my maximized application.

I am aiming to achieve a scenario where a user can (despite my app having focus) still interact as normal with all other running programs - as if it was a piece of coloured glass which merely redirects all user input to another intended application, eg what ever exists at a given x,y mouse click behind the overlay.

The basic idea is to create an overlay over everything other than the task bar to apply a tint or tone to everything the user sees on screen.

Please bare in mind I am an undergrad so have limited knowledge - hence why I am here.

I have also considered some methodology of talking to perhaps a graphics driver to make these colour changes but I am unsure of the way forward?

Is my initial idea of redirecting user input feasible? Or should I go down the route of drivers and windows color profiles etc?

So with regard to the gammaramp idea I tried out he following but not performing as expected ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;
using System.Drawing;

namespace GammaRAMP
{
public class Program
{

    [DllImport("user32.dll")]
    public static extern IntPtr GetDC(IntPtr hWnd);

    [DllImport("gdi32.dll")]
    public static extern bool SetDeviceGammaRamp(IntPtr hDC, ref RAMP lpRamp);



    [DllImport("gdi32.dll")]
    public static extern int GetDeviceGammaRamp(IntPtr hDC, ref RAMP lpRamp);


    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
    public struct RAMP
    {
        [ MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] 
        public UInt16[] Red;
        [ MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] 
        public UInt16[] Green;
        [ MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] 
        public UInt16[] Blue;
    }

    public static void SetGamma(int gamma)
    {
        if (gamma <= 256 && gamma >= 1)
        {
            RAMP ramp = new RAMP();
            ramp.Red = new ushort[256];
            ramp.Green = new ushort[256];
            ramp.Blue = new ushort[256];

            for( int i=1; i<256; i++ )
            {
                int iArrayValue = i * (gamma + 128);

                if (iArrayValue > 65535) // I assume this is a max value.
                    iArrayValue = 65535;

                // So here I purposfully set red to max all the time expecting 
                // a lot of extra red but hardly any change occurs?

                //ramp.Red[i] = 65535; 

                // However if I do this:
                ramp.Red[i] = (ushort)iArrayValue;
                // I get VERY noticable changes?


                ramp.Blue[i] = ramp.Green[i] = (ushort)iArrayValue;
            }
            SetDeviceGammaRamp(GetDC(IntPtr.Zero), ref ramp);

        }
     }

    public static void Main(string[] args)
    {
        string ent = "";
        int g=0;

        // A RAMP struct to store initial values.
        RAMP r = new RAMP();
        // Store initial values.
       GetDeviceGammaRamp(GetDC(IntPtr.Zero),ref r);

        while (ent != "EXIT")
        {

            Console.WriteLine("Enter new Gamma (or 'EXIT' to quit):");
            ent = Console.ReadLine();
            try
            {
            g=int.Parse(ent);
            SetGamma(g);
            }
            catch
            {
            //Here only to catch errors where input is not a number (EXIT, for example, is a string)        
            }
        }

        // Reset any RAMP changes.
        SetDeviceGammaRamp(GetDC(IntPtr.Zero), ref r);
        Console.ReadLine();
    }
}
}

Looking forward to responses and thanks very much for your time!

Ok so I played around with the above code and found that if you change a given red / green / blue ramp member by a factor of the gamma value passed in to public static void SetGamma(int gamma) and set values you do not want to change as iArrayValue = i * 128; you get the desired effect. All that remains to be done now is map specific rgb scalars to slider controls or maybe a colordialog. Thanks to everyone for your responses!

James C
  • 464
  • 1
  • 4
  • 12
  • Do you want to log or otherwise process the user's actions or do you just want to tint the screen? – J... Jun 25 '12 at 22:43
  • Just tint the screen to a users specified colour and opacity. I feel like the colour profile approach is more elegant but technically challenging. However the overlay approach is easier to understand as a software implementation of a real world colour filter so to speak. – James C Jun 25 '12 at 23:09
  • A system service may be the best approach for this type of program. Something like f.lux : http://stereopsis.com/flux/ You could probably hack something together in a c# winforms app, but unless this is purely an academic exercise it's probably better to just start on the right path to begin with. – J... Jun 26 '12 at 00:04
  • Yea I already use f.lux on my mac, have no idea how to go about hacking something like that together although that is basically the end result I want, just with user defined alpha and rgb. Any ideas on which libraries I can look up? or if C# is even going to allow me to achieve this? - Thanks – James C Jun 26 '12 at 00:11

2 Answers2

0

You might try looking at something like :

http://www.pinvoke.net/default.aspx/gdi32.setdevicegammaramp

http://www.pinvoke.net/default.aspx/gdi32/getdevicegammaramp.html

These are easily accessible gamma modifiers - you should be able to put together a quick application to see how they work. It's not exactly like an overlay but it will allow you to modify the entire screen at a low level.

J...
  • 30,968
  • 6
  • 66
  • 143
  • Thanks for doing the leg work but I've already had a look through that, here is what I did. If you run it you will see what I'm on about in the comments with regard to things seemingly not acting as you might think ..... FYI make sure you use EXIT otherwise previous settings won't be restored and you might end up having to re-calibrate your display. – James C Jun 26 '12 at 00:36
  • @JamesC - if you already have code then *please* edit your question and post it in there. That instantly makes your question better and easier to answer! – J... Jun 26 '12 at 00:38
  • @JamesC pastebin should generally not be required. We don't need to see your entire program, just the part where there is a problem and SO nicely allows you to insert formatted code. Critically, however, a stackoverflow question should include "what have you tried", "what did you expect", and "what actually happened". Unless the entire program is broken, there is probably just one part that didn't work like you wanted. That's the bit we need to see. – J... Jun 26 '12 at 08:48
0

I am not sure if you are wanting to do this with WinForms or WPF. With WPF you can do something like the following:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" Background="Transparent"
    AllowsTransparency="True" WindowStyle="None" Topmost="True" WindowState="Maximized">
</Window>

This will give you a completely transparent window, and all clicks etc will go to the underlying screen. You can then put controls on the window, and they will be seen and respond to clicks. Then you could, for example, have Opacity="0.2" if you want those controls to be partly transparent.

Look here for a WinForms solution.

Edit: To just have a colored tint over the screen that always stays on top and has no mouse or keyboard effect, use...

this.TopMost = true;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
this.Opacity = 0.5;
int initialStyle = GetWindowLong(this.Handle, -20);
SetWindowLong(this.Handle, -20, initialStyle | 0x20);
Community
  • 1
  • 1
Michael
  • 8,891
  • 3
  • 29
  • 42
  • Updated entry. If I am still missing the point can you provide more detail about what you are after in your question? – Michael Jun 26 '12 at 04:10