本文总阅读量 本站访客数人次 本站总访问量
gongluck's blog
C/C++ Golang 音视频流媒体
任务管理器播放BadApple

有屏幕的地方就有BadApple!前面做了在控制台显示BadApple了,这一次把画面渲染到任务管理器上!

设计思路

和上一篇差不多,只是设置指定窗口为libvlc的渲染窗口。找到指定的窗口比较复杂。

效果视频

https://www.bilibili.com/video/BV1B64y1u7rv

代码仓库

https://github.com/gongluck/Character-player/tree/taskmgr

//process.cpp
#include "process.h"
#include "../errcode.h"

#include <iostream>

#ifdef _WIN32
#include <windows.h>
#include <TlHelp32.h>
#include <tchar.h>
#include <atlconv.h>
#endif

namespace gprocess
{
    int gethandle(const char* processname, std::vector<ProcessInfo>& result)
    {
        if (processname == nullptr)
        {
            return G_ERROR_INVALIDPARAM;
        }

#ifdef _WIN32
        auto hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        USES_CONVERSION;
        auto processT = A2T(processname);
        if (hSnapshot == INVALID_HANDLE_VALUE || processT == nullptr)
        {
            std::cerr << __FILE__ << " : " << __LINE__ << " : " << GetLastError() << std::endl;
            return G_ERROR_INTERNAL;
        }

        result.clear();
        ProcessInfo info = { 0 };
        PROCESSENTRY32 pe = { sizeof(pe) };
        auto fOk = FALSE;
        for (fOk = Process32First(hSnapshot, &pe); fOk; fOk = Process32Next(hSnapshot, &pe))
        {
            if (!_tcscmp(pe.szExeFile, processT))
            {
                info.processid = pe.th32ProcessID;
                info.parentid = pe.th32ParentProcessID;
                result.push_back(info);
            }
        }
        CloseHandle(hSnapshot);
        return G_ERROR_SUCCEED;
#endif

        return G_ERROR_SUCCEED;
    }

#ifdef _WIN32
    BOOL CALLBACK EnumChildWindowCB(HWND h, LPARAM l)
    {
        auto pinfo = reinterpret_cast<WindowInfo*>(l);
        DWORD pid = 0;
        GetWindowThreadProcessId(h, &pid);
        if (pid == pinfo->processid)
        {
            auto pchild = std::make_shared<WindowInfo>();
            pchild->processid = pid;
            pchild->window = h;
            pinfo->childs.push_back(pchild);
            EnumChildWindows(h, EnumChildWindowCB, reinterpret_cast<LPARAM>(pchild.get()));
        }
        return TRUE;
    }
    BOOL CALLBACK EnumWindowCB(HWND h, LPARAM l)
    {
        auto pinfo = reinterpret_cast<WindowInfo*>(l);
        DWORD pid = 0;
        GetWindowThreadProcessId(h, &pid);
        if (pid == pinfo->processid)
        {
            auto pchild = std::make_shared<WindowInfo>();
            pchild->processid = pid;
            pchild->window = h;
            pinfo->childs.push_back(pchild);
            EnumChildWindows(h, EnumChildWindowCB, reinterpret_cast<LPARAM>(pchild.get()));
        }
        return TRUE;
    }
#endif

    int getallwindows(WindowInfo* info)
    {
#ifdef _WIN32
        if (EnumWindows(EnumWindowCB, reinterpret_cast<LPARAM>(info)) != TRUE)
        {
            std::cerr << __FILE__ << " : " << __LINE__ << " : " << GetLastError() << std::endl;
            return G_ERROR_INTERNAL;
        }
        return G_ERROR_SUCCEED;
#endif
        return G_ERROR_SUCCEED;
    }
} // namespace gprocess
//main.cpp
#include <iostream>

#ifdef _WIN32
#include <Windows.h>
#include <tchar.h>
#define ssize_t SSIZE_T
#endif
#include <vlc/vlc.h>

#include "../../Code-snippet/cpp/process/process.h"

#define CHECKEQUALRET(ret, compare)\
if(ret == compare)\
{\
    std::cerr << "error ocurred in " << __FILE__\
              << "`s line " << __LINE__\
              << ", error " << ret;\
    goto END;\
}

#define CHECKNEQUALRET(ret, compare)\
if(ret != compare)\
{\
    std::cerr << "error ocurred in " << __FILE__\
              << "`s line " << __LINE__\
              << ", error " << ret;\
    goto END;\
}

int getwindows(const TCHAR* classname,
    const gprocess::WindowInfo& info,
    std::vector<std::shared_ptr<gprocess::WindowInfo>>& result)
{
    std::vector<std::shared_ptr<gprocess::WindowInfo>> tmp;
    TCHAR classname_[MAX_PATH] = { 0 };
    for (int i = 0; i < info.childs.size(); ++i)
    {
        GetClassName(reinterpret_cast<HWND>(info.childs[i]->window), classname_, _countof(classname_));
        if (_tcscmp(classname_, classname) == 0)
        {
            tmp.push_back(info.childs[i]);
        }
    }
    for (const auto& each : tmp)
    {
        result.push_back(each);
    }
    return 0;
}
int getwindows(const TCHAR* classname,
    const std::vector<std::shared_ptr<gprocess::WindowInfo>>& windows,
    std::vector<std::shared_ptr<gprocess::WindowInfo>>& result)
{
    std::vector<std::shared_ptr<gprocess::WindowInfo>> tmp;
    for (int i = 0; i < windows.size(); ++i)
    {
        getwindows(classname, *windows[i], tmp);
    }
    for (const auto& each : tmp)
    {
        result.push_back(each);
    }
    return 0;
}

int main(int argc, char** argv)
{
    libvlc_instance_t* inst_ = nullptr;
    libvlc_media_t* media_ = nullptr;
    libvlc_media_player_t* player_ = nullptr;
    libvlc_media_list_t* list_ = nullptr;
    libvlc_media_list_player_t* plist_ = nullptr;
    HWND wnd_ = nullptr;

    std::vector<gprocess::ProcessInfo> result;
    gprocess::WindowInfo windowinfo;
    std::vector<std::shared_ptr<gprocess::WindowInfo>> windows;
    std::vector<std::shared_ptr<gprocess::WindowInfo>> tmpwindows;
    auto ret = gprocess::gethandle("Taskmgr.exe", result);
    CHECKNEQUALRET(ret, 0);
    windowinfo.processid = result[0].processid;
    ret = gprocess::getallwindows(&windowinfo);
    CHECKNEQUALRET(ret, 0);

    ret = getwindows(TEXT("TaskManagerWindow"), windowinfo, windows);
    CHECKNEQUALRET(ret, 0);
    ret = getwindows(TEXT("NativeHWNDHost"), windows, tmpwindows);
    CHECKNEQUALRET(ret, 0);
    windows.clear();
    windows.swap(tmpwindows);
    ret = getwindows(TEXT("DirectUIHWND"), windows, tmpwindows);
    CHECKNEQUALRET(ret, 0);
    windows.clear();
    windows.swap(tmpwindows);
    ret = getwindows(TEXT("CvChartWindow"), windows, tmpwindows);
    CHECKNEQUALRET(ret, 0);
    CHECKEQUALRET(tmpwindows.size(), 0);

    wnd_ = reinterpret_cast<HWND>(tmpwindows[tmpwindows.size() - 1]->window);

    inst_ = libvlc_new(0, nullptr);
    CHECKEQUALRET(inst_, nullptr);
    media_ = libvlc_media_new_path(inst_, argc <= 1 ? "badapple.mp4" : argv[1]);
    CHECKEQUALRET(media_, nullptr);

    //player_ = libvlc_media_player_new_from_media(media_);
    player_ = libvlc_media_player_new(inst_);
    CHECKEQUALRET(player_, nullptr);

    libvlc_media_player_set_hwnd(player_, reinterpret_cast<void*>(wnd_));

    // play loop
    list_ = libvlc_media_list_new(inst_);
    plist_ = libvlc_media_list_player_new(inst_);
    libvlc_media_list_add_media(list_, media_);
    libvlc_media_list_player_set_media_list(plist_, list_);
    libvlc_media_list_player_set_media_player(plist_, player_);
    libvlc_media_list_player_set_playback_mode(plist_, libvlc_playback_mode_loop);
    libvlc_media_list_player_play(plist_);

    std::cin.get();

END:
    if (player_ != nullptr)
    {
        libvlc_media_player_stop(player_);
        libvlc_media_player_release(player_);
        player_ = nullptr;
    }
    if (media_ != nullptr)
    {
        libvlc_media_release(media_);
        media_ = nullptr;
    }

    if (plist_ != nullptr)
    {
        libvlc_media_list_player_release(plist_);
        plist_ = nullptr;
    }
    if (list_ != nullptr)
    {
        libvlc_media_list_release(list_);
        list_ = nullptr;
    }
    if (inst_ != nullptr)
    {
        libvlc_release(inst_);
        inst_ = nullptr;
    }
}

Last modified on 2020-04-08