Моя заставка останавливает приостановку экрана, но я этого не хочу

Сделал заставку в .Net 4.0. По сути, он просто перемещает биты изображения и отображает его, используя .Invalidate по таймеру и переопределяя событие onPaint.

Пока он работает отлично, однако я заметил одну проблему с ним.

Это не позволяет монитору приостанавливаться после тайм-аута приостановки. С тех пор, как я его установил, мой монитор теперь работает круглосуточно и без выходных.

Дело в том, что я не делал ничего, чтобы специально остановить функции энергосбережения, и я убедился, что настройки энергосбережения моего компьютера установлены (они установлены). Затем я выбрал другую заставку, чтобы убедиться, что настройки все еще работают. Монитор завис после тайм-аута.

Что мне нужно сделать, чтобы хорошо играть с управлением питанием? Я искал этот ответ в Google, и все, что я нашел, это как заблокировать управление питанием, и я не блокировал его явно! Я просто хочу, чтобы приостановка была разрешена, когда придет время.


person Dracorat    schedule 05.06.2012    source источник


Ответы (2)



Я смог заставить свою программу «играть хорошо». Я не знаю, почему это работает, а исходный код — нет, но это не только работает — это фактически делает программу более дружественной к «энергосбережению», потому что сокращает циклы ЦП, не выполняя вычисления после приостановки экрана. Короче говоря, я просматриваю сообщения WndProc и ищу сообщение о приостановке работы монитора, и как только оно получено, я прекращаю перерисовку до тех пор, пока оно не возобновится (можно возобновить и сохранить активную заставку).

Изменения кода:

    // Field Definitions
    /// <summary>
    /// Constants that relate to the WndProc messages we wish to intercept and evaluate.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Standard practice to use this naming style for Win32 API Constants.")]
    private const int WM_SYSCOMMAND = 0x0112, SC_MONITORPOWER = 0xF170;

    /// <summary>
    /// Gets or sets whether we are suspended. Should coincide with whether the display is turned on or not.
    /// </summary>
    private bool isSuspended = false;


    // New overridden method
    /// <summary>
    /// Intercepts WndProc messages. We are looking for the screen suspend activity. From it, we will return that we are able to suspend and we ourselves will suspend.
    /// </summary>
    /// <param name="m">Message to be checked.</param>
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_SYSCOMMAND)
        {
            // The 0x000F bits are used to indicate the specific state and must be ignored to see if this is a monitor power event.
            if ((m.WParam.ToInt32() & 0xFFF0) == SC_MONITORPOWER)
            {
                switch (m.WParam.ToInt32() & 0x000F)
                {
                    case -1:
                        // Display powering on - resume operation
#if DEBUG
                        System.Diagnostics.Debug.WriteLine("Display powered on.");
#endif
                        this.isSuspended = false;
                        break;
                    case 0:
                    case 1:
                    case 2:
                        // Display being powered off - suspend operation
#if DEBUG
                        System.Diagnostics.Debug.WriteLine("Display suspended");
#endif
                        this.isSuspended = true;
                        break;
                    default:
#if DEBUG
                        System.Diagnostics.Debug.WriteLine(string.Format("Unknown power state: {0}", (m.WParam.ToInt32() & 0x000F).ToString("0")));
#endif
                        // Assuming that unknown values mean to power off. This is a WAG.
                        this.isSuspended = true;
                        break;
                }
            }
        }

        base.WndProc(ref m);
    }


    // Change to my refreshing timer.
    /// <summary>
    /// Called when the refresh timer ticks. This invalidates the form, forcing it to be redrawn, which creates a framerate for us.
    /// </summary>
    /// <param name="sender">Who called this method.</param>
    /// <param name="e">Event Arguments.</param>
    private void RefreshTimer_Tick(object sender, EventArgs e)
    {
        if (this.isSuspended)
        {
            // Program is in suspended mode, so don't do anything this update.
            return;
        }

        // Program is not suspended, so invalidate the client area so it can be painted again.
        this.Invalidate();
    }

Внесение этого изменения останавливает всю перерисовку при вызове приостановки (и останавливает вычисления GDI+), и после внесения этого изменения экранная заставка «ведет себя» с настройками управления питанием.

person Dracorat    schedule 06.06.2012
comment
Очень круто - если вы не возражаете, я, вероятно, буду использовать это как шаблон для изменения имеющегося у нас приложения мониторинга, которое довольно сильно ударяет по базе данных при запуске и бессмысленно, когда экран все равно не отображается. - person 500 - Internal Server Error; 06.06.2012
comment
Я не возражаю, и это уже отчасти ваш собственный успех! Еще раз спасибо! - person Dracorat; 06.06.2012