Странность Z-порядка окна MDI при активации - PullRequest
3 голосов
/ 17 октября 2011

У меня есть приложение со многими дочерними окнами MDI.Обычно пользователь может вывести одно дочернее окно MDI на передний план, щелкая области клиента как в клиентской, так и в не клиентской областях.Обычно это происходит, как только кнопка мыши нажата.

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

В результате, если у меня естьнесколько дочерних окон MDI частично перекрывают друг друга, я не могу вывести окно вперед, как обычно.Кажется, что это не зависит от фокуса - дочернее окно MDI может иметь фокус, но все еще находиться на позади другого дочернего окна MDI.

Более того - это происходит случайно, после использования приложениякакое-то время.Я могу воспроизвести ошибку, используя сериализованное состояние программы (файл 'save'), отправленный пользователем.

Мой вопрос состоит из 2 частей: любые идеи, почему это может произойти, и как я могу отладить мойпрограмма, чтобы узнать, почему это происходит?

Я подозреваю, что оконное сообщение WM_ACTIVATE (или что-то подобное) не обрабатывается должным образом, но это приложение C #, и я не делаю ничего необычного сочередь сообщений.

Редактировать: Вот дополнительная информация из spy ++.

Ниже приведен вывод из spy ++, когда все происходит нормально:

<00013> 00D209AA S WM_PARENTNOTIFY fwEvent:WM_LBUTTONDOWN xPos:146 yPos:147
<00014> 00D209AA R WM_PARENTNOTIFY
<00015> 00D209AA S WM_WINDOWPOSCHANGING lpwp:0012EE90
<00016> 00D209AA R WM_WINDOWPOSCHANGING
<00017> 00D209AA S WM_CHILDACTIVATE
<00018> 00D209AA S WM_NCPAINT hrgn:D3043A75
<00019> 00D209AA R WM_NCPAINT
<00020> 00D209AA S WM_ERASEBKGND hdc:C20124F7
<00021> 00D209AA S WM_GETTEXTLENGTH
<00022> 00D209AA R WM_GETTEXTLENGTH cch:1
<00023> 00D209AA S WM_GETTEXT cchTextMax:4 lpszText:0012DC48
<00024> 00D209AA R WM_GETTEXT cchCopied:1 lpszText:0012DC48 (" ")
<00025> 00D209AA R WM_ERASEBKGND fErased:True
<00026> 00D209AA S WM_WINDOWPOSCHANGING lpwp:0012EB80
<00027> 00D209AA R WM_WINDOWPOSCHANGING
<00028> 00D209AA S WM_MDIACTIVATE hwndDeactivate:014809AE hwndActivate:00D209AA (activating)
<00029> 00D209AA S WM_NCACTIVATE fActive:True
<00030> 00D209AA R WM_NCACTIVATE
<00031> 00D209AA S WM_IME_SETCONTEXT fSet:1 iShow:C000000F
<00032> 00D209AA R WM_IME_SETCONTEXT
<00033> 00D209AA S WM_SETFOCUS hwndLoseFocus:00B20A2A
<00034> 00D209AA R WM_SETFOCUS
<00035> 00D209AA R WM_MDIACTIVATE
<00036> 00D209AA R WM_CHILDACTIVATE
<00037> 00D209AA S WM_WINDOWPOSCHANGED lpwp:0012EE90
<00038> 00D209AA R WM_WINDOWPOSCHANGED
<00039> 00D209AA S WM_MOUSEACTIVATE hwndTopLevel:012C093A nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN
<00040> 00D209AA R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE

Когда я получаю выводпосле запуска приложения с воспроизводимой ошибкой щелчок по клиентской области приводит к следующему:

<01315> 023E0AA0 S WM_PARENTNOTIFY fwEvent:WM_LBUTTONDOWN xPos:139 yPos:142
<01316> 023E0AA0 R WM_PARENTNOTIFY
<01317> 023E0AA0 S WM_MOUSEACTIVATE hwndTopLevel:012C093A nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN
<01318> 023E0AA0 R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE

Глядя на номера сообщений, я сразу вижу, что существует куча сообщений, которые не появляются,в частности, WM_CHILDACTIVATE.

Решение

MdiParent одной из форм не было установлено до окнапоказывается.

Ответы [ 2 ]

3 голосов
/ 20 октября 2011

Вот несколько советов:

  • Добавьте событие клика в дочернюю форму и по клику позвоните Show(), чтобы вывести форму на передний план
  • Убедитесьчто свойство MdiParent установлено во всех дочерних формах
  • Убедитесь, что свойство IsMdiContainer установлено в родительской форме
  • Установите WindowState дочерних форм в Normal
  • Используйте Activate(), чтобы активировать форму и придать ей фокус

Вы также можете попробовать использовать z-порядок от родителя, чтобы сфокусировать внимание на ребенке:

this.ActiveMdiChild.SendToBack();
Control.ControlCollection ct = ((MdiClient)this.ActiveMdiChild.Parent).Controls;
((Form)ct[0]).Activate();

Надеемсяодно или несколько из этих предложений решат вашу проблему.

1 голос
/ 20 октября 2011

Ответ на этот вопрос может лежать глубже в реализации вашего приложения, чем вы поделились.

Используете ли вы сторонние библиотеки пользовательского интерфейса? (например: DevExpress или Telerik или ...) Эти библиотеки часто используют apvo win32 apis для достижения некоторых из своих красиво оформленных окон и / или аккуратной функциональности. Если вы используете старые добрые winforms, это было бы полезно знать.

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

Также, если вы можете собрать несколько сохраненных файлов состояния, которые воспроизводят проблему, вы сможете определить тенденцию. Возможно, это одно конкретное окно в вашем приложении, которое последовательно отображает вышеуказанное поведение?

Вопреки другому предложению, в настоящее время находящемуся в этой теме, вы НЕ должны использовать ShowDialog () для Mdi Children. (Я даже надеюсь, что Microsoft сгенерирует исключение, если вы попробуете ShowDialog с MdiParent, назначенным для формы). MdiChildren не могут быть модальными окнами, и это вполне может вызвать плохое поведение, которое вы видите. пример: одна форма хочет быть модальной / встроенной, в то время как нормальная дочерняя форма пытается сфокусироваться.

...