【问题标题】:Is there a way to detect if a Window has been flashed?有没有办法检测窗口是否已闪烁?
【发布时间】:2020-08-07 13:36:32
【问题描述】:

使用函数FlashWindowFlashWindowEx,可以使窗口闪烁。但是,我似乎找不到任何可以检测窗口是否已闪烁的 API。有吗?

编辑

鉴于FLASHWINFO 具有DWORD dwFlags,我猜想此信息将存储在窗口中,并且可以使用GetWindowLongWGetWindowLongPtrW 访问,但我无法在那里找到它。

我需要这个的原因是为了自动化。

【问题讨论】:

    标签: windows winapi win32gui


    【解决方案1】:

    根据ShellProc

    lParam [输入]
    类型:LPARAM
    HSHELL_REDRAW 如果窗口闪烁,则值为 TRUE,否则为 FALSE

    所以我们只需要添加一个SetWindowsHookExA 函数来捕获WH_SHELL 消息。

    这是一个示例:

    #include <Windows.h>
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK procShell(int, WPARAM, LPARAM);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        HHOOK hook = SetWindowsHookEx(WH_SHELL, procShell, NULL,GetCurrentThreadId());
        int e = GetLastError();
        static TCHAR szAppName[] = TEXT("Test Flashing");
        HWND hwnd;
        MSG msg;
        WNDCLASS wndclass;
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc = WndProc;
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInstance;
        wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
        if (!RegisterClass(&wndclass))
        {
            MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
        }
    
        hwnd = CreateWindow(szAppName,
            szAppName,
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,
            NULL,
            hInstance,
            NULL);
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
        while (GetMessageW(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
        UnhookWindowsHookEx(hook);
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        case WM_LBUTTONDOWN:
            FlashWindow(hwnd, TRUE);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    LRESULT CALLBACK procShell(int nCode, WPARAM wParam, LPARAM lParam) {
        if (nCode == HSHELL_REDRAW) {
            if (lParam)
            {
                OutputDebugString(L"Window is flashing\n");
            }
        }
        return CallNextHookEx(NULL, nCode, wParam, lParam);
    }
    

    如果我们按下左键,FlashWindow 将被调用。然后钩子函数会得到HSHELL_REDRAW消息并输出:

    【讨论】:

    • 您好,如果这个答案对您有帮助,请随时标记它以帮助遇到相同问题的人,如果您有任何问题,请告诉我。谢谢。
    • 我也遇到了同样的问题,但是闪烁的窗口属于即时通讯应用程序,没有打开代码。 FlashWindow/FlashWindowEx API 在 RDP RemoteApp 上下文中不起作用。我需要运行我的进程来监视该 Messenger 进程的窗口闪烁。
    • @Acewind 您可以发布问题,以便社区可以详细了解您的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多