Как убить фокус элемента управления "edit" при нажатии клавиши "Enter"

У меня есть главное окно, созданное в основной функции. В процедуре для главного окна в сообщении WM_CREATE я создаю элемент управления для редактирования, который как дочерний элемент родительского окна использует системный класс окна "edit". Я хочу, чтобы фокус переместился в главное окно при нажатии клавиши ввода в элементе управления редактированием. Поскольку я использовал системный класс, у меня нет доступа к его процедуре. Я использую C++ для этого в Visual Studio 10 Так как я новичок в приложениях win32, я хочу простое решение независимо от того, как долго код

1 ответ

Решение

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

Поэтому сначала вам нужно добавить еще один фокусируемый элемент управления в ваше окно, если у вас его еще нет (я не могу сказать по вопросу). Например, вы можете добавить кнопку "ОК" или "Отмена". Таким образом, когда вы отменяете фокусировку элемента управления, кнопка может получить фокус.

Затем вам нужно будет создать подкласс для элемента управления редактирования, чтобы вы могли обрабатывать события нажатия клавиш (например, WM_KEYDOWN а также WM_KEYUP). Чтобы создать подкласс одного окна, вызовите SetWindowLongPtr функции и передать дескриптор окна вместе с GWLP_WNDPROC флаг и указатель на вашу пользовательскую оконную процедуру. Это эффективно заменяет оконную процедуру по умолчанию для этого класса управления вашей пользовательской оконной процедурой. Например:

// Stores the old original window procedure for the edit control.
WNDPROC wpOldEditProc;

// The new custom window procedure for the edit control.
LRESULT CALLBACK CustomEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_KEYDOWN:
        {
            if (wParam == VK_RETURN)
            {
                // The user pressed Enter, so set the focus to the other control
                // on the window (where 'hwndOther' is a handle to that window).
                SetFocus(hwndOther);

                // Indicate that we processed the message.
                return 0;
            }
        }
    }

    // Pass the messages we don't process here on to the
    // original window procedure for default handling.
    CallWindowProc(wpOldEditProc, hWnd, msg, wParam, lParam);
}
// ----- Add to the parent window's WM_CREATE: -----

// Create the edit control
HWND hwndEdit = CreateWindowEx(...);

// Subclass it.
wpOldEditProc = (WNDPROC)SetWindowLongPtr(hwndEdit,
                                          GWLP_WNDPROC,
                                          (LONG_PTR)CustomEditProc);

// Show it.
ShowWindow(hwndEdit, SW_SHOW);

// ... your other code (e.g. creating and showing the other control)
// ----- Add to the parent window's WM_DESTROY: -----

// Unsubclass the edit control.
SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR)wpOldEditProc);

// ... your other code (e.g. calling PostQuitMessage(...) to close your app)

Дальнейшее чтение о окнах подклассов здесь на MSDN. Пример кода там (и во многих других местах в Интернете) предполагает, что вы подклассифицируете элемент управления редактирования в диалоговом окне. Поскольку диалоговые окна представляют собой особые типы родительских окон, которые автоматически выполняют большую часть обработки с клавиатуры, вам необходимо предпринять дополнительные шаги, чтобы преодолеть эту обработку по умолчанию, выполняемую диалогом. Если вы используете обычное окно, созданное с CreateWindowEx, это не обязательно.

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

Но я не буду вдаваться в подробности, как это сделать здесь. Вы можете найти код в Интернете, если вам интересно, и ваш конкретный вариант использования делает его немного сложнее. Чтобы изменить фокус, элемент управления должен знать, на какой другой элемент управления он должен установить фокус. С этим трудно справиться глобально. Использование диалогового окна в качестве родителя может быть целесообразным. Он управляет Z-порядком и автоматически устанавливает фокус для вас.

Другие вопросы по тегам