Processing Ajax...

Title

Message

Confirm

Confirm

Confirm

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure?

Toff's profile on WallpaperFusion.com
Hi,

I'm delighted to see the inclusion of screen fading GUI in the latest release of DF.
(which is great, the only bug so far is the dimming flickers when Windows system notifications appear).

I work in a conservatory, so my monitors need to be full brightness during the day, gradually fading as it turns to dusk.

I've been using a piece of software called "Pangolin Screen Brightness" to control this for years. Its a very simple app, so I had to string together batch scripts which altered the registry entry for the dimming value. This was a belts & braces approach but it worked.

Now I'm looking to replicate this in DF. I have seen there are a few functions already scripted (such as "Fade Selected Monitor to Black" by BF's very own Keith Lammers) which presumably could be altered to dim all screens. Its the scheduling I need some advice on please:

SIMPLE APPROACH:
Is it possible to schedule the dimming level to change at set times of the day using functions?

ADVANCED APPROACH:
I use a Z-Wave multi sensor to detect the light level in my conservatory (this alters sporadically due to the cloud cover, rain etc). I use Event Ghost to perform actions when the light levels rise / fall above certain thresholds*. Can I somehow make a procedure call (or command line call etc) to trigger a function to change the dimming level?

Thanks in advance for any advice.

Regards
Al

* For anybody who's interested; I use a SmartApp within the Samsung SmartThings IDE to automatically make a HTTP call to Event Ghost on my PC when the light sensor reaches certain levels. EvenGhost can then run a batch / call or whatever's needed to interface with Display Fusion.
Oct 26, 2017  • #1
Toff's profile on WallpaperFusion.com
PS: It would be great to see some scheduling options in the Fading GUI (and perhaps even some ability to link it to the sunset / sunrise data from weather.com based on your nearest city)

I wish I was clever enough to write a function for this, alas I'm not; so it's a suggestion for a future release :)
Oct 26, 2017 (modified Oct 26, 2017)  • #2
User Image
Michael M
1 discussion post
It sounds like similar functionality to F.lux (scheduled fade times / duration), though not as advanced as what you have set up (kudos on that, btw!) What you are requesting would be a great feature, then I could stop using F.lux and Palingo.

I would also like to add upon this request - It would be nice to have a quick control for changing the dimming percentage, like Palingo does, in the taskbar (fader or a list of values would be nice), since at times, during the faded period, it is necessary to disable / adjust the fade quickly.

Finally, a quick fade from brightness levels (from 100% to 50%, for example) in increments of 10% over 5 seconds would be much nicer on the eyes, rather than a quick 'bam' from 100% to 50%. This is most noticeable when fading the non-active window and switching between them.
Oct 26, 2017 (modified Oct 26, 2017)  • #3
Keith Lammers (BFS)'s profile on WallpaperFusion.com
Thanks for the feedback, guys! Scheduling will be coming hopefully in the next major version. In the meantime, you could duplicate my script, change the fading level in it, and then call whichever one you need via DisplayFusionCommand.exe like so:

"C:\Program Files (x86)\DisplayFusion\DisplayFusionCommand" -functionrun "ScriptedFunctionName"

Hope that helps!
Oct 28, 2017  • #4
Toff's profile on WallpaperFusion.com
Hi Keith,

Please could you point out exactly where i need to change the transparency value and how to remove the screen chooser (as i always want all the monitors to fade.

Code

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Collections.Generic;

// Based entirely on NetMage's "Fade All Monitors Except the Primary Monitor to Black" which was based on Thomas' "Dim All Monitors Except Primary"

public static class DisplayFusionFunction {
    private static readonly string SettingName = "BlackenMonitors_Run";
    public static void Run(IntPtr windowHandle) {
        //toggle the setting from running to not running, and vice versa
        ToggleSetting();

        if (RunFadeMonitors()) {
            //add the selected monitor to the form
            var forms = new List<Form>();
            forms.Add(new TransparentForm(BFS.Monitor.ShowMonitorSelector()));
        
            //this will open the forms we added to the list by using our custom application context
            Application.Run(new MultipleFormApplicationContext(forms));
        }
    }
    
    //this function allows us to see the currect state of the script
    private static bool RunFadeMonitors() {
        return BFS.ScriptSettings.ReadValue(SettingName) == "run";
    }

    //this function toggles the script settings from running to not running
    private static void ToggleSetting() {
        BFS.ScriptSettings.WriteValue(SettingName, RunFadeMonitors() ? "not" : "run");
    }

    //extend the ApplicationContext class to support opening multiple forms
    private class MultipleFormApplicationContext : ApplicationContext {
        internal MultipleFormApplicationContext(List<Form> forms) {
            //open each of the forms, and add our closing event to them
            foreach(Form form in forms) {
                form.FormClosed += OnFormClosed;
                form.Show();
            }
        }

        //when all the forms close, make sure to exit the application
        private void OnFormClosed(object sender, EventArgs e) {
            if(Application.OpenForms.Count == 0)
                ExitThread();
        }
    }
    
    //extend the Form class to get the behavior we want
    private class TransparentForm : Form {
        //this will tell us what monitor to open on
        private uint MonitorId;
        private uint FadeWait;
        private decimal TransparentIncrement;
        
        //this will tell us our current transparency
        private decimal Transparency;
        
        //the contructor for our class
        internal TransparentForm(uint monitorId) {        
            MonitorId = monitorId;
            Transparency = 0m;
            const decimal FadeTime = 2.0m; // seconds
            TransparentIncrement = 1m; // percent
            FadeWait = (uint)(TransparentIncrement * 10m * FadeTime);
            
            SuspendLayout();
            
            //setup the layout of this form
            BackColor = Color.Black;
            FormBorderStyle = FormBorderStyle.None;
            ShowInTaskbar = false;
            //move the window to the desired monitor
            Rectangle bounds = BFS.Monitor.GetMonitorBoundsByID(MonitorId);
            Location = new Point(bounds.X, bounds.Y);
            Size = new Size(bounds.Width, bounds.Height);
            StartPosition = FormStartPosition.Manual;
            
            BFS.Window.SetAlwaysOnTop(Handle, true);
            BFS.Window.SetTransparency(Handle, Transparency);

            //setup the form load event
            Load += Form_Load;            
            
            ResumeLayout(false);
        }
        
        private void Form_Load(object sender, EventArgs e) {
            //add a windows style to the current style that will
            //tell this window to ignore user input
            uint style = (uint)BFS.Window.GetWindowStyleEx(Handle) | (uint)BFS.WindowEnum.WindowStyleEx.WS_EX_TRANSPARENT | (uint)BFS.WindowEnum.WindowStyleEx.WS_EX_LAYERED;
            BFS.Window.SetWindowStyleEx((BFS.WindowEnum.WindowStyleEx)style, Handle);
            
            //start up a thread to listen for an exit event
            new Thread(new ThreadStart(ExitListener)).Start();
        }

        private void ExitListener() {
            while(true) {
                //if we should close, tell the main thread to close the form
                if(RunFadeMonitors()) {
                    // Fade to Black
                    if (Transparency < 100m) {
                        Transparency += TransparentIncrement;
                        BFS.Window.SetTransparency(Handle, Transparency);
                    }

                    //sleep
                    BFS.General.ThreadWait((Transparency < 100m) ? FadeWait : 250u);                
                }
                else {
                    if (this.Transparency > 0m) {
                        // Fade back in
                        Transparency -= TransparentIncrement;
                        BFS.Window.SetTransparency(Handle, Transparency);

                        //sleep
                        BFS.General.ThreadWait((Transparency < 100m) ? FadeWait : 250u);
                    }
                    else {
                        try {
                            this.Invoke((MethodInvoker) delegate {
                                Close();
                            });
                        }
                        catch { //something went wrong, ignore
                        }
                        
                        break;
                    }
                }
            }
        }
    }
}


Many thanks in advance

Al
Oct 10, 2018  • #5
Toff's profile on WallpaperFusion.com
Just a thought...

Would it be easy to get the script to read the previous transparency value and increase or decrease it by a set increment?

That way, I could have just two scripts to tun the brightness up & down

One that has a hotkey of something like
CTRL SHIFT -

and another that has a hotkey of
CTRL SHIFT +

Any guidance appreciated
Al
Oct 10, 2018  • #6
Keith Lammers (BFS)'s profile on WallpaperFusion.com
I'll pass this over to Thomas to answer, as he was the original author of this script :)
Oct 11, 2018  • #7
Thomas Malloch (BFS)'s profile on WallpaperFusion.com

Sorry for the late response!

I was able to modify the script to be able to listen for the change of transparency value. The only downside is that you'll now need 3 scripts. One to toggle the dimming functionality and listen, another to increase the transparency value, and another to decrease it.

Here's the first script:

Code

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Collections.Generic;

// The 'windowHandle' parameter will contain the window handle for the:
//   - Active window when run by hotkey
//   - Window Location target when run by a Window Location rule
//   - TitleBar Button owner when run by a TitleBar Button
//   - Jump List owner when run from a Taskbar Jump List
//   - Currently focused window if none of these match
public static class DisplayFusionFunction
{
    private static readonly string SettingName = "DimMonitor_TransparentForm_Running";
    private static readonly string TransparencySettingName = "DimMonitor_TransparentForm_TransparencyValue";
    public static void Run(IntPtr windowHandle)
    {
        // toggle the setting from running to not running, and vice versa
        ToggleSetting();
        
        // check to see if we should exit
        bool isExiting = !IsTransparentWindowRunning();
                
        // if we are exiting, exit
        if(isExiting)
            return;
            
        // get the transparency value. if there's none, set it to 30%
        decimal transparency = 30;
        if(new List<string>(BFS.ScriptSettings.GetValueNames()).Contains(TransparencySettingName))
            transparency = (decimal)BFS.ScriptSettings.ReadValueInt(TransparencySettingName);
        else
            BFS.ScriptSettings.WriteValueInt(TransparencySettingName, 30);
        
        // add all but the primary monitor to the list of monitors that will be dimmed
        List<Form> forms = new List<Form>();
        foreach(uint id in BFS.Monitor.GetMonitorIDs())
            forms.Add(new TransparentForm(id, transparency));
        
        // this will open the forms we added to the list by using our custom application context
        Application.Run(new MultipleFormApplicationContext(forms));
    }
    
    // this function toggles the script settings from running to not running
    private static void ToggleSetting()
    {
        string status = BFS.ScriptSettings.ReadValue(SettingName);
        if(status.Equals("running", StringComparison.Ordinal))
            BFS.ScriptSettings.WriteValue(SettingName, "not");
        else
            BFS.ScriptSettings.WriteValue(SettingName, "running");
    }
    
    // this function allows us to see the currect state of the script
    private static bool IsTransparentWindowRunning()
    {
        string status = BFS.ScriptSettings.ReadValue(SettingName);
        return status.Equals("running", StringComparison.Ordinal);
    }
    
    // extend the ApplicationContext class to support opening multiple forms
    private class MultipleFormApplicationContext : ApplicationContext 
    {
        internal MultipleFormApplicationContext(List<Form> forms)
        {
            //open each of the forms, and add our closing event to them
            foreach(Form form in forms)
            {
                form.FormClosed += OnFormClosed;
                form.Show();    
            }        
        }
        
        // when all the forms close, make sure to exit the application
        private void OnFormClosed(object sender, EventArgs e)
        {
            if(Application.OpenForms.Count == 0)
                ExitThread();
        }
    }
    
    // extend the Form class to get the behavior we want
    private class TransparentForm : Form 
    {
        // this will tell us what monitor to open on
        private uint MonitorId;
        
        // this will tell us what transparency to use
        private decimal LastTransparency;
        
        // this will help us with some threading
        private object ThreadLock = new object();
        
        // the contructor for our class
        internal TransparentForm(uint monitorId, decimal transparency)
        {        
            this.MonitorId = monitorId;
            lock(this.ThreadLock)
                this.LastTransparency = transparency;
            
            this.SuspendLayout();
            
            // setup the layout of this form
            this.BackColor = Color.Black;
            this.FormBorderStyle = FormBorderStyle.None;
            this.ShowInTaskbar = false;
            
            // setup the form load event
            this.Load += Form_Load;            
            
            this.ResumeLayout(false);
        }
        
        private void Form_Load(object sender, EventArgs e)
        {
            // set the window to be always on top
            BFS.Window.SetAlwaysOnTop(this.Handle, true);
            
            // make the window transparent
            lock(this.ThreadLock)
                BFS.Window.SetTransparency(this.Handle, this.LastTransparency);
            
            // add a windows style to the current style that will
            // tell this window to ignore user input
            uint style = (uint)BFS.Window.GetWindowStyleEx(this.Handle);
            BFS.Window.SetWindowStyleEx((BFS.WindowEnum.WindowStyleEx)(style | (uint)BFS.WindowEnum.WindowStyleEx.WS_EX_TRANSPARENT | (uint)BFS.WindowEnum.WindowStyleEx.WS_EX_LAYERED), this.Handle);
        
            // move the window to the desired monitor
            this.Bounds = BFS.Monitor.GetMonitorBoundsByID(this.MonitorId);
            
            // start up a thread to listen for an exit event
            new Thread(new ThreadStart(ExitListener)).Start();
        }
        
        private void ExitListener()
        {
            while(true)
            {
                // if we should close, tell the main thread to close the form
                if(!IsTransparentWindowRunning())
                {
                    try
                    {
                        this.Invoke((MethodInvoker) delegate
                        {
                            this.Close();
                        });
                    }
                    catch // something went wrong, ignore
                    {
                    }
                        
                    break;
                }
                
                // check to see if we need to update the transparency
                bool isNeedingToUpdateTransparency = false;
                int transparency = BFS.ScriptSettings.ReadValueInt(TransparencySettingName);
                lock(this.ThreadLock)
                {
                    if(transparency != (int)this.LastTransparency)
                    {  
                        this.LastTransparency = (decimal)transparency;
                        isNeedingToUpdateTransparency = true;
                    }
                }

                if(isNeedingToUpdateTransparency)
                {
                    decimal temp = (decimal)transparency;
                    this.Invoke((MethodInvoker) delegate
                    {
                        BFS.Window.SetTransparency(this.Handle, temp);
                    });
                }
                
                // sleep for a quarter of a second
                BFS.General.ThreadWait(250);
            }
        }
    }
}

Here's the second that will increase the value:

Code

using System;
using System.Drawing;

// The 'windowHandle' parameter will contain the window handle for the:
//   - Active window when run by hotkey
//   - Trigger target when run by a Trigger rule
//   - TitleBar Button owner when run by a TitleBar Button
//   - Jump List owner when run from a Taskbar Jump List
//   - Currently focused window if none of these match
public static class DisplayFusionFunction
{
    private static readonly string TransparencySettingName = "DimMonitor_TransparentForm_TransparencyValue";
    public static void Run(IntPtr windowHandle)
    {
        int transparency = BFS.ScriptSettings.ReadValueInt(TransparencySettingName) + 5;
        if(transparency > 100)
            transparency = 100;
            
        BFS.ScriptSettings.WriteValueInt(TransparencySettingName, transparency);
    }
}

Here's the third that will decrease the value:

Code

using System;
using System.Drawing;

// The 'windowHandle' parameter will contain the window handle for the:
//   - Active window when run by hotkey
//   - Trigger target when run by a Trigger rule
//   - TitleBar Button owner when run by a TitleBar Button
//   - Jump List owner when run from a Taskbar Jump List
//   - Currently focused window if none of these match
public static class DisplayFusionFunction
{
    private static readonly string TransparencySettingName = "DimMonitor_TransparentForm_TransparencyValue";
    public static void Run(IntPtr windowHandle)
    {
        int transparency = BFS.ScriptSettings.ReadValueInt(TransparencySettingName) - 5;
        if(transparency < 0)
            transparency = 0;
            
        BFS.ScriptSettings.WriteValueInt(TransparencySettingName, transparency);
    }
}

I hope this works for you!

Feb 4, 2019 (modified Feb 4, 2019)  • #8
Owen Muhlethaler (BFS)'s profile on WallpaperFusion.com
We've released a new beta that allows you set to a gradual fade time. You can grab it here: https://www.displayfusion.com/Download/Beta/

Thanks!
Jun 26, 2024  • #9
Toff's profile on WallpaperFusion.com
Thanks v.much Thomas for the scripts and Owen for notificaiton of this latest release.

Just out of interest... how do you know to come back to this thread to notify of this specific feature? Is it done with tags?

Thanks
Al
Jul 11, 2024  • #10
Owen Muhlethaler (BFS)'s profile on WallpaperFusion.com
Yep we keep track of who has asked for what, so we can follow up if we add it in :)
Jul 12, 2024  • #11
Subscribe to this discussion topic using RSS
Was this helpful?  Login to Vote(1)  Login to Vote(-)