Переключение Фокуса
От: Аноним  
Дата: 29.03.10 11:49
Оценка:
Имею небольшую проблему:

Есть диалог в котором расположены несколько контролов.
Контролы создаются на куче в OnCreate().
Не работало переключение фокуса по нажатию клавиши Tab.
Я занялся извращением и переопределил метод PreTranslateMessage(), в котором по нажатию клавиши Tab переключал фокус вручную путем m_pControl->SetFocus();

Но тут появилась вторая проблема — фокус переключается, но не отрисовывается FocusRect (Рамочка фокуса). Использовать DrawFocusRect() не предлагать. Я конечно извращенец, но не до такой же степени.

Помогите пожалуйста с этим болотом под названием MFC

30.03.10 03:31: Перенесено модератором из 'Пользовательский интерфейс: проектирование, usability' — Кодт
Re: Переключение Фокуса
От: Кодт Россия  
Дата: 29.03.10 23:32
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Помогите пожалуйста с этим болотом под названием MFC


Это не болото, это ты забыл им стиль WS_TABSTOP включить, наверно.
Перекуём баги на фичи!
Re: Переключение Фокуса
От: zitz  
Дата: 30.03.10 05:40
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Имею небольшую проблему:


А>Есть диалог в котором расположены несколько контролов.

А>Контролы создаются на куче в OnCreate().
А>Не работало переключение фокуса по нажатию клавиши Tab.
А>Я занялся извращением и переопределил метод PreTranslateMessage(), в котором по нажатию клавиши Tab переключал фокус вручную путем m_pControl->SetFocus();

А>Но тут появилась вторая проблема — фокус переключается, но не отрисовывается FocusRect (Рамочка фокуса). Использовать DrawFocusRect() не предлагать. Я конечно извращенец, но не до такой же степени.


А>Помогите пожалуйста с этим болотом под названием MFC


BOOL CDlgXXX::PreTranslateMessage( MSG* pMsg )
{
if ( WM_KEYDOWN == pMsg->message || WM_SYSKEYDOWN == pMsg->message )
{
BOOL isShift = GetAsyncKeyState( VK_SHIFT ) < 0;
BOOL isCtrl = GetAsyncKeyState( VK_CONTROL ) < 0;
BOOL isAlt = GetAsyncKeyState( VK_MENU ) < 0;
if ( pMsg->wParam == VK_TAB && !isCtrl && !isAlt && !isShift )
{
CDialog* pParent = (CDialog*)GetParent();
if ( pParent != NULL )
{
if ( m_hWndNextTab != NULL )
{
pParent->PostMessage( WM_NEXTDLGCTL, (WPARAM)m_hWndNextTab, TRUE );
return TRUE;
}
}
}
else if ( pMsg->wParam == VK_TAB && !isCtrl && !isAlt && isShift )
{
CDialog* pParent = (CDialog*)GetParent();
if ( pParent != NULL )
{
if ( m_hWndPrevTab != NULL )
{
pParent->PostMessage( WM_NEXTDLGCTL, (WPARAM)m_hWndPrevTab, TRUE );
return TRUE;
}
}
}
}
return CButton::PreTranslateMessage( pMsg );
}
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[2]: Переключение Фокуса
От: zitz  
Дата: 30.03.10 05:40
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Это не болото, это ты забыл им стиль WS_TABSTOP включить, наверно.


Вот у меня такой вопрос, если создавать контролы динамически то у них перемещение по Tab в порядке создания будет — у меня была задача сделать между кнопками диалога свой динамический контрол, так беда в том что таб ордер он получает последний, а нужно чтобы следующий за кнопкой. Как это победить?
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[2]: Переключение Фокуса
От: zitz  
Дата: 30.03.10 05:42
Оценка: 1 (1)
Поправьте пожалуйста форматирование

Смысл в том что нужно вызывать не SetFocus, а WM_NEXTDLGCTL
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[2]: Переключение Фокуса
От: antonew  
Дата: 30.03.10 07:56
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Аноним, Вы писали:


А>>Помогите пожалуйста с этим болотом под названием MFC


К>Это не болото, это ты забыл им стиль WS_TABSTOP включить, наверно



Стиль какраз-таки стоит везде. Проблема в другом. В настройках виндовз есть опция отключения этой рамочки по-умолчанию. Она появляется если нажать alt. Можно отключить ее и тогда рамочка будет видна всегда.

Например в ХР — правый щелчек по десктопу -> свойства -> оформления -> эффекты
там есть чекбокс соответствующий.

Возникает логичный вопрос — можно как-нить включить эту рамку для конкретного диалога, не изменяя настроек винды в реестре. Можно в принципе слать WM_KEYDOWN — VK_ALT, но это как-то не кашерно )
Re[3]: Переключение Фокуса
От: antonew  
Дата: 30.03.10 08:35
Оценка:
Здравствуйте, zitz, Вы писали:

Z>Поправьте пожалуйста форматирование


Z>Смысл в том что нужно вызывать не SetFocus, а WM_NEXTDLGCTL


Спасибо, я помню пробовал и такой вариант, но фокус не переключается. Вполне возможно что я делал что-то неправильно. Но смысл был у меня такой же как и в вашенм примере.

Приходится изворачиваться через SetFocus().
Re[3]: Переключение Фокуса
От: AstroMan  
Дата: 30.03.10 18:09
Оценка: 2 (1)
Z>Вот у меня такой вопрос, если создавать контролы динамически то у них перемещение по Tab в порядке создания будет — у меня была задача сделать между кнопками диалога свой динамический контрол, так беда в том что таб ордер он получает последний, а нужно чтобы следующий за кнопкой. Как это победить?

Победить это можно вызовом SetWindowPos, меняя z-ордер контрола. Табордер в диалоге — он же z-order.
Re[3]: Переключение Фокуса
От: AstroMan  
Дата: 30.03.10 18:10
Оценка:
A>Стиль какраз-таки стоит везде. Проблема в другом. В настройках виндовз есть опция отключения этой рамочки по-умолчанию. Она появляется если нажать alt. Можно отключить ее и тогда рамочка будет видна всегда.

A>Например в ХР — правый щелчек по десктопу -> свойства -> оформления -> эффекты

A>там есть чекбокс соответствующий.

A>Возникает логичный вопрос — можно как-нить включить эту рамку для конкретного диалога, не изменяя настроек винды в реестре. Можно в принципе слать WM_KEYDOWN — VK_ALT, но это как-то не кашерно )


Смотри в сторону сообщений WM_CHANGEUISTATE, WM_UPDATEUISTATE и т.д.
Re[2]: Переключение Фокуса
От: AstroMan  
Дата: 30.03.10 18:14
Оценка:
А>>Я занялся извращением и переопределил метод PreTranslateMessage(), в котором по нажатию клавиши Tab переключал фокус вручную путем m_pControl->SetFocus();

А вот это делать не надо. Не отбирайте хлеб у функции IsDialogMessage.
Она вызывается в CDialog::PreTranslateMessage() и прекрасно справляется с переключением фокуса и
другими особенностями диалоговых окон.
Re[4]: Переключение Фокуса
От: zitz  
Дата: 01.04.10 09:10
Оценка:
Здравствуйте, AstroMan, Вы писали:

AM>Победить это можно вызовом SetWindowPos, меняя z-ордер контрола. Табордер в диалоге — он же z-order.


Вах!
Спасибо, добрый человек!
Всё работает!
    m_btn.Create( _T("Button"), WS_CHILD | WS_VISIBLE | WS_TABSTOP, CRect( 50, 50, 200, 100 ), this, 1111 );
    m_btn.SetWindowPos( GetDlgItem( IDOK ),
                        0,
                        0,
                        0,
                        0,
                        SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
... << RSDN@Home 1.2.0 alpha rev. 786>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.