Кнопка в подклассе не производит анимацию при каждом повторном нажатии - PullRequest
0 голосов
/ 08 сентября 2018

У меня есть пользовательская подклассная кнопка, созданная в сообщении WM_CREATE моего обратного вызова WindowProc. Вот инструкции по созданию и созданию подклассов, а также структура, используемая для управления состоянием кнопки:

static button_state btnstateBtnInstall;
hBtnInstall = CreateWindow(WC_BUTTON, L"Button", WS_CHILD | WS_VISIBLE, (window_width / 2) - (btn_install_width / 2), window_height - (window_height / 6) - (btn_install_height / 2), btn_install_width, btn_install_height, hwnd, (HMENU)HMENU_btn_install, NULL, NULL);
SetWindowSubclass(hBtnInstall, BtnInstallProc, 0, (DWORD_PTR)&btnstateBtnInstall);

Структура определяется следующим образом:

struct button_state
{
    bool pushed;
    button_state() { pushed = false; }
};

Подклассная процедура кодируется следующим образом:

LRESULT CALLBACK BtnInstallProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubClass, DWORD_PTR dwRefData)
{
    button_state* state = (button_state*)dwRefData;

    // Omitted part where I create brushes and font to be used for painting

    switch (msg)
    {
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        RECT rc = ps.rcPaint;

        POINT pt;
        GetCursorPos(&pt);
        ScreenToClient(hwnd, &pt);
        BOOL hover = PtInRect(&rc, pt);

        if (state->pushed)
        {
            // Pushed
            FillRect(hdc, &rc, hBrPushed);
        }
        else if (hover)
        {
            // Mouse over
            FillRect(hdc, &rc, hBrHover);
        }
        else
        {
            // Normal
            FillRect(hdc, &rc, hBrNormal);
        }

        SetBkMode(hdc, TRANSPARENT);
        SetTextColor(hdc, RGB(255, 255, 255));
        SelectFont(hdc, SegoeUI);
        static LPCWSTR InstallBtnTxt = L"Install";
        static int InstallBtnTxtLen = static_cast<int>(wcslen(InstallBtnTxt));  // Should be a safe cast, for small arrays like this one
        DrawText(hdc, InstallBtnTxt, InstallBtnTxtLen, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

        EndPaint(hwnd, &ps);
        return 0;
    }

    case WM_LBUTTONDOWN:
    {
        state->pushed = true;

        break;
    }

    case WM_LBUTTONUP:
    {
        state->pushed = false;

        break;
    }

    // Omitted part where I handle WM_DESTROY to do cleanup

    }

    return DefSubclassProc(hwnd, msg, wParam, lParam);
}

Чтобы сравнить поведение моей кнопки со стандартной, я создал другую кнопку без подклассов и использовал только стандартные атрибуты BUTTON class и WS_VISIBLE | WS_CHILD.

Как вы можете видеть из прикрепленного gif, когда я несколько раз нажимаю на стандартную кнопку класса, каждый щелчок производит анимацию , тогда как при многократном нажатии на кнопку, которую я создал с этим код кажется, что не ловит каждый клик, но (как вы можете видеть) примерно на 50% из них .

Что мне не хватает? Почему моя кнопка не такая отзывчивая, как та, что входит в стандартный класс?

TL; DR : при медленном нажатии на мою кнопку в подклассе, картина будет правильной. Как вы можете видеть из моего прикрепленного изображения, разница между моей и стандартной кнопкой велика при повторном нажатии на них. Как я могу сделать свой контроль таким же отзывчивым, как и стандартный?

enter image description here

1 Ответ

0 голосов
/ 09 сентября 2018

При быстром нажатии некоторые сообщения WM_LBUTTONDOWN заменяются на WM_LBUTTONDBLCLK (обработка двойного щелчка по умолчанию). Вы должны обрабатывать это так же, как вы обрабатываете сообщение WM_LBUTTONDOWN.

case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK: // <-- Added
{
    state->pushed = true;

    break;
}
...