WS_CHILD и активность окна
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 10.12.22 15:56
Оценка:
MS в своей документации пишет: "Only a top-level window can be an active window. When the user is working with a child window, the system activates the top-level parent window associated with the child window".

И в той же документации:

WM_CHILDACTIVATE message: "Sent to a child window when the user clicks the window's title bar or when the window is activated, moved, or sized".

WM_MOUSEACTIVATE message: "The parent window determines whether to activate the child window. If it activates the child window, the parent window should return..."

Что здесь понимается под "активацией" дочернего окна?
Re: WS_CHILD и активность окна
От: Pavel Dvorkin Россия  
Дата: 12.12.22 04:54
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Что здесь понимается под "активацией" дочернего окна?


Эти 2 сообщения относятся к MDI. MDI child могут иметь активность.
With best regards
Pavel Dvorkin
Re[2]: WS_CHILD и активность окна
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 12.12.22 09:03
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Эти 2 сообщения относятся к MDI.


Из чего это следует?

PD>MDI child могут иметь активность.


Если они могут иметь активность в том смысле, как она определена в описании оконных стилей, то возникает противоречие. Или они могут имитировать активность своими силами — так, что окно формально считается неактивным, но фактически отображается с подсвеченным заголовком и фокусом?
Re[3]: WS_CHILD и активность окна
От: Pavel Dvorkin Россия  
Дата: 12.12.22 10:10
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Эти 2 сообщения относятся к MDI.


ЕМ>Из чего это следует?


https://learn.microsoft.com/en-us/dotnet/desktop/winforms/advanced/how-to-determine-the-active-mdi-child?view=netframeworkdesktop-4.8
https://learn.microsoft.com/en-us/dotnet/desktop/winforms/advanced/how-to-send-data-to-the-active-mdi-child?view=netframeworkdesktop-4.8
https://learn.microsoft.com/ru-ru/dotnet/desktop/winforms/advanced/how-to-determine-the-active-mdi-child?view=netframeworkdesktop-4.8

https://stackoverflow.com/questions/46768865/how-to-change-the-active-mdi-child

http://win-api.narod.ru/a6594.htm

WM_CHILDACTIVATE Performs activation processing when MDI child windows are sized, moved, or displayed. This message must be passed.

PD>>MDI child могут иметь активность.


ЕМ>Если они могут иметь активность в том смысле, как она определена в описании оконных стилей, то возникает противоречие. Или они могут имитировать активность своими силами — так, что окно формально считается неактивным, но фактически отображается с подсвеченным заголовком и фокусом?


Это особый стиль для MDI child. Нет тут противоречия. В MDI приложении одно из child окон имеет синий заголовок и является активным в смысле MDI.

Женя, не надо спорить и искать ошибки и противоречия. Я это помню еще о времен Windows 3.0.

https://www.frolov-lib.ru/books/bsp/v17/ch1_4.htm

Функция окна Document Window очень похожа на функцию обычного дочернего окна, но все необработанные ей сообщения должны передаваться функции DefMDIChildProc (а не функции DefWindowProc). Функция DefMDIChildProc обрабатывает сообщения WM_CHILDACTIVATE, WM_GETMINMAXINFO, WM_MENUCHAR, WM_MOVE, WM_NEXTMENU, WM_SETFOCUS, WM_SIZE, WM_SYSCOMMAND. Перечисленные сообщения должны в обязательном порядке передаваться функции DefMDIChildProc, даже если функция окна Document Window обрабатывает их самостоятельно.
With best regards
Pavel Dvorkin
Отредактировано 12.12.2022 10:14 Pavel Dvorkin . Предыдущая версия .
Re[4]: WS_CHILD и активность окна
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 12.12.22 10:58
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>https://learn.microsoft.com/en-us/dotnet/desktop/winforms/advanced/how-to-determine-the-active-mdi-child?view=netframeworkdesktop-4.8

PD>https://learn.microsoft.com/en-us/dotnet/desktop/winforms/advanced/how-to-send-data-to-the-active-mdi-child?view=netframeworkdesktop-4.8
PD>https://learn.microsoft.com/ru-ru/dotnet/desktop/winforms/advanced/how-to-determine-the-active-mdi-child?view=netframeworkdesktop-4.8

Ни в одной из этих статей не упоминается ни WM_MOUSEACTIVATE, ни WM_CHILDACTIVATE. К чему они здесь?

PD>https://stackoverflow.com/questions/46768865/how-to-change-the-active-mdi-child


Здесь, кстати, тоже.

PD>http://win-api.narod.ru/a6594.htm


А более официальные источники есть? Я не нашел.

PD>Это особый стиль для MDI child. Нет тут противоречия. В MDI приложении одно из child окон имеет синий заголовок и является активным в смысле MDI.


Именно поэтому я и уточнил, в каком смысле оно "является активным". Есть понятие активного окна в отношении "окон вообще" — оно используется везде, где встречаются понятие "активность", "активация", "деактивация" и т.п. Я правильно понимаю, что дочерние окна MDI все равно не являются "активными" в этом общем смысле, и для них лишь имитируется поведение, похожее на поведение "истинно активных" окон?
Re[5]: WS_CHILD и активность окна
От: Pavel Dvorkin Россия  
Дата: 13.12.22 01:35
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Ни в одной из этих статей не упоминается ни WM_MOUSEACTIVATE, ни WM_CHILDACTIVATE. К чему они здесь?


В них упоминается Active MDI Child. Обычный child active быть не может.

PD>>https://stackoverflow.com/questions/46768865/how-to-change-the-active-mdi-child


ЕМ>Здесь, кстати, тоже.


PD>>http://win-api.narod.ru/a6594.htm


ЕМ>А более официальные источники есть? Я не нашел.


Я тоже. MDI мертв с прошлого века.

PD>>Это особый стиль для MDI child. Нет тут противоречия. В MDI приложении одно из child окон имеет синий заголовок и является активным в смысле MDI.


ЕМ>Именно поэтому я и уточнил, в каком смысле оно "является активным". Есть понятие активного окна в отношении "окон вообще" — оно используется везде, где встречаются понятие "активность", "активация", "деактивация" и т.п. Я правильно понимаю, что дочерние окна MDI все равно не являются "активными" в этом общем смысле, и для них лишь имитируется поведение, похожее на поведение "истинно активных" окон?


Видимо, да, правильно, но не все ли тебе равно ? Ты же не собираешься делать, надеюсь, MDI-приложение , а для обычных окон эти сообщения неприменимы.
With best regards
Pavel Dvorkin
Re[6]: WS_CHILD и активность окна
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.12.22 11:26
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

ЕМ>>Я правильно понимаю, что дочерние окна MDI все равно не являются "активными" в этом общем смысле, и для них лишь имитируется поведение, похожее на поведение "истинно активных" окон?


PD>не все ли тебе равно ?


Конечно, нет. Если в MDI реализована "честная" активизация, которой почему-то нет в реализации по умолчанию, то я бы использовал MDI, а не самодельный костыль.

PD>Ты же не собираешься делать, надеюсь, MDI-приложение


Я его сделал в тестовых целях, но фокус в поля редактирования
Автор: Евгений Музыченко
Дата: 21.11.22
без костылей все равно не ставится.

PD>для обычных окон эти сообщения неприменимы.


Значит, у меня галлюцинации, когда я вижу их оба в простейших примерах с обычными окнами.
Re[7]: WS_CHILD и активность окна
От: Pavel Dvorkin Россия  
Дата: 13.12.22 11:39
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Конечно, нет. Если в MDI реализована "честная" активизация, которой почему-то нет в реализации по умолчанию, то я бы использовал MDI, а не самодельный костыль.


Никто сейчас MDI приложения не пишет. Их в Windows 95 уже мало было. Если ты хочешь, чтобы твое приложение выглядело как приложение для Windows 3.11 — тогда делай.


ЕМ>Я его сделал в тестовых целях, но фокус в поля редактирования
Автор: Евгений Музыченко
Дата: 21.11.22
без костылей все равно не ставится.


PD>>для обычных окон эти сообщения неприменимы.


ЕМ>Значит, у меня галлюцинации, когда я вижу их оба в простейших примерах с обычными окнами.


Ну не знаю. Проверять не буду.
With best regards
Pavel Dvorkin
Re[8]: WS_CHILD и активность окна
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.12.22 11:56
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Никто сейчас MDI приложения не пишет.


"MDI приложения" — это приложения, использующие DefMDIFrameProc, DefMDIChildProc и прочее, или таки приложения, группирующие несколько однотипных документов в одном окне?

PD>Если ты хочешь, чтобы твое приложение выглядело как приложение для Windows 3.11 — тогда делай.


Ну вот, например, VS 2008 использует MDI API, но почему-то не выглядит, как в 3.11.

А мне, честно говоря, по барабану, как будет выглядеть приложение, поскольку оно предназначено сугубо для демонстрационно-тестовых целей. Лишь бы функции работали.

PD>Ну не знаю. Проверять не буду.


Так я уже проверил — WM_CHILDACTIVATE идет безо всякого MDI, а WM_MOUSEACTIVATE и вовсе ни малейшего отношения к MDI не имеет.
Re[9]: WS_CHILD и активность окна
От: Pavel Dvorkin Россия  
Дата: 13.12.22 12:16
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>"MDI приложения" — это приложения, использующие DefMDIFrameProc, DefMDIChildProc и прочее, или таки приложения, группирующие несколько однотипных документов в одном окне?


Первое. По определению.

https://www.frolov-lib.ru/books/bsp.old/v17/ch1.htm

ЕМ>Ну вот, например, VS 2008 использует MDI API, но почему-то не выглядит, как в 3.11.


Не знаю, что именно он использует, но едва ли классический MDI

ЕМ>А мне, честно говоря, по барабану, как будет выглядеть приложение, поскольку оно предназначено сугубо для демонстрационно-тестовых целей. Лишь бы функции работали.


Хозяин — барин.

ЕМ>Так я уже проверил — WM_CHILDACTIVATE идет безо всякого MDI, а WM_MOUSEACTIVATE и вовсе ни малейшего отношения к MDI не имеет.


Spy ++ ?

Может, ты и прав.
With best regards
Pavel Dvorkin
Re: WS_CHILD и активность окна
От: qaz77  
Дата: 13.12.22 14:34
Оценка: 5 (1)
Здравствуйте, Евгений Музыченко, Вы писали:

WM_CHILDACTIVATE — это про стандартный MDI, забудьте.

В вот WM_MOUSEACTIVATE сообщение общего назначения.
Его посылает система окну (в т.ч. дочернему), над которым нажали кнопку мыши.
"Над которым" в смысле hit test — иерархии parent-child и z-order среди сиблингов.
Речь тут идет об активизации popup окна, а вовсе не child.
Но child может кастомизировать поведение, нужно ли активизировать его top level хозяина.

Если WM_MOUSEACTIVATE разрешает активизацию top level (MA_ACTIVATE или MA_ACTIVATEANDEAT), то top level получает сообщение WM_ACTIVATE, а DefWindowProc для этого сообщения устанавливает фокус ввода.

Для всяких вспомогательных popup окон нежелателен эффект их активизации, когда какое-то "основное" окно будет терять активность с визуальным эффектом в заголовке, потерей фокуса ввода и т.д.
Например, выпадающие списки комбобокс. Это listbox со стилем popup, при его показе и нажатиях мыши над ним не происходит отбор активности у top level окна.
Такая же история с tooltips.
Чтобы достичь указанного эффекта такие окна обрабатывают WM_MOUSEACTIVATE и возвращают MA_NOACTIVATE.

При посылке WM_MOUSEACTIVATE отдельному child контролу можно реализовать логику, которая будет только для этого контрола подавлять активизацию top level.
Например, floating toolbars и различные палитры (немодальные диалоги). Куда-то в них тыкнули, команда сгенерировалась.
А зачем их активизировать? Не надо активизировать.
Но если, например, в немодальном диалоге есть что-то более сложное, чем кнопки, то может потребоваться активизация и установка фокуса ввода (например, edit имеется). Т.е. при нажатии на кнопки такой диалог не забирает активность, а при клике в edit — забирает.
Для такого избирательного поведения кнопки должны обрабатывать WM_MOUSEACTIVATE и возвращать MA_NOACTIVATE.
Re[10]: WS_CHILD и активность окна
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.12.22 16:03
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Первое. По определению.

PD>https://www.frolov-lib.ru/books/bsp.old/v17/ch1.htm

С каких пор такая литература стала источником определений?

PD>Не знаю, что именно он использует, но едва ли классический MDI


Использует CreateMDIWindow, DefMDIChildProc, DefFrameProc. А уж какую пред- и постобработку при этом делает — неважно.

PD>Spy ++ ?


Мои собственные логи, они удобнее.
Re[2]: WS_CHILD и активность окна
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.12.22 21:24
Оценка:
Здравствуйте, qaz77, Вы писали:

Q>WM_CHILDACTIVATE — это про стандартный MDI, забудьте.


Еще один. Вы б, народ, хоть в SDK заглянули, что ли. И WM_MOUSEACTIVATE, и WM_CHILDACTIVATE определяются еще в 2.0, в то время как MDI начинается только с 3.0, хотя некие его признаки появляются и в 2.11.

И еще раз, если это "про стандартный MDI", то почему его получают дочерние окна в моем простейшем примере без MDI?

Q>В вот WM_MOUSEACTIVATE сообщение общего назначения.

Q>Его посылает система окну (в т.ч. дочернему), над которым нажали кнопку мыши.

Угу, я уже сляпал на нем костыль. Но таки теплилась надежда, что в дефолтном поведении окон логики чуть больше.

Q>Речь тут идет об активизации popup окна, а вовсе не child.


А какая разница-то? Какие силы зла мешают child-окну быть активным, кроме соответствующего постулата?

Q>Для всяких вспомогательных popup окон нежелателен эффект их активизации, когда какое-то "основное" окно будет терять активность с визуальным эффектом в заголовке, потерей фокуса ввода и т.д.


Если это изначально прибили гвоздями, то для чего потом добавили стиль WS_EX_NOACTIVATE?

Q>Но если, например, в немодальном диалоге есть что-то более сложное, чем кнопки, то может потребоваться активизация и установка фокуса ввода (например, edit имеется). Т.е. при нажатии на кнопки такой диалог не забирает активность, а при клике в edit — забирает.


Так все началось как раз с того, что он <i>не</i> забирает без дополнительных приседаний. А почему — хз. Вот есть окно с WS_CHILD, в нем есть Edit. Первый постулат: "окна с WS_CHILD не могут быть активными". Второй постулат: при клике мышью в Edit неактивного окна фокус не ставится". Какие есть типовые (чтобы оправдать такое поведение) ситуации, в которых установка фокуса в Edit при клике в него была бы интуитивно нежелательной?
Re[11]: WS_CHILD и активность окна
От: Pavel Dvorkin Россия  
Дата: 14.12.22 13:06
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Первое. По определению.

PD>>https://www.frolov-lib.ru/books/bsp.old/v17/ch1.htm

ЕМ>С каких пор такая литература стала источником определений?


На тебе другую

https://learn.microsoft.com/en-us/windows/win32/winmsg/multiple-document-interface
https://learn.microsoft.com/en-us/windows/win32/winmsg/using-the-multiple-document-interface
With best regards
Pavel Dvorkin
Re[3]: WS_CHILD и активность окна
От: qaz77  
Дата: 14.12.22 14:54
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Еще один. Вы б, народ, хоть в SDK заглянули, что ли. И WM_MOUSEACTIVATE, и WM_CHILDACTIVATE определяются еще в 2.0, в то время как MDI начинается только с 3.0, хотя некие его признаки появляются и в 2.11.


ЕМ>И еще раз, если это "про стандартный MDI", то почему его получают дочерние окна в моем простейшем примере без MDI?


Ну, ок. Может и не только для mdi child приходят. Но это всего лишь уведомление, что top level хозяин стал активным.
Скорее всего, для MDI это надо было, чтобы перерисовывалась рамка текущего (не хочу тут использовать слово "активного") mdi child при смене активности mdi frame.

Если для контрола как-то важна активность окна-хозяина, то имеет смысл обрабатывать.
На память приходят только тултипы со стилем TTS_ALWAYSTIP.

ЕМ>А какая разница-то? Какие силы зла мешают child-окну быть активным, кроме соответствующего постулата?

А что мешает EnumWindows перебирать child окна.
Так сделали...

ЕМ>Если это изначально прибили гвоздями, то для чего потом добавили стиль WS_EX_NOACTIVATE?

Фактически этот стиль определяет, что возвращает DefWindowProc для WM_MOUSEACTIVATE — когда "user clicks it".

ЕМ>Вот есть окно с WS_CHILD, в нем есть Edit. Первый постулат: "окна с WS_CHILD не могут быть активными". Второй постулат: при клике мышью в Edit неактивного окна фокус не ставится". Какие есть типовые (чтобы оправдать такое поведение) ситуации, в которых установка фокуса в Edit при клике в него была бы интуитивно нежелательной?


Я приводил пример с edit, где как раз надо забирать фокус и активность.
Собственно, WM_MOUSEACTIVATE приходит, когда кликают над неактивным top level окном или его детками, внуками и т.д.

Кстати, MS использует термин "активность" не только для top level окон.
Есть еще активность для страниц в property sheet: PSN_SETACTIVE, PSN_KILLACTIVE.

Но та самая активность, которая GetActiveWindow/SetActiveWindow, привязана к GUI потоку с очередью сообщений (cм. структуру GUITHREADINFO).
Отредактировано 14.12.2022 15:04 qaz77 . Предыдущая версия . Еще …
Отредактировано 14.12.2022 15:01 qaz77 . Предыдущая версия .
Re[4]: WS_CHILD и активность окна
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 16.12.22 09:37
Оценка:
Здравствуйте, qaz77, Вы писали:

Q>Может и не только для mdi child приходят.


Почему "может"-то? WM_CHILDACTIVATE, вместе с WM_MOUSEACTIVATE, введено задолго до MDI, и в описании, ссылку на которое я давал, о нем нет ни слова.

Q>это всего лишь уведомление, что top level хозяин стал активным.


Не логичнее ли было бы, чтобы хозяин сам уведомлял об этом нужные ему окна?

Q>Скорее всего, для MDI это надо было, чтобы перерисовывалась рамка текущего (не хочу тут использовать слово "активного") mdi child при смене активности mdi frame.


Вот и непонятно, почему сюда не подходит "активный". Было бы вполне логично: среди top-level окон активно одно, среди его потомков — тоже одно, и так далее. Тот же элемент управления, имеющий фокус — чем он не "активный"?

Q>что мешает EnumWindows перебирать child окна.


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

Q>Я приводил пример с edit, где как раз надо забирать фокус и активность.


Понятно, что надо. Но откуда могут расти ноги у имеющейся реализации, которая отказывается это делать для "inactive child window"? Какую практическую пользу может принести Edit, в который по умолчанию не ставится фокус при клике мышкой именно потому, что так было задумано? Вам приходилось видеть такую конфигурацию за все время существования винды? Мне — нет.

Q>MS использует термин "активность" не только для top level окон.


Чем сам себе противоречит. И ничуть при этом не смущается.

Q>Есть еще активность для страниц в property sheet: PSN_SETACTIVE, PSN_KILLACTIVE.


Это как раз их собственная, самодельная активность, тут нет противоречия.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.