Вчера (04.08.07 17:02) была внезапно перенесена модератором из 'MFC' в 'WIN API'
ветка 4-х летней давностиАвтор: Carc
Дата: 01.10.03
,
с одновременным включением ее (вместе с
еще более древней на ту же темуАвтор: Долгов Сергей Сергеевич
Дата: 14.01.02
) в 'WIN API — Q&A'.
Это событие заставляет меня прервать бесконечное вынашивание одной идейки и разродиться ею незамедлительно.
Дело в том, что наряду с часто повторяющимися вопросами и ответами —
есть еще и часто повторяющиеся ошибки и неточности в этих вопросах и ответах.
И эту словесную муть следовало бы прикончить "весомо, грубо, зримо": специальными наглядными тулзами.
Т.е. вот оно, мое предложение: пристроить к 'WIN API — Q&A' тулзопарк.
И вот первый туда кандидат:
ParentOwner, на тему перманентной путаницы с Parent и Owner окнами.
В известном смысле в этой путанице повинны GetParent и GetWindowLong/GWL_HWNDPARENT API:
MSDN> The GetParent function retrieves a handle to the specified window's parent or owner.
MSDN> GWL_HWNDPARENT Retrieves a handle to the parent window, if any. // но и здесь надо читать "parent or owner" !
По "противоположным" API (SetParent и SetWindowLong/GWL_HWNDPARENT) MSDN как будто имеет целью запутать окончательно:
справка противоречива и опровергается практикой самой MS, причем SetWindowLong/GWL_HWNDPARENT по сути рекомендовано не пользоваться...
Еще один момент, вносящий свой вклад в общую картину: в справке по Get* API "owner" фигурирует, а в справке по Set* API — о нем ни-гу-гу...
Зато сильно поотдаль объявляется, что Owner-а окно получает раз и навсегда: при своем зачатии.
Короче, однажды решил во всем этом разобраться, и пришел к следующим выводам:
1) Для точного разделения получаемых Parent и Owner надо пользоваться другими API: GetWindow/GW_OWNER и GetAncestor/GA_PARENT.
2) SetParent устанавливает именно отношения
Parent/Child, причем речь не о WS_CHILD у Child-а, а о привязанности Child-а к
клиентской области Parent-а.
3) GetWindowLong/GWL_HWNDPARENT, оказывается, на самом деле устанавливает отношения
Owner/Owned, и ясен пень — как только, так сразу.
Так что согласен с VladD2 2002 года:
>Для SetWindowLong флаг GWL_HWNDPARENT вообще не документирован.
>Однако во всех версиях виндовс это работает (видимо MS сами пользуются этой фичей, ну а другим рекамендуют как безопаснее).
Все это (и кое-что еще, о чем скажу позже) и сконцентрировано в утилитке ParentOwner.
(Естественно, к exe прилагаются хелп и исходник, иначе это не было бы тулзой для WIN API — Q&A).
---
Касаемо вышеупомянутых веток — там указанная путаница налицо:
1)
Gurza>>Или просто указать окну отца, тогда кнопка пропадёт
Gurza>>::SetWindowLong(m_hWnd, GWL_HWNDPARENT, (LONG)::GetDesktopWindow());
Carc>Угу, но а обратно включить? Я вин98 пробовал обратно отца выключить (SetParent(NULL) или же просче ::SetParent((HWND)NULL)),
Carc>кнопичка не проявлялсь снова, может тескбар как-то перерисовать надо?
2)
VladD2>>>>
Приведенный ниже код скрывает/показывает первый попавшийся Notepad (т.е. можно скрывать любое окно... даже не свое).
HWND hWnd = ::FindWindow(_T("Notepad"), NULL);
if(!hWnd)
return;
// Если окно уже имеет парента...
if(::GetWindowLong(hWnd, GWL_HWNDPARENT))
// урать его, тем самым показав в таскбаре...
::SetWindowLong(hWnd, GWL_HWNDPARENT, NULL);
else
// иначе ставим его парантом к DesktopWindow, тем самым убирая из таскбара.
::SetWindowLong(hWnd, GWL_HWNDPARENT, (LONG)::GetDesktopWindow());
Alexander>>>В МСДН написано, что вместо данной функции с параметром GWL_HWNDPARENT лучше (и желательно) использовать SetWindowParent (),
Alexander>>>но желаемый эффект от вызова последней почему-то не наблюдается, а с SetWindowLong () всё нормально... плз, объясните почему, если можно?
VladD2>>Вроде как SetParent работает только с чильд-окнами...
VladD2>[...] нам пнишлось повозиться с SetWindowLong. В том числе с динамической заменой парента у поуп-ап окон.
---
Между прочим, в коде VladD2 есть неточность.
Да, код будет работать с Notepad.exe, но, например, с Calc.exe — не будет.
Потому как Calc.exe имеет WS_EX_APPWINDOW, который надо предварительно удалить.
Кстати, на скриншоте запечатлен момент назначения легендарному подопытному кролику Owner-ом полу-message-only окна #32774, в результате чего Calc покидает таскбар.
[Продолжение следует...]