DeferWindowPos странное поведение - PullRequest
5 голосов
/ 11 апреля 2011

Это происходит со всеми элементами управления ActiveX.Если я переставлю элемент управления ActiveX с DeferWindowPos

HDWP hdwp = BeginDeferWindowPos(1);
DeferWindowPos(hdwp, m_pActiveX->GetSafeHwnd(), NULL, left, top, width, height, SWP_NOZORDER);
EndDeferWindowPos(hdwp);

, он перейдет туда , но затем переместится / изменит свой размер на старый прямоугольник, как только вы щелкнете где-нибудь внутри элемента управления .Если я вместо этого использую MoveWindow

m_pActiveX->MoveWindow(left, top, width, height);

, этого не произойдет.

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

Ответы [ 2 ]

6 голосов
/ 08 ноября 2011

Вы никогда не получили подходящий ответ.Я постараюсь немного помочь здесь.

Проблема в том, что MFC скрывает много хитрости с размещением элемента управления ActiveX в своей структуре.В частности, если вы вступаете в вызов MoveWindow, это не просто оболочка для Win32-функции MoveWindow.Он вызывает классы поддержки OLE Control Container.По сути, это говорит о том, что если у нас есть интерфейс контрольного сайта, тогда вызовите COleControlSite :: MoveWindow, в противном случае вызовите стандартный Win32 MoveWindow.То же самое происходит с несколькими другими оконными функциями, обрабатываемыми CWnd и т. Д. Например, COleControlSite :: SetWindowPos обрабатывает скрытие / отображение элемента управления, затем вызывает COleControlSite :: MoveWindow для его перемещения и, наконец, вызывает :: SetWindowPos (с флагами перемещения / показа)замаскировано) для обработки остальных.

Оказавшись внутри COleControlSite :: MoveWindow, вы заметите, что он делает несколько вещей: он вызывает SetExtent, обновляет свой внутренний член m_rect, а затем вызывает SetObjectRects.

Обход этих элементов управления ActiveX с использованием API Win32 напрямую (например, через DeferWindowPos) приводит к тому, что некоторые из этих важных шагов будут пропущены.В зависимости от того, как выстроен ваш код, обычно вы можете справиться с этим самостоятельно.

1 голос
/ 11 апреля 2011

Что такое это элемент управления ActiveX?

Кроме того, учтите, что DeferWindowPos предназначен для позиционирования нескольких окон одновременно. Концепция заключается в том, что вы вводите оператор начала, изменяете несколько позиций окна для нового макета, а затем заканчиваете, чтобы фактически перемещать и применять новые позиции и размеры.

Если вы не обновляете несколько окон, рассмотрите возможность использования SetWindowPos .

Учтите также, что вы можете получать сообщение о перемещении, изменении размера или изменении положения окна во время отсрочки. Чтобы предотвратить это, если это происходит, передайте флаг SWP_NOSENDCHANGING в каждом вызове DeferWindowPos, чтобы он не был отправлен, или обработайте сообщение и очистите все биты в полученной структуре WINDOWPOS, чтобы предотвратить нежелательные изменения.

Также возможен сбой этого вызова ... вы проверяете возвращаемое значение?

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