##### Далее - древний текст и древний аттач ###################################### Эта заметка - поначалу реакция на "КАК УБРАТЬ ОКНО ИЗ STATUS BAR" (http://www.wasm.ru/forum/viewtopic.php?id=15541), а отдельной веткой - потому как утянуло на более широкую тему... --- cresta: > интересно, как удалось вставить окно в статус-бар? > Если это всё-таки таск-бар, то удалить кнопку программы из него можно так: > 1.создать невидимое окно. 2.это окно сделать парентом видимому окну. 3.всё. Вы вот подшучиваете над путаницей, неизбежной у начинающих, а ведь и в Вашем ответе есть, к чему придраться 1) Вставить окно и в статус-бар, и куда угодно - просто, но об этом чуть позже. 2) СОЗДАВАТЬ невидимое окно - не обязательно, можно воспользоваться и уже существующим в системе. 3) Ну, а фраза "это окно сделать парентом видимому окну" - вполне способна запутать вконец... Поэтому проясним цель: видимое top-level окно с невидимым Owner-ом, именно Owner-ом, а не Parent-ом ! А установить отношения Owned/Owner можно лишь через СОЗДАНИЕ (CreateWindow*, CreateDialog*, DialogBox*) top-level окна с привязкой в поле hWndParent к существующему top-level окну. Кстати, в отличие от хрупких отношений Child/Parent - отношения Owned/Owner нерушимы. rmn : >> как изменить парента у окна > SetParent(hwndChild, hwndNewParent); Хотя окна с hwndChild и hwndNewParent могут быть top-level без WS_CHILD, - SetParent устанавливает отношения Child/Parent, а не Owned/Owner. Для отношения Child/Parent ключевое понятие - клиентская область Parent-а: Child (у него может и не быть WS_CHILD) отображается только в пределах этой области. И если Parent не имеет WS_VISIBLE, то и Child невидим, даже если имеет WS_VISIBLE. Что для нашего случая категорически не подходит. А подойти может другое: через SetParent установить нашему окну Parent-ом - окно Progman ("Program Manager"). --- Итак, SetParent очень умеет творить чудеса с иерархией окон. Но с SetParent надо быть очень аккуратным, и прежде всего - обязательно изучить описание SetParent в MSDN. Там серьезные ограничения. Которые небесполезно проверить, хотя бы в учебных целях Посему прикладываю набросок учебной утилитки с примером: [Вставить окно в статус-бар] - запускаем ParentOwner.exe (исходник приложен), - запускаем блокнот со строкой состояния, - наводим курсор на часики (TrayClockWClass) и шлепаем F8, - наводим курсор на статусбар (msctls_statusbar32) блокнота и шлепаем F9, - убеждаемся, что в строках "Window..." и "Parent..." - то, что надо, - нажимаем кнопку "WS_CLIPCHILDREN...", чтобы статусбар получил (+) этот стиль, - нажимаем кнопку "SetParent..." - и видим живые часики на новом месте. Вообще-то утилитка может кое-что еще и расчитана на большее Вернуть назад - кнопка "Undo", глубина Undo/Redo - 64, при закрытии окна утилитки все проводившиеся SetParent автоматом отыгрываются назад (если не надо другого). Короткий хелп - в системном меню, а вообще - все в исходнике (masm32). Проверено только на XP pro SP2. --- 18.08.06 - поправки в утилитке (заменен .rar)
А вот и практический пример модификации чужой программы. В очень симпатичном Spy by Kobi (v.2.70) одно неудобно: Finder Tool лежит на закладке. Но это легко поправить, вставив SetParent в предварительный loader (см. исходник spy_loader). Возможно, это оценит автор Sign-0f-Misery
Более продуманная версия учебной утилитки ParentOwner. 1) Добавлен комбобокс, в который загружается дерево окон через один из следующих фильтров (нажатием одной из кнопок): - все окна (включая все message-only окна), - все окна процесса выбранного парента/оунера, - все окна потока выбранного парента/оунера, - все top-level окна (включая все верхние message-only окна). Выбор окна - правым, а выбор парента/оунера - левым кликом по строке листа комбобокса. Или же наведением курсора + F8 (окно) или F9 (парент). Причем при F9 - координаты курсора относительно парента задают будущую позицию (дочернего) окна. (О message-only окнах - http://www.wasm.ru/forum/viewtopic.php?id=14302&p=1 , пост #24). 2) Добавлена кнопка "sWaP" для перестановки строк Window и Parent|Owner (при отмеченном чекбоксе "lock"). 3) Теперь при нажатии кнопки "SetParent" сохраняются не только хендл окна и хендл его прежнего парента, но и style, exstyle и клиентские координаты окна относительно прежнего парента (не более 64 таких структур). 4) Добавлена кнопка "CreateWindowEx", с помощью которой легко построить цепочки окон с любыми комбинациями отношений парент/оунер (старые кнопки "CreateDialog" и "DialogBox" для этого не годятся). 5) Добавлено раздвоение/объединение интерфейса по двойному клику, просто как пример применения SetParent. ------ Ну, и несколько экспериментов. 1) Жмем кнопку "All", где-то внизу открывшегося листа комбобокса находим строчку с "#32774", угощаем ее левым кликом, после чего жмем кнопку "min/". А теперь наведите курсор на любую из стандартных кнопок заголовка любого окна... Ничего-ничего, кнопка "min/" все поправит 2) Попробуйте назначить этому же message-only #32774 парентом десктоп (т.е. HWND_DESKTOP или #32769 из комбобокса)... 3) Spy++ сообщает, что у окна "О программе "Калькулятор"" и парент, и оунер - это "главное" окно "Калькулятор". Но это враки. Парент - это десктоп (#32769), гляньте-ка в ParentOwner Чтобы построить окно, у которого на самом деле парент = оунеру, - запускаем ParentOwner, жмем кнопку "CreateWindowEx", жмем кнопку "sWaP", жмем кнопку "CreateWindowEx", жмем кнопку "SetParent". Искомое окно - "Window 2". 4) А теперь самое занятное. В только что построенном окне "Window 2" жмем кнопку "WS_POPUP", после чего текст кнопки меняется на "not WS_POPUP", а окно "Window 2" лишается стиля WS_POPUP. Нажатие на кнопку "not WS_POPUP" все восстановит. Так вот: понажимайте эту кнопку и одновременно понаблюдайте за строкой "GetParent" в окне ParentOwner... Вам не кажется, что с функцией GetParent не все в порядке ? -------- 2011-12-08 хехе, вот и R.Chen, наконец, высказался по этому вопросу: GetParent, just as confusing as EnumClaw, but it's an actual function!
Updated: v.2009-06-04 1) Устранен баг с текст.буффером и 2) добавлен чекбокс для настройки внутреннего оконного искателя: использовать в нем RealChildWindowFromPoint или же ChildWindowFromPointEx (т.е. теперь учтен случай предка с чудовищным WS_EX_LAYOUTRTL).