Night Vision Mode on WPF Windows

梦想的初衷 提交于 2019-12-03 08:45:44

One suggestion is of course MahappsThemes. You could switch between Light and Dark by this :

// get the theme from the current application
var theme = ThemeManager.DetectAppStyle(Application.Current);

// now set the Green accent and dark theme
ThemeManager.ChangeAppStyle(Application.Current,
                            ThemeManager.GetAccent("Green"),
                            ThemeManager.GetAppTheme("BaseDark"));

( Mahapps.Styles for ref )

Or you could use DynamicResource for each Brushes and change the SINGLE ResourceDictionary holding them to change everything in a click :)

Alternatively, consider just using the DWM Magnification functionality to make all of windows go into "Night-Mode".

Example:

See the Magnification API sample, with modifications below:

/*************************************************************************************************
*
* File: FullscreenMagnifierSample.cpp
*
* Description: Implements simple UI to control fullscreen magnification, using the 
* Magnification API.
*
*  Copyright (C) Microsoft Corporation.  All rights reserved.
* 
* This source code is intended only as a supplement to Microsoft
* Development Tools and/or on-line documentation.  See these other
* materials for detailed information regarding Microsoft code samples.
* 
* THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
* 
*************************************************************************************************/

#include "windows.h"
#include "resource.h"
#include "strsafe.h"
#include "magnification.h"

// Global variables and strings.
const LPWSTR g_pszAppTitle = L"Night Colors";

// Initialize color effect matrices to apply grayscale or restore the colors on the desktop.
MAGCOLOREFFECT g_MagEffectIdentity = { 
    1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f, 1.0f };
MAGCOLOREFFECT g_MagEffectWashout = {
    0.5f, 0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.3f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.3f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f, 1.0f };

MAGCOLOREFFECT g_MagEffectWashout2 = {
    0.35f, 0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.2f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.2f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f, 1.0f };

MAGCOLOREFFECT g_MagEffectWashout3 = {
    0.25f, 0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.13f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.13f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f, 1.0f };

/*MAGCOLOREFFECT g_MagEffectGrayscale = {0.3f,  0.3f,  0.3f,  0.0f,  0.0f,
                                       0.6f,  0.6f,  0.6f,  0.0f,  0.0f,
                                       0.1f,  0.1f,  0.1f,  0.0f,  0.0f,
                                       0.0f,  0.0f,  0.0f,  1.0f,  0.0f,
                                       0.0f,  0.0f,  0.0f,  0.0f,  1.0f};*/

MAGCOLOREFFECT g_MagEffectGrayscaleInverted = { 
    -0.3f, 0.0f, 0.0f, 0.0f, 0.0f,
    -0.6f, 0.0f, 0.0f, 0.0f, 0.0f,
    -0.1f, 0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
    1.0f, 0.0f, 0.0f, 0.0f, 1.0f };

MAGCOLOREFFECT g_MagEffectInverted = { 
    -1.0f,  0.0f,  0.0f, 0.0f, 0.0f,
     0.0f, -1.0f,  0.0f, 0.0f, 0.0f,
     0.0f,  0.0f, -1.0f, 0.0f, 0.0f,
     0.0f,  0.0f,  0.0f, 1.0f, 0.0f,
     1.0f,  1.0f,  1.0f, 0.0f, 1.0f 
};

MAGCOLOREFFECT g_MagEffectGrayscale = {0.3f,  0.0f,  0.0f,  0.0f,  0.0f,
                                       0.6f,  0.0f,  0.0f,  0.0f,  0.0f,
                                       0.1f,  0.0f,  0.0f,  0.0f,  0.0f,
                                       0.0f,  0.0f,  0.0f,  1.0f,  0.0f,
                                       0.0f,  0.0f,  0.0f,  0.0f,  1.0f};

// Forward declarations.
INT_PTR CALLBACK SampleDialogProc(_In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
void InitDlg(_In_ HWND hwndDlg);
void HandleCommand(_In_ HWND hwndDlg, _In_ WORD wCtrlId);

//
// FUNCTION: WinMain()
//
// PURPOSE: Entry point for the application.
//
int APIENTRY WinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE /*hPrevInstance*/,
                     _In_ LPSTR     /*lpCmdLine*/,
                     _In_ int       /*nCmdShow*/)
{
    // Initialize the magnification functionality for this process.
    if (MagInitialize())
    {
        // Present a dialog box to allow the user to control fullscreen magnification.
        DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_FULLSCREENMAGNIFICATIONCONTROL), NULL, SampleDialogProc);

        // Any current magnification and color effects will be turned off as a result of calling MagUninitialize().
        MagUninitialize();
    }
    else
    {
        MessageBox(NULL, L"Failed to initialize magnification.", g_pszAppTitle, MB_OK);
    }

    return 0;
}

//
// FUNCTION: SampleDialogProc()
//
// PURPOSE: Dialog proc for the UI used for controlling fullscreen magnification.
//
INT_PTR CALLBACK SampleDialogProc(
  _In_  HWND   hwndDlg,
  _In_  UINT   uMsg,
  _In_  WPARAM wParam,
  _In_  LPARAM /*lParam*/
)
{
    INT_PTR ipRet = 0;

    switch (uMsg)
    {
    case WM_INITDIALOG:

        InitDlg(hwndDlg);

        ipRet = 0;

        break;

    case WM_COMMAND:

        if(HIWORD(wParam) == BN_CLICKED)
        {
            WORD wCtrlId = LOWORD(wParam);

            HandleCommand(hwndDlg, wCtrlId);

            ipRet = 1;
        }

        break;

    case WM_CLOSE:

        EndDialog(hwndDlg, 0);

        break;
    }

    return ipRet;
}

//
// FUNCTION: InitDlg()
//
// PURPOSE: Initialize the sample dialog box's position and controls.
//
void InitDlg(_In_ HWND hwndDlg)
{
    // Position the dialog box in the center of the primary monitor.
    RECT rcDlg;
    GetWindowRect(hwndDlg, &rcDlg);

    int xDlg = (GetSystemMetrics(SM_CXSCREEN) - (rcDlg.right - rcDlg.left)) / 2;
    int yDlg = (GetSystemMetrics(SM_CYSCREEN) - (rcDlg.bottom - rcDlg.top)) / 2;

    SetWindowPos(hwndDlg, NULL, xDlg, yDlg, 0, 0, SWP_NOZORDER | SWP_NOSIZE);

    // Set the default color and invalidate the status
    DWORD defaultColor = IDC_CHECK_SETRED_INVERTED;
    HWND hwndControl = GetDlgItem(hwndDlg, defaultColor);
    SendMessage(hwndControl, BM_SETCHECK, BST_CHECKED, 0);
    HandleCommand(hwndDlg, defaultColor);
    SetFocus(hwndControl);
}        

//
// FUNCTION: HandleCommand()
//
// PURPOSE: Take action in response to user action at the dialog box's controls.
//
void HandleCommand(_In_ HWND hwndDlg, _In_ WORD wCtrlId)
{
    switch (wCtrlId)
    {
        case IDC_CHECK_SETRED:
            {
                if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_SETRED))
                {
                    MagSetFullscreenColorEffect(&g_MagEffectGrayscale);
                }
            }
            break;
        case IDC_CHECK_SETRED_INVERTED:
            {
                if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_SETRED_INVERTED))
                {
                    MagSetFullscreenColorEffect(&g_MagEffectGrayscaleInverted);
                }
            }
            break;
        case IDC_CHECK_SET_INVERTED:
            {
                if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_SET_INVERTED))
                {
                    MagSetFullscreenColorEffect(&g_MagEffectInverted);
                }
            }
            break;
        case IDC_CHECK_SET_WASHOUT:
        {
            if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_SET_WASHOUT))
            {
                MagSetFullscreenColorEffect(&g_MagEffectWashout);
            }
        }
        break;
        case IDC_CHECK_SET_WASHOUT2:
        {
            if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_SET_WASHOUT2))
            {
                MagSetFullscreenColorEffect(&g_MagEffectWashout2);
            }
        }
        break;
        case IDC_CHECK_SET_WASHOUT3:
        {
            if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_SET_WASHOUT3))
            {
                MagSetFullscreenColorEffect(&g_MagEffectWashout3);
            }
        }
        break;
    }
}

Window Specific

You can also do this on a window by window basis by compiling a HLSL shader and setting it as an effect upon the window. This technique also works if you need to vary the intensity.

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.img.Source = new BitmapImage(new Uri("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"));
        this.Effect = new ColorComplementEffect();
    }
}

public class ColorComplementEffect : ShaderEffect
{
    public ColorComplementEffect()
    {
        PixelShader = _shader;
        UpdateShaderValue(InputProperty);
    }

    public Brush Input
    {
        get { return (Brush)GetValue(InputProperty); }
        set { SetValue(InputProperty, value); }
    }

    public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(ColorComplementEffect), 0);
    private static PixelShader _shader = new PixelShader() { UriSource = new Uri(@"cc.ps") };
}

Shader:

sampler2D implicitInput : register(s0);

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 color = tex2D(implicitInput, uv);

    float4 complement;
    complement.r = (color.a - color.r) * 0.2;
    complement.g = (color.a - color.g) * 0.2;
    complement.b = (color.a - color.b) * 0.2;
    complement.a = color.a;

    return complement;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!