zoukankan      html  css  js  c++  java
  • 一个查找窗口和子窗口的MFC类

    参考了其他博主的代码修改而成,直接上源代码吧:

    #pragma once
    #include "MfcStrFile.h"
    
    //标题中包含szWindTitle的窗口
    bool FindWindowTitle(const char* szWindTitle, HWND& wDstHWnd, const char* szWindClass = nullptr);
    bool FindSubWindowTitle(const char* szWindTitle, HWND& wHWndParent, HWND& wDstHWnd, const char* szWindClass = nullptr);
    
    class CMonitorWindow
    {
    public:
        CMonitorWindow(){}
        bool MonitorWindowClose(HWND& wHWnd, DWORD dwMilliseconds = INFINITE);
    
    private:
        static void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime );
        static UINT WaitWorker(LPVOID lParam);
    
    private:
        static HANDLE g_hEvent;
        static DWORD g_nWaitRes;
    };

    然后是cpp文件:

    #include "FindWindowTitle.h"
    #include "tlhelp32.h"
    #include <vector>
    #include "Log.h"
    
    #pragma region 依赖
    
    typedef struct EnumHWndsArg
    {
        std::vector<HWND> *vecHWnds;
        DWORD dwProcessId;
    }EnumHWndsArg, *LPEnumHWndsArg;
    
    // 判断窗口是否属于目标进程
    BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam)
    {
        EnumHWndsArg *pArg = (LPEnumHWndsArg)lParam;
        DWORD  processId;
    
        // 检索窗口线程标识符
        GetWindowThreadProcessId(
            hwnd,            // 窗口句柄
            &processId        // 接收 PID 的指针
            );
    
        // 如果这个 HWND 属于这个 PID ,则加入到 vecHWnds 数组末尾
        if (processId == pArg->dwProcessId){pArg->vecHWnds->push_back(hwnd);}
    
        return TRUE;
    }
    
    // 根据 PID 获取 HWND
    void GetHWndsByProcessID(DWORD processID, std::vector<HWND> &vecHWnds)
    {
        EnumHWndsArg wi;
        wi.dwProcessId = processID;
        wi.vecHWnds = &vecHWnds;
    
        // 枚举所有顶级窗口
        EnumWindows(
            lpEnumFunc,        // 回调函数指针
            (LPARAM)&wi        // 传递给回调函数的值
            );
    }
    
    #pragma endregion
    
    
    bool FindWindowTitle(const char* szWindTitle, HWND& wDstHWnd, const char* szWindClass /*= nullptr*/)
    {
        HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
        PROCESSENTRY32 process = {sizeof(PROCESSENTRY32)};
        
        // 遍历进程
        while (Process32Next(hProcessSnap,&process))
        {
            std::string processName = process.szExeFile;        // 进程名
            std::vector<HWND> vecHWnds;                    // 进程下的窗体句柄数组
            GetHWndsByProcessID(process.th32ProcessID,vecHWnds);
            
            // 获取 HWND 窗口标题、窗口类名
            TCHAR szBuf_title[MAX_PATH];
            TCHAR szBuf_class[MAX_PATH];
            size_t nWindCount = vecHWnds.size();
            for (size_t i = 0; i < nWindCount; ++i)
            {
                const HWND &h = vecHWnds[i];
                GetWindowText(
                h,                    // 窗口句柄
                szBuf_title,        // 接收窗口标题的缓冲区指针
                MAX_PATH            // 缓冲区字节大小
                );
                GetClassName(
                h,                    // 窗口句柄
                szBuf_class,        // 接收窗口类名的缓冲区指针
                MAX_PATH            // 缓冲区字节大小
                );
    
                std::string stBuftitle(szBuf_title);
                std::string stWindTitle(szWindTitle);
    
                if (szWindClass == nullptr)
                {
                    //只考虑标题
                    if (stBuftitle.find(szWindTitle) != std::string::npos)
                    {
                        wDstHWnd = h;
                        return true;
                    }
                }
                else
                {
                    //同时考虑标题和类名
                    if (stBuftitle.find(szWindTitle) != std::string::npos && strcmp(szBuf_class, szWindClass) == 0)
                    {
                        wDstHWnd = h;
                        return true;
                    }
                }
    
                //TRACE(szBuf_title + ' ');
                //TRACE(szBuf_class + '
    ');
                
                // 输出结果    
                //cout << "szBuf_title = " << szBuf_title << endl;
                //cout << "szBuf_class = " << szBuf_class << endl;
                //cout << "--------------------------------------------" << endl;
            }
        }
        
        return false;
    }
    
    bool FindSubWindowTitle(const char* szWindTitle, HWND& wHWndParent, HWND& wDstHWnd, const char* szWindClass /*= nullptr*/)
    {
        if (wHWndParent == nullptr)
        {
            return false;
        }
    
        HWND childWindow = GetWindow(wHWndParent, GW_CHILD);
    
        TCHAR szBuf_title[MAX_PATH];
        TCHAR szBuf_class[MAX_PATH];
    
        int nWindowCount = 1;
    
        while (childWindow)
        {
            const HWND &h = childWindow;
            GetWindowText(
                h,                    // 窗口句柄
                szBuf_title,        // 接收窗口标题的缓冲区指针
                MAX_PATH            // 缓冲区字节大小
                );
            GetClassName(
                h,                    // 窗口句柄
                szBuf_class,        // 接收窗口类名的缓冲区指针
                MAX_PATH            // 缓冲区字节大小
                );
    
            std::string stBuftitle(szBuf_title);
            std::string stWindTitle(szWindTitle);
            CLOG::Out(_T("%d %s"), nWindowCount, szBuf_title);
            CLOG::Out(_T("%d %s"), nWindowCount++, szBuf_class);
    
            if (szWindClass == nullptr)
            {
                //只考虑标题
                if (stBuftitle.find(szWindTitle) != std::string::npos)
                {
                    wDstHWnd = h;
                    return true;
                }
            }
            else
            {
                //同时考虑标题和类名
                if (stBuftitle.find(szWindTitle) != std::string::npos && strcmp(szBuf_class, szWindClass) == 0)
                {
                    wDstHWnd = h;
                    return true;
                }
            }
    
            childWindow = GetNextWindow(childWindow, GW_HWNDNEXT);
        }
    
        return false;
    }
    
    HANDLE CMonitorWindow::g_hEvent;
    DWORD CMonitorWindow::g_nWaitRes;
    
    //传递参数
    typedef struct _lPara
    {
        HWND pDoc;
        DWORD dTimeout;
    }lPara;
    
    //定时器
    void CALLBACK CMonitorWindow::TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime )
    {
        TRACE("TimerProc");
        SetEvent(g_hEvent);
    }
    
    UINT  CMonitorWindow::WaitWorker(LPVOID  lParam)
    {
        DWORD dTimeout = 6000;
        HWND hWnd = nullptr;
    
        if (lParam)
        {
            lPara* lp = (lPara*)lParam;
            dTimeout = lp->dTimeout;
            hWnd = lp->pDoc;
        }
    
        //启动定时器1,定时时间是1秒,注意SetTimer在线程中设置无效
        //SetTimer(hWind, 1, 1000, (TIMERPROC)TimerProc);//用回调函数处理,此时对话框的消息处理函数不再处理。
    
        for(;;)
        {
            TRACE("%s, %d
    ", "monitoring...", hWnd);
            if (!::IsWindow(hWnd) || !::IsWindowVisible(hWnd))
            {
                TRACE("window closed!");
                SetEvent(g_hEvent);
                break;
            }
    
            Sleep(1000);
    
            if (WAIT_TIMEOUT == g_nWaitRes)
            {
                break;
            }
        }
    
        //KillTimer(nullptr, 1);
    
        return 0;
    }
    
    bool CMonitorWindow::MonitorWindowClose(HWND& wHWnd, DWORD dwMilliseconds /*= INFINITE*/)
    {
        if (wHWnd == nullptr)
        {
            return true;
        }
    
        //默认等待失败
        g_nWaitRes = WAIT_FAILED;
    
        lPara lp;
        lp.pDoc = wHWnd;
        lp.dTimeout = dwMilliseconds;
    
        //创建等待事件
        g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    
        AfxBeginThread(WaitWorker, (LPVOID)&lp);//启动新的线程
    
        g_nWaitRes = WaitForSingleObject(g_hEvent, dwMilliseconds);
    
        switch (g_nWaitRes)
        {
        case WAIT_OBJECT_0:
            TRACE("wait success!");
            break;
    
        case WAIT_TIMEOUT:
            TRACE("wait timeout!");
            break;
    
        case WAIT_FAILED:
            TRACE("wait failed!");
            //函数调用失败,比如传递了一个无效的句柄
            break;
        }
    
        ResetEvent(g_hEvent);
    
        return g_nWaitRes == WAIT_OBJECT_0;
    }

    希望能帮助到你。

  • 相关阅读:
    Qt生成随机数
    Qt调用系统DLL,判断网络连接状态
    Qt操作sqlite数据库
    Qt 操作注册表
    vs报错:RC1004 unexpected end of file found
    Qt操作ini文件
    Django Admin:自动选择当前用户
    BSTR转QString
    vue-cli4,vue3打包后页面无内容
    Qt 5.12.10 国际化
  • 原文地址:https://www.cnblogs.com/autumoonchina/p/13230264.html
Copyright © 2011-2022 走看看