Рисуем на Windows 10 обои в C ++ - PullRequest
4 голосов
/ 14 мая 2019

Есть ли способ получить дескриптор обоев Windows (за значками) в C ++, чтобы рисовать на нем? Это позволило бы сделать эквивалент активного рабочего стола (более не выпускаемого после Windows XP), аналога Wallpaper Engine или любого другого аналогичного инструмента. (Контроль температуры и использования ресурсов на обоях в моем случае).

Примечание: дескриптор, возвращаемый GetDesktopWindow(), возвращает окно на уровне значков рабочего стола, а не за ним.

Решения от похожих вопросов не работают для меня. В частности, я попробовал режим обоев VLC Media Player код.

Код ключа:

hwnd = FindWindow( _T("Progman"), NULL );
 if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SHELLDLL_DefView"), NULL );
 if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SysListView32"), NULL );
 if( !hwnd )
 {
     msg_Warn( p_vout, "couldn't find \"SysListView32\" window, "
               "wallpaper mode not supported" );
     return;
 }

Но это не будет рисовать на обоях.

1 Ответ

4 голосов
/ 14 мая 2019

Кредиты для этой отрисовки за значками рабочего стола C # в качестве ссылки.В статье объясняется теория, лежащая в основе решения, которое применяется независимо от используемого языка программирования.

Короче говоря, плавная анимация затухания, которую вы видите в Windows 10 при смене обоев, достигается созданием нового окна, которое делаетименно то, что вы просите, рисуя под иконками.Это окно обеспечивает эффект постепенного появления новых обоев и создается Менеджером программ.

В упомянутой статье вы можете увидеть вместе с реализацией C # объяснение каждого шага.Здесь я напишу эквивалент C ++, сохраняя комментарии из источника.

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
    {
    HWND p = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", NULL);
    HWND* ret = (HWND*)lParam;

    if (p)
        {
        // Gets the WorkerW Window after the current one.
        *ret = FindWindowEx(NULL, hwnd, L"WorkerW", NULL);
        }
    return true;
    }

HWND get_wallpaper_window()
    {
    // Fetch the Progman window
    HWND progman = FindWindow(L"ProgMan", NULL);
    // Send 0x052C to Progman. This message directs Progman to spawn a 
    // WorkerW behind the desktop icons. If it is already there, nothing 
    // happens.
    SendMessageTimeout(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, nullptr);
    // We enumerate all Windows, until we find one, that has the SHELLDLL_DefView 
    // as a child. 
    // If we found that window, we take its next sibling and assign it to workerw.
    HWND wallpaper_hwnd = nullptr;
    EnumWindows(EnumWindowsProc, (LPARAM)&wallpaper_hwnd);
    // Return the handle you're looking for.
    return wallpaper_hwnd;
    }

C-подобные броски могут быть заменены на reinterpret_cast s, в соответствии с вашими предпочтениями кодирования.


Одна заметка , которая не упоминается в статье: поскольку при смене обоев создается новое окно WorkerW для достижения эффекта выцветания, если пользователь пытается сменить обои, пока ваша программа активно рисует и обновляетВ вашем экземпляре WorkerW заданный пользователем фон будет помещен поверх вашего чертежа, начнет постепенно исчезать, пока не достигнет 100% непрозрачности, и, наконец, будет уничтожен, оставляя ваш WorkerW все еще работающим.

...