Сообщение Re[7]: Сменна фокуса ввода в новигационном сообщении TVN_SEL от 03.05.2023 14:16
Изменено 03.05.2023 14:17 Carc
Re[7]: Сменна фокуса ввода в новигационном сообщении TVN_SEL
Здравствуйте, Melamed, Вы писали:
M>Окна сделаны в одном потоке. Проверено в Spy++.
C>>2) Что возвращает SetFocus()? Что говорит ::IsWindow(Hwnd куда фокус)?
M>SetFocus возвращает не нулевое значения.
M>После вызова SetFocus() вставил следующую строку
M>
M>Исключения нет. Значит фокус получает окно, которое мне нужно.
C>>3) В оконной процедуре (HWND куда фокус) приходят всякие WM_ACTIVATE? WM_KILLFOCUS в оконную процедуру дерева приходит?
M>Поставил обработчик сообщения WM_KILLFOKUS окно, куда передаю фокус (Благо этот контроль я сам разрабатываю). Он вызывается. Значит окно получает фокус, и почему-то его тут же отдает. По кадру стека понял, что это происходит не в моем коде, а в системном.
M>Самое интересное в сообщении WM_LButtonDown окна, которому передается фокус, функция SetFocus() работает безупречно.
Ну вот и разобрались... Видимо фокус все-таки приходит, но его кто-то забирает.
Что видим в WPARAM в обработчике WM_KILLFOKUS? Там по идее может быть HWND окна, которое забирает фокус.
Хм... Вообще я такие вещи делал несколько иначе. А именно отложенная передача фокуса.
Если в 2-ух словах: то в обработчике TVN_SELCHANGED запоминался выделенный узел (HTREEITEM), и взводился таймер.
А по таймеру проверялось, если выделенный айтем (TVGN_CARET) совпадает с запомненным узлом, то фокус куда-то там в правую панель передавался. Если нет, то нет.
Это было нужно когда-то давно в одной софтине, чтобы переходить куда-то там в правую панель. Причем по выделению узла в дереве при выделении именно с клавы. А таймер был нужен, только для того, чтобы можно было спокойно "бегать" по дереву клавой и фокус и не уходил с дерева мгновенно.
Потом я в той софтине как-то все иначе и очевиднее сделал (клавиши-акселераторы, переход в правую панель по Enter в дереве и.т.п.).
Но сам приём был именно такой.
Технические детали конечно могут различаться: это может быть не таймер, а фоновый спящий поток. Который собсна периодически будится по TVN_SELCHANGED. Ну да это всё нюансы.
Как-то так. Можно попробовать отложенную передачу фокуса, тогда кто-б там не забрал фокус раньше, он все равно должен будет вернуться в окно назначения, ибо по идее это произойдет позже.
M>Окна сделаны в одном потоке. Проверено в Spy++.
C>>2) Что возвращает SetFocus()? Что говорит ::IsWindow(Hwnd куда фокус)?
M>SetFocus возвращает не нулевое значения.
M>После вызова SetFocus() вставил следующую строку
M>
M> Check_Win(SetFocus(m_hwndImageTable));
M> assert(GetFocus() == m_hwndImageTable);
M>M>Исключения нет. Значит фокус получает окно, которое мне нужно.
C>>3) В оконной процедуре (HWND куда фокус) приходят всякие WM_ACTIVATE? WM_KILLFOCUS в оконную процедуру дерева приходит?
M>Поставил обработчик сообщения WM_KILLFOKUS окно, куда передаю фокус (Благо этот контроль я сам разрабатываю). Он вызывается. Значит окно получает фокус, и почему-то его тут же отдает. По кадру стека понял, что это происходит не в моем коде, а в системном.
M>Самое интересное в сообщении WM_LButtonDown окна, которому передается фокус, функция SetFocus() работает безупречно.
Ну вот и разобрались... Видимо фокус все-таки приходит, но его кто-то забирает.
Что видим в WPARAM в обработчике WM_KILLFOKUS? Там по идее может быть HWND окна, которое забирает фокус.
Хм... Вообще я такие вещи делал несколько иначе. А именно отложенная передача фокуса.
Если в 2-ух словах: то в обработчике TVN_SELCHANGED запоминался выделенный узел (HTREEITEM), и взводился таймер.
А по таймеру проверялось, если выделенный айтем (TVGN_CARET) совпадает с запомненным узлом, то фокус куда-то там в правую панель передавался. Если нет, то нет.
Это было нужно когда-то давно в одной софтине, чтобы переходить куда-то там в правую панель. Причем по выделению узла в дереве при выделении именно с клавы. А таймер был нужен, только для того, чтобы можно было спокойно "бегать" по дереву клавой и фокус и не уходил с дерева мгновенно.
Потом я в той софтине как-то все иначе и очевиднее сделал (клавиши-акселераторы, переход в правую панель по Enter в дереве и.т.п.).
Но сам приём был именно такой.
Технические детали конечно могут различаться: это может быть не таймер, а фоновый спящий поток. Который собсна периодически будится по TVN_SELCHANGED. Ну да это всё нюансы.
Как-то так. Можно попробовать отложенную передачу фокуса, тогда кто-б там не забрал фокус раньше, он все равно должен будет вернуться в окно назначения, ибо по идее это произойдет позже.
Re[7]: Сменна фокуса ввода в новигационном сообщении TVN_SEL
Здравствуйте, Melamed, Вы писали:
M>Окна сделаны в одном потоке. Проверено в Spy++.
C>>2) Что возвращает SetFocus()? Что говорит ::IsWindow(Hwnd куда фокус)?
M>SetFocus возвращает не нулевое значения.
M>После вызова SetFocus() вставил следующую строку
M>
M>Исключения нет. Значит фокус получает окно, которое мне нужно.
C>>3) В оконной процедуре (HWND куда фокус) приходят всякие WM_ACTIVATE? WM_KILLFOCUS в оконную процедуру дерева приходит?
M>Поставил обработчик сообщения WM_KILLFOKUS окно, куда передаю фокус (Благо этот контроль я сам разрабатываю). Он вызывается. Значит окно получает фокус, и почему-то его тут же отдает. По кадру стека понял, что это происходит не в моем коде, а в системном.
M>Самое интересное в сообщении WM_LButtonDown окна, которому передается фокус, функция SetFocus() работает безупречно.
Ну вот и разобрались... Видимо фокус все-таки приходит, но его кто-то забирает.
Что видим в WPARAM в обработчике WM_KILLFOCUS? Там по идее может быть HWND окна, которое забирает фокус.
Хм... Вообще я такие вещи делал несколько иначе. А именно отложенная передача фокуса.
Если в 2-ух словах: то в обработчике TVN_SELCHANGED запоминался выделенный узел (HTREEITEM), и взводился таймер.
А по таймеру проверялось, если выделенный айтем (TVGN_CARET) совпадает с запомненным узлом, то фокус куда-то там в правую панель передавался. Если нет, то нет.
Это было нужно когда-то давно в одной софтине, чтобы переходить куда-то там в правую панель. Причем по выделению узла в дереве при выделении именно с клавы. А таймер был нужен, только для того, чтобы можно было спокойно "бегать" по дереву клавой и фокус и не уходил с дерева мгновенно.
Потом я в той софтине как-то все иначе и очевиднее сделал (клавиши-акселераторы, переход в правую панель по Enter в дереве и.т.п.).
Но сам приём был именно такой.
Технические детали конечно могут различаться: это может быть не таймер, а фоновый спящий поток. Который собсна периодически будится по TVN_SELCHANGED. Ну да это всё нюансы.
Как-то так. Можно попробовать отложенную передачу фокуса, тогда кто-б там не забрал фокус раньше, он все равно должен будет вернуться в окно назначения, ибо по идее это произойдет позже.
M>Окна сделаны в одном потоке. Проверено в Spy++.
C>>2) Что возвращает SetFocus()? Что говорит ::IsWindow(Hwnd куда фокус)?
M>SetFocus возвращает не нулевое значения.
M>После вызова SetFocus() вставил следующую строку
M>
M> Check_Win(SetFocus(m_hwndImageTable));
M> assert(GetFocus() == m_hwndImageTable);
M>M>Исключения нет. Значит фокус получает окно, которое мне нужно.
C>>3) В оконной процедуре (HWND куда фокус) приходят всякие WM_ACTIVATE? WM_KILLFOCUS в оконную процедуру дерева приходит?
M>Поставил обработчик сообщения WM_KILLFOKUS окно, куда передаю фокус (Благо этот контроль я сам разрабатываю). Он вызывается. Значит окно получает фокус, и почему-то его тут же отдает. По кадру стека понял, что это происходит не в моем коде, а в системном.
M>Самое интересное в сообщении WM_LButtonDown окна, которому передается фокус, функция SetFocus() работает безупречно.
Ну вот и разобрались... Видимо фокус все-таки приходит, но его кто-то забирает.
Что видим в WPARAM в обработчике WM_KILLFOCUS? Там по идее может быть HWND окна, которое забирает фокус.
Хм... Вообще я такие вещи делал несколько иначе. А именно отложенная передача фокуса.
Если в 2-ух словах: то в обработчике TVN_SELCHANGED запоминался выделенный узел (HTREEITEM), и взводился таймер.
А по таймеру проверялось, если выделенный айтем (TVGN_CARET) совпадает с запомненным узлом, то фокус куда-то там в правую панель передавался. Если нет, то нет.
Это было нужно когда-то давно в одной софтине, чтобы переходить куда-то там в правую панель. Причем по выделению узла в дереве при выделении именно с клавы. А таймер был нужен, только для того, чтобы можно было спокойно "бегать" по дереву клавой и фокус и не уходил с дерева мгновенно.
Потом я в той софтине как-то все иначе и очевиднее сделал (клавиши-акселераторы, переход в правую панель по Enter в дереве и.т.п.).
Но сам приём был именно такой.
Технические детали конечно могут различаться: это может быть не таймер, а фоновый спящий поток. Который собсна периодически будится по TVN_SELCHANGED. Ну да это всё нюансы.
Как-то так. Можно попробовать отложенную передачу фокуса, тогда кто-б там не забрал фокус раньше, он все равно должен будет вернуться в окно назначения, ибо по идее это произойдет позже.