Здравствуйте
Хотелось бы при выборе определенного узла в TreeView фокус ввода автоматически передавался бы на в другой контроль в этом же главном окне. Для этого в новигационом сообщении TVN_SELCHANGED, полученном от моего TreeView Control вызываю API функцию SetFocus(). Но она почему то не работает.
Операционная система MS Windows 10.
Подскажите пожалуйста, в чем тут дело.
Заранее благодарен
Re: Сменна фокуса ввода в новигационном сообщении TVN_SELCHANGED
Здравствуйте, Melamed, Вы писали:
M>Здравствуйте M>Хотелось бы при выборе определенного узла в TreeView фокус ввода автоматически передавался бы на в другой контроль в этом же главном окне. Для этого в новигационом сообщении TVN_SELCHANGED, полученном от моего TreeView Control вызываю API функцию SetFocus(). Но она почему то не работает. M>Операционная система MS Windows 10. M>Подскажите пожалуйста, в чем тут дело. M>Заранее благодарен
Где фокус в момент получения TVN_SELCHANGED?
Где обрабатывается TVN_SELCHANGED?
И вообще код в студию!
Здравствуйте, Carc, Вы писали:
C>Здравствуйте, Melamed, Вы писали:
M>>Здравствуйте M>>Хотелось бы при выборе определенного узла в TreeView фокус ввода автоматически передавался бы на в другой контроль в этом же главном окне. Для этого в новигационом сообщении TVN_SELCHANGED, полученном от моего TreeView Control вызываю API функцию SetFocus(). Но она почему то не работает. M>>Операционная система MS Windows 10. M>>Подскажите пожалуйста, в чем тут дело. M>>Заранее благодарен C>Где фокус в момент получения TVN_SELCHANGED?
В Момент обработки сообщения фокус находился на TreeView, от которого пришло данное сообщения C>Где обрабатывается TVN_SELCHANGED?
В Родительском окне C>И вообще код в студию!
В TVN_SELCHANGED как получается? С клавиатуры или мышом? (NMTREEVIEW::action ?) Вообще говоря SetFocus должна работать, если m_hwndImageTable для SetFocus работает в том же потоке, что и TreeView.
Здравствуйте, Carc, Вы писали:
C>В TVN_SELCHANGED как получается? С клавиатуры или мышом? (NMTREEVIEW::action ?) Вообще говоря SetFocus должна работать, если m_hwndImageTable для SetFocus работает в том же потоке, что и TreeView.
Сooбщение TVN_SELCHANGED получается с клавиатуры или мышью без разницы. Есть подозрение, так часть сообщения ITM_FILLFILEBYMASK выполняется в фоновом потоке и во время ее выполнения выводится диалоговое окно, показывающее ход ее выполнения, то не исключено, что из-за этого.
Здравствуйте, Melamed, Вы писали:
M>Здравствуйте, Carc, Вы писали:
C>>В TVN_SELCHANGED как получается? С клавиатуры или мышом? (NMTREEVIEW::action ?) Вообще говоря SetFocus должна работать, если m_hwndImageTable для SetFocus работает в том же потоке, что и TreeView.
M>Сooбщение TVN_SELCHANGED получается с клавиатуры или мышью без разницы.
В общем случае должно быть без разницы...
M>Есть подозрение, так часть сообщения ITM_FILLFILEBYMASK выполняется в фоновом потоке и во время ее выполнения выводится диалоговое окно, показывающее ход ее выполнения, то не исключено, что из-за этого.
1) Ну а GetWindowThreadProcessId(HWND обработчика TVN_SELCHANGED) == GetWindowThreadProcessId(hwnd куда бросаем фокус)?
В одном потоке или нет?
2) Что возвращает SetFocus()? Что говорит ::IsWindow(Hwnd куда фокус)?
3) В оконной процедуре (HWND куда фокус) приходят всякие WM_ACTIVATE? WM_KILLFOCUS в оконную процедуру дерева приходит?
Проще говоря:
а) окна дерева и куда_фокус (прости меня за русский, хаспади ) в одном потоке или нет?
б) Фокус с дерева уходит ли? И если да, то доходит ли он до таргет-окна?
Я б «раскопки» начинал в таком направлении.
Можно, конечно, еще попробовать ReleaseCapture позвать перед SetFocus, но имхо это не решение. Надо в происходящем разбираться, ну и далее в причинах. Ибо какое-то странное поведение.
Не должно так быть. А то как-то получается, что "пищит-мигает, куда известно не попападает"... А должно
Здравствуйте, Carc, Вы писали:
C>Здравствуйте, Melamed, Вы писали:
C>1) Ну а GetWindowThreadProcessId(HWND обработчика TVN_SELCHANGED) == GetWindowThreadProcessId(hwnd куда бросаем фокус)? C>В одном потоке или нет?
Окна сделаны в одном потоке. Проверено в Spy++. C>2) Что возвращает SetFocus()? Что говорит ::IsWindow(Hwnd куда фокус)?
SetFocus возвращает не нулевое значения.
После вызова SetFocus() вставил следующую строку
Исключения нет. Значит фокус получает окно, которое мне нужно. C>3) В оконной процедуре (HWND куда фокус) приходят всякие WM_ACTIVATE? WM_KILLFOCUS в оконную процедуру дерева приходит?
Поставил обработчик сообщения WM_KILLFOKUS окно, куда передаю фокус (Благо этот контроль я сам разрабатываю). Он вызывается. Значит окно получает фокус, и почему-то его тут же отдает. По кадру стека понял, что это происходит не в моем коде, а в системном.
Самое интересное в сообщении WM_LButtonDown окна, которому передается фокус, функция SetFocus() работает безупречно. C>Проще говоря: C>а) окна дерева и куда_фокус (прости меня за русский, хаспади ) в одном потоке или нет? C>б) Фокус с дерева уходит ли? И если да, то доходит ли он до таргет-окна? C>Я б «раскопки» начинал в таком направлении.
C>Можно, конечно, еще попробовать ReleaseCapture позвать перед SetFocus, но имхо это не решение. Надо в происходящем разбираться, ну и далее в причинах. Ибо какое-то странное поведение. C>Не должно так быть. А то как-то получается, что "пищит-мигает, куда известно не попападает"... А должно
Здравствуйте, 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. Ну да это всё нюансы.
Как-то так. Можно попробовать отложенную передачу фокуса, тогда кто-б там не забрал фокус раньше, он все равно должен будет вернуться в окно назначения, ибо по идее это произойдет позже.
Здравствуйте, Carc, Вы писали: C>Хм... Вообще я такие вещи делал несколько иначе. А именно отложенная передача фокуса. C>Если в 2-ух словах: то в обработчике TVN_SELCHANGED запоминался выделенный узел (HTREEITEM), и взводился таймер. C>А по таймеру проверялось, если выделенный айтем (TVGN_CARET) совпадает с запомненным узлом, то фокус куда-то там в правую панель передавался. Если нет, то нет.
С таймером — это уже тяжелая артиллерия.
Иногда нужно чтобы текущий стек оконных процедур размотался до ближайшего цикла обработки сообщений.
Может SetFocus(куда-то там) вызывается в default обработке одного из текущих сообщений (WM_MOUSEACTIVATE и т.п.).
В таком случае помогает PostMessage(WM_APP + N, ...), а в его обработчике уже вызывать SetFocus куда хотим.
Re[9]: Сменна фокуса ввода в новигационном сообщении TVN_SEL
Здравствуйте, qaz77, Вы писали:
Q>Здравствуйте, Carc, Вы писали: C>>Хм... Вообще я такие вещи делал несколько иначе. А именно отложенная передача фокуса. C>>Если в 2-ух словах: то в обработчике TVN_SELCHANGED запоминался выделенный узел (HTREEITEM), и взводился таймер. C>>А по таймеру проверялось, если выделенный айтем (TVGN_CARET) совпадает с запомненным узлом, то фокус куда-то там в правую панель передавался. Если нет, то нет.
Q>С таймером — это уже тяжелая артиллерия.
Я же выше написал
Технические детали конечно могут различаться: это может быть не таймер, а фоновый спящий поток....
C>Технические детали конечно могут различаться: это может быть не таймер, а фоновый спящий поток....
Отдельный поток для такого — это еще более тяжелая артиллерия.
Да, у потока отдельный стек.
Но прием, о котором я написал с PostMessage, решает проблемы со стеком самым дешевым способом и по ресурсам, и по объему кодирования.
Re[11]: Сменна фокуса ввода в новигационном сообщении TVN_SEL
Здравствуйте, qaz77, Вы писали:
Q>Здравствуйте, Carc, Вы писали: C>>
C>>Технические детали конечно могут различаться: это может быть не таймер, а фоновый спящий поток....
Q>Отдельный поток для такого — это еще более тяжелая артиллерия. Q>Да, у потока отдельный стек.
Для тех кто в бронепоезде после выходных...
Еще раз. По слогам.
Технические детали конечно могут различаться
Я суть человеку рассказал, всего лишь иллюстрация «как примерно». А как именно сделать в отложенность там вариантов тьма. И выбор конкретного будет зависеть от задачи чуть более чем на 120 процентов. Ненамного, конечно. Чутка. Но всё ж более чем 120 процентов.
Q>Но прием, о котором я написал с PostMessage, решает проблемы со стеком самым дешевым способом и по ресурсам, и по объему кодирования.
Нет, не решает.
Оный прием решает проблемы разработчика. А нужно было решить проблему пользователя.