C++/Win32 枚举属于我的进程的窗口 &关闭它们

发布于 2024-12-11 15:49:34 字数 275 浏览 0 评论 0原文

我有一个 Windows 应用程序,其中嵌入了一个 Web 浏览器(Internet Explorer)。可以通过 IPC 从另一个进程关闭该应用程序。除了嵌入式 Web 浏览器可能显示弹出对话框窗口(例如,在保存内容期间)的情况外,它工作得很好。在这种情况下,当我的应用程序尝试通过 IPC 关闭外部请求时,它会崩溃。 (在内部,它只是将 WM_CLOSE 消息发送给自身。)

鉴于此,我想提出一种方法来枚举属于我的进程的所有窗口,并在关闭我的进程本身之前先关闭它们。问题是,如何枚举属于我的进程的所有窗口以关闭它们?

I have a Windows app that houses a web browser (Internet explorer) embedded in it. The app can be closed from another process by means of IPC. It works just fine except the situation when the embedded web browser may be displaying a pop-up dialog window (say, during saving of contents). In that case my app crashes when it tries to close from an outside request via IPC. (Internally it simply posts the WM_CLOSE message to itself.)

In light of that I thought to come up with a way to enumerate all windows that belong to my process and close them first before closing my process itself. The question is, how do you enumerate all windows belonging to my process for the purpose of closing them?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

农村范ル 2024-12-18 15:49:34

好吧,我想我自己得到了。如果有人感兴趣的话,这是:

#define SIZEOF(f) (sizeof(f) / sizeof(f[0]))
typedef struct _ENUM_POPUPS_INFO{
    DWORD dwProcID;
    HWND hThisWnd;
    int nNextHWNDIndex;
    HWND hFoundHWNDs[256];
}ENUM_POPUPS_INFO;

void CloseAllOpenPopups(HWND hWnd, int dwmsWait)
{
    //'hWnd' = our main window handle (we won't close it)
    //'dwmsWait' = maximum wait time in milliseconds, or -1 to wait for as long as needed
    ENUM_POPUPS_INFO epi = {0};
    BOOL bR;
    int i, iIteration;
    HWND hWndRoot, hWndActivePopup;

    DWORD dwmsTickBegin = GetTickCount();

    for(iIteration = 0;; iIteration = 1)
    {
        //Get our process ID
        memset(&epi, 0, sizeof(epi));
        epi.hThisWnd = hWnd;
        epi.dwProcID = GetCurrentProcessId();

        bR = EnumWindows(EnumPopupWindowsProc, (LPARAM)&epi);

        //Did we get any
        if(epi.nNextHWNDIndex == 0)
            break;

        //Wait on a second and later iteration
        if(iIteration > 0)
        {
            if(dwmsWait != -1)
            {
                DWORD dwmsTick = GetTickCount();
                int nmsDiff = abs((long)(dwmsTick - dwmsTickBegin));
                if(nmsDiff >= dwmsWait)
                {
                        //Timed out
                break;
                }

                //Wait
                Sleep(min(100, dwmsWait - nmsDiff));
            }
            else
            {
                //Wait
                Sleep(100);
            }
        }

        //Go through all windows found
            for(i = 0; i < epi.nNextHWNDIndex; i++)
        {
            //Get root owner
            hWndRoot = GetAncestor(epi.hFoundHWNDs[i], GA_ROOTOWNER);
            if(!hWndRoot)
                continue;

            //Get it's active popup
            hWndActivePopup = GetLastActivePopup(hWndRoot);
            if(!hWndActivePopup)
                continue;

            //Close it
            PostMessage(hWndActivePopup, WM_CLOSE, 0, 0);
        }
    }
}    


BOOL CALLBACK EnumPopupWindowsProc(HWND hWnd, LPARAM lParam)
{
    ENUM_POPUPS_INFO* pEPI = (ENUM_POPUPS_INFO*)lParam;

    //Get process ID of the window
    DWORD dwProcID = 0;
    GetWindowThreadProcessId(hWnd, &dwProcID);

    //We need this window only if it's our process
    if(dwProcID == pEPI->dwProcID &&
        pEPI->hThisWnd != hWnd &&
        ((GetWindowLongPtr(hWnd, GWL_STYLE) & (WS_VISIBLE | WS_POPUP | WS_CAPTION)) == (WS_VISIBLE | WS_POPUP | WS_CAPTION)))
    {
        if(pEPI->nNextHWNDIndex >= SIZEOF(pEPI->hFoundHWNDs))
        {
            //Stop, we're full
            return FALSE;
        }

        //Add it
        pEPI->hFoundHWNDs[pEPI->nNextHWNDIndex] = hWnd;
        pEPI->nNextHWNDIndex++;
    }

    return TRUE;
}

OK, I guess I got it myself. Here's if someone is interested:

#define SIZEOF(f) (sizeof(f) / sizeof(f[0]))
typedef struct _ENUM_POPUPS_INFO{
    DWORD dwProcID;
    HWND hThisWnd;
    int nNextHWNDIndex;
    HWND hFoundHWNDs[256];
}ENUM_POPUPS_INFO;

void CloseAllOpenPopups(HWND hWnd, int dwmsWait)
{
    //'hWnd' = our main window handle (we won't close it)
    //'dwmsWait' = maximum wait time in milliseconds, or -1 to wait for as long as needed
    ENUM_POPUPS_INFO epi = {0};
    BOOL bR;
    int i, iIteration;
    HWND hWndRoot, hWndActivePopup;

    DWORD dwmsTickBegin = GetTickCount();

    for(iIteration = 0;; iIteration = 1)
    {
        //Get our process ID
        memset(&epi, 0, sizeof(epi));
        epi.hThisWnd = hWnd;
        epi.dwProcID = GetCurrentProcessId();

        bR = EnumWindows(EnumPopupWindowsProc, (LPARAM)&epi);

        //Did we get any
        if(epi.nNextHWNDIndex == 0)
            break;

        //Wait on a second and later iteration
        if(iIteration > 0)
        {
            if(dwmsWait != -1)
            {
                DWORD dwmsTick = GetTickCount();
                int nmsDiff = abs((long)(dwmsTick - dwmsTickBegin));
                if(nmsDiff >= dwmsWait)
                {
                        //Timed out
                break;
                }

                //Wait
                Sleep(min(100, dwmsWait - nmsDiff));
            }
            else
            {
                //Wait
                Sleep(100);
            }
        }

        //Go through all windows found
            for(i = 0; i < epi.nNextHWNDIndex; i++)
        {
            //Get root owner
            hWndRoot = GetAncestor(epi.hFoundHWNDs[i], GA_ROOTOWNER);
            if(!hWndRoot)
                continue;

            //Get it's active popup
            hWndActivePopup = GetLastActivePopup(hWndRoot);
            if(!hWndActivePopup)
                continue;

            //Close it
            PostMessage(hWndActivePopup, WM_CLOSE, 0, 0);
        }
    }
}    


BOOL CALLBACK EnumPopupWindowsProc(HWND hWnd, LPARAM lParam)
{
    ENUM_POPUPS_INFO* pEPI = (ENUM_POPUPS_INFO*)lParam;

    //Get process ID of the window
    DWORD dwProcID = 0;
    GetWindowThreadProcessId(hWnd, &dwProcID);

    //We need this window only if it's our process
    if(dwProcID == pEPI->dwProcID &&
        pEPI->hThisWnd != hWnd &&
        ((GetWindowLongPtr(hWnd, GWL_STYLE) & (WS_VISIBLE | WS_POPUP | WS_CAPTION)) == (WS_VISIBLE | WS_POPUP | WS_CAPTION)))
    {
        if(pEPI->nNextHWNDIndex >= SIZEOF(pEPI->hFoundHWNDs))
        {
            //Stop, we're full
            return FALSE;
        }

        //Add it
        pEPI->hFoundHWNDs[pEPI->nNextHWNDIndex] = hWnd;
        pEPI->nNextHWNDIndex++;
    }

    return TRUE;
}
星星的軌跡 2024-12-18 15:49:34

当您希望进程退出时,只需调用ExitProcess即可。无论当时打开什么窗口,它们都会消失。

When you want your process to exit, just call ExitProcess. It doesn't matter what windows might be open at the time, they all go away.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文