2

Web ブラウザー (Internet Explorer) が組み込まれた Windows アプリがあります。アプリは、IPC を使用して別のプロセスから閉じることができます。組み込みの Web ブラウザーがポップアップ ダイアログ ウィンドウを表示している場合 (コンテンツの保存中など) を除いて、問題なく動作します。その場合、IPC を介して外部要求から閉じようとすると、アプリがクラッシュします。(内部的には、WM_CLOSE メッセージを自分自身にポストするだけです。)

それを踏まえて、プロセスに属するすべてのウィンドウを列挙し、プロセス自体を閉じる前に最初にそれらを閉じる方法を考え出すことにしました。問題は、私のプロセスに属するすべてのウィンドウを、それらを閉じる目的でどのように列挙するのですか?

4

2 に答える 2

3

OK、私はそれを自分で手に入れたと思います。誰かが興味を持っている場合は次のとおりです。

#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 に答える