2

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

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

4

2 回答 2

3

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

#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;
}
于 2011-10-24T01:38:18.997 回答
2

当您希望您的进程退出时,只需调用ExitProcess. 不管当时打开什么窗户,它们都会消失。

于 2011-10-24T00:18:55.757 回答