Debugging WIN32 focus bugs

前端 未结 3 711
死守一世寂寞
死守一世寂寞 2021-01-21 19:25

I\'m developing a WIN32/C++ application containing a main window and a lot of child windows, and I\'m looking for tools that could assist me in tracking down focus bugs.

3条回答
  •  栀梦
    栀梦 (楼主)
    2021-01-21 19:59

    A Spy++ message log will give a complete record of focus changes, but trying to decode what was happening from the log is a chore. Spy++'s nasty UI doesn't help.

    Remote debugging is helpful because the debugger won't interfere with your application's activation and focus, but I'm not sure there's a simple way to determine the focused window from the debugger. Here are a couple of articles on configuring it. Hint: if it doesn't work, double-check your DCOM and firewall settings.

    Obviously it would be best to find a tool that does exactly what you want but I couldn't and I was bored so I wrote this code. It creates a semi-transparent blue window that sits on top of the focused control. It's transparent to clicks so it shouldn't interfere with using your app.

    To initialise it simply create a timer somewhere in your program's initialisation code:

    // Check the focus ten times a second
    // Change hwndMain to your main application window
    // Note that this won't work if you have multiple UI threads
    ::SetTimer(hwndMain, 1, 100, HighlightTimerProc);
    

    and add the following code:

    LRESULT CALLBACK HighlightWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_NCHITTEST:
            return HTTRANSPARENT;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }
    
    VOID CALLBACK HighlightTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
    {
        // static locals are bad
        static bool initialised = false;
        static HWND hwndHighlight = 0;
    
        if (!initialised)
        {
            HINSTANCE hInstance = 0;
    
            WNDCLASSEX wcex;
    
            wcex.cbSize = sizeof(WNDCLASSEX);
    
            wcex.style          = CS_HREDRAW | CS_VREDRAW;
            wcex.lpfnWndProc    = HighlightWndProc;
            wcex.cbClsExtra     = 0;
            wcex.cbWndExtra     = 0;
            wcex.hInstance      = hInstance;
            wcex.hIcon          = 0;
            wcex.hCursor        = 0;
            wcex.hbrBackground  = (HBRUSH)(COLOR_HIGHLIGHTTEXT);
            wcex.lpszMenuName   = 0;
            wcex.lpszClassName  = L"HighlightWindowClasss";
            wcex.hIconSm        = 0;
    
            ATOM atomHighlightClass = RegisterClassEx(&wcex);
    
            hwndHighlight = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW,
                (LPCTSTR)atomHighlightClass, L"", WS_POPUP,
                CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    
            // Set opacity to 200/255
            SetLayeredWindowAttributes(hwndHighlight, 0, 200, LWA_ALPHA);
    
            initialised = true;
        }
    
        static HWND hwndCurrentHighlight = 0;
    
        HWND hwndFocus = GetFocus();
        if (hwndFocus != hwndCurrentHighlight)
        {
            if (hwndFocus == 0)
            {
                ShowWindow(hwndHighlight, SW_HIDE);
            }
            else
            {
                RECT rect;
                GetWindowRect(hwndFocus, &rect);
                MoveWindow(hwndHighlight, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, false);
                ShowWindow(hwndHighlight, SW_SHOW);
            }
            hwndCurrentHighlight = hwndFocus;
        }
    }
    

提交回复
热议问题