Отладка ошибок фокуса WIN32 - PullRequest
2 голосов
/ 15 января 2012

Я занимаюсь разработкой приложения WIN32 / C ++, содержащего главное окно и множество дочерних окон, и ищу инструменты, которые могли бы помочь мне отследить ошибки фокусировки.

В частности, мне нужен инструмент, который может выделить элемент управления, который в данный момент имеет фокус (или сказать мне, что ни один элемент управления в настоящее время не имеет фокуса). Также я где-то читал, что использование удаленного отладчика может помочь в такого рода ошибках. Есть идеи, как это сделать?

ОБНОВЛЕНИЕ : Джеффри Рихтер в 1997 году написал статью, в которой, помимо прочего, содержится инструмент для нахождения фокуса: http://www.microsoft.com/msj/0397/Win32/Win320397.aspx

Ответы [ 3 ]

4 голосов
/ 15 января 2012

Журнал сообщений Spy ++ даст полную запись изменений фокуса, но попытка расшифровать то, что происходило из журнала, является рутиной. Противный интерфейс Spy ++ не помогает.

Удаленная отладка полезна, потому что отладчик не будет мешать активации и фокусировке вашего приложения, но я не уверен, что есть простой способ определить сфокусированное окно из отладчика. Вот пара из статей о его настройке. Подсказка: если это не работает, перепроверьте настройки DCOM и брандмауэра.

Очевидно, что было бы лучше найти инструмент, который делает именно то, что вы хотите, но я не смог, и мне было скучно, поэтому я написал этот код. Это создает полупрозрачное синее окно, которое находится сверху сфокусированного элемента управления. Он прозрачен для кликов, поэтому не должен мешать работе вашего приложения.

Чтобы инициализировать его, просто создайте таймер где-нибудь в коде инициализации вашей программы:

// 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);

и добавьте следующий код:

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;
    }
}
3 голосов
/ 16 января 2012

Инструмент Inspect , являющийся частью загрузки Windows SDK, может быть полезен здесь.Он предназначен для тестирования двух API-интерфейсов, связанных с расширенными возможностями - MSAA и UI Automation, - и одна из вещей, к которым эти API-интерфейсы, - это доступность и инструменты тестирования, позволяющие отслеживать фокус.для отслеживания фокуса необходимо перевести его в режим MSAA, установите флажки, чтобы отслеживать только изменения фокуса (т. е. отключить по указателю мыши), затем включите желтый прямоугольник выделения.Теперь, когда фокус меняется, вы можете видеть движение прямоугольника.В качестве бонуса, если фокус переходит к чему-то скрытому или закадровому, вы не увидите прямоугольник, но имя и класс элемента управления Win32 будут отображены в окне.

Обратите внимание, что Inspect отображает надмножествособытий фокуса: вы получаете не только изменения фокуса HWND, но и уведомления, когда фокус перемещается в определенных элементах управления - например, между элементами в списке.Это нужно автоматическому тестированию и доступности, но для ваших целей вам следует просто игнорировать их;это дополнительная информация, но она не должна слишком сильно мешать.

0 голосов
/ 15 января 2012

Я думаю, что вы можете использовать Spy ++, который является частью Visual Studio или Windows SDK.Он сообщает вам много другой информации, вы также можете захватывать сообщения, отправленные в выбранное окно.

http://msdn.microsoft.com/en-us/library/dd460760.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...