1

这是我的处女帖,所以请放轻松!

我正在用 C# 编写一个程序,我想最大化并始终在顶部运行。该应用程序将是半透明的,因此用户仍然可以看到我最大化的应用程序背后发生的一切。

我的目标是实现这样一种场景,即用户(尽管我的应用程序具有焦点)仍然可以与所有其他正在运行的程序正常交互 - 就好像它是一块彩色玻璃,它只是将所有用户输入重定向到另一个预期的应用程序,例如什么曾经存在于覆盖层后面的给定 x,y 鼠标单击处。

基本思想是在任务栏以外的所有内容上创建一个叠加层,以将色调或色调应用于用户在屏幕上看到的所有内容。

请记住,我是一名本科生,所以知识有限 - 因此我在这里。

我还考虑了一些与图形驱动程序交谈以进行这些颜色更改的方法,但我不确定前进的方向?

我最初重定向用户输入的想法可行吗?或者我应该沿着驱动程序和窗户颜色配置文件等路线走下去吗?

因此,关于 gammaramp 的想法,我尝试了他跟随但没有按预期执行......

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

期待回复,非常感谢您的宝贵时间!

好的,所以我玩弄了上面的代码,发现如果您将给定的红色/绿色/蓝色渐变成员更改为传递给的伽玛值的一个因子,public static void SetGamma(int gamma)并设置您不想更改的值,因为iArrayValue = i * 128;您可以获得所需的效果。现在剩下要做的就是将特定的 rgb 标量映射到滑块控件或彩色对话框。感谢大家的回复!

4

2 回答 2

0

您可以尝试查看以下内容:

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

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

这些是易于访问的 gamma 修改器 - 您应该能够组合一个快速应用程序来查看它们是如何工作的。它不完全像覆盖,但它可以让您在低级别修改整个屏幕。

于 2012-06-26T00:18:14.230 回答
0

我不确定您是否要使用 WinForms 或 WPF 执行此操作。使用 WPF,您可以执行以下操作:

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

这将为您提供一个完全透明的窗口,所有点击等都将转到底层屏幕。然后,您可以将控件放在窗口上,它们将被看到并响应点击。然后,例如,如果您希望这些控件部分透明,则可以使用 Opacity="0.2"。

在此处查找WinForms 解决方案。

编辑:要在屏幕上始终保持在顶部并且没有鼠标或键盘效果,请使用...

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);
于 2012-06-26T00:28:32.907 回答