Как я могу обойти асимметрию GetParent / EnumChildWindows? - PullRequest
4 голосов
/ 12 февраля 2010

Я недавно проверил графический интерфейс с Microsoft Spy ++ и заметил странную структуру; это выглядело так (предупреждение, искусство ASCII впереди):

 |
 + 002004D6 "MyRootWindow1" FooClassName
 |   |
 |   + 001F052C "MyChildWindow" ClassOfChildWindow
 |
 \ 001D0A8C "MyRootWindow2" SomeOtherClassName

Существует два корневых окна, 002004D6 и 001D0A8c, первое из которых имеет одно дочернее окно, 001F052C.

Теперь, это было бы хорошо, если бы не одна вещь: вызов GetParent (или просмотр полей «Родительское окно» или «Окно владельца» в Spy ++) в дочернем окне. (001F052C) дает 001D0A8C.

Чтение: «MyChildWindow» является дочерним по отношению к «MyRootWindow1», но «MyRootWindow1» не является родительским по отношению к «MyChildWindow». Вместо этого родителем «MyChildWindow» является «MyRootWindow2», но для завершения перечисления дочерних элементов «MyRootWindow2» не выдается «MyChildWindow».

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

Кто-нибудь знает, как это может произойти? Кто-нибудь знает, как я могу обойти это? До тех пор теперь я использовал GetParent и EnumChildWindows , чтобы получить родителя (или потомков) для данного HWND, и я предположил, что это отношение симметрично. Может быть, я должен использовать что-то еще?

РЕДАКТИРОВАТЬ: Вот код для небольшой программы C ++, которая демонстрирует проблему:

const HINSTANCE thisModule = ::GetModuleHandle( NULL );
HWND oldParent = ::CreateWindow( TEXT("STATIC"),
                                 TEXT("Old parent"),
                                 WS_VISIBLE | WS_BORDER,
                                 0, 0, 850, 500,
                                 NULL,
                                 NULL,
                                 thisModule,
                                 NULL );
HWND child = ::CreateWindow( TEXT("STATIC"),
                             TEXT("This is a sample dialog"),
                             WS_OVERLAPPED | WS_POPUP | WS_VISIBLE | WS_BORDER,
                             100, 100, 300, 300,
                             oldParent,
                             NULL,
                             thisModule,
                             NULL );
HWND newParent = ::CreateWindow( TEXT("STATIC"),
                                 TEXT("Fake main window"),
                                 WS_VISIBLE | WS_BORDER,
                                 0, 0, 850, 500,
                                 NULL,
                                 NULL,
                                 thisModule,
                                 NULL );
::SetParent( child, newParent );

Обратите внимание, как для дочернего объекта установлены WS_POPUP и WS_OVERLAPPED, но не WS_CHILD.

Ответы [ 2 ]

3 голосов
/ 18 февраля 2010

Документация для GetParent объясняет: «Обратите внимание, что, несмотря на свое имя, эта функция может возвращать окно владельца вместо родительского окна.»

Поскольку вы не создаете дочернее окно, я предполагаю, что вы попали в это дело.

Вы должны иметь возможность вызывать GetAncestor, передавая GA_PARENT, как сказано в документации: «Извлекает родительское окно. Это не включает владельца, как это происходит с функцией GetParent.»

См. Владелец окна Win32 против окна Родитель?

3 голосов
/ 12 февраля 2010

Ну, это не имеет большого смысла, конечно. Пахнет, как будто дочернее окно переопределяет себя. Это обычная техника в .NET Windows Forms, у нее есть «окно парковки», где дочерние элементы управления могут найти временный дом, когда их окно контейнера необходимо воссоздать, потому что стиль окна изменился. Это не очень заметный эффект, он также временный.

Другая, удаленная возможность - SetParent (). Он имеет поведение appcompat для поддержки старых программ Windows 3.x. Это довольно хорошо объяснено в документации по SDK, в двух словах, окно можно родить, но не устанавливать флаг стиля WS_CHILD. Adobe Acrobat Reader является классическим примером программы, которая делает это. Какое влияние это окажет на EnumChildWindows, мне неясно.

Последнее, но не менее важное: не забывайте, что Spy ++ дает статический вид окон. Нажатие клавиши F5 для обновления списка окон может быть важно для отслеживания изменений.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...