Почему обработка WM_NCCALCSIZE заставляет мое окно прыгать?

У меня есть приложение WPF, которое привязывается к краям экрана (я просто установил .Top или .Left окна, если вы находитесь в пределах 20 пикселей от края экрана), но недавно я добавил код предоставлено командой WPF SDK, чтобы «беспорядок» с окном chrome, и хотя он отлично работает (снимок экрана), из-за этого "snapto" неожиданно перемещает окно (например, он прыгает влево, когда должен быть привязан прямо к низу)

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

Согласно документации WM_NCCALCSIZE, это должно просто привести к тому, что все окно будет рассматриваться как клиент (не имеющее неклиентского края), но каким-то образом это также означает, что всякий раз, когда мой код привязки перемещает окно вниз в нижнюю часть экрана , он также перемещается влево примерно на 134 пикселя ... (перемещение к другим краям имеет аналогичные побочные эффекты), и пока я удерживаю мышь, чтобы перетащить его, он мерцает взад и вперед от того места, где должен быть. Если я прокомментирую обработку WM_NCCALCSIZE, привязка работает так, как должна (но форма выглядит неправильно).

Я пробовал все, что мог, в обработчике WM_NCCALCSIZE, но я не могу остановить его от прыжка влево ... и, конечно же, WM_NCCALCSIZE вызывается только при изменении размера окна, поэтому я не понимаю, как это вызывает это в первую очередь!

P.S. Если вы действительно хотите увидеть код, это уже на CodePlex, в двух файлах ищите _HandleNCCalcSize и OnWindowLocationChanged

Я так и не понял этого, но я определил, что проблема исчезнет, ​​если мы отрегулируем положение окна во время сообщения WM_WINDOWPOSCHANGING вместо события WPF WindowPositionChanged. Итак, обходной путь найден. двигаться дальше по жизни.

Jaykul 13.10.2008 22:30

Что такое wParam и lParam, когда обработчик WM_NCCALCSIZE возвращает 0? В документации говорится: «Если wParam имеет значение ИСТИНА и приложение возвращает ноль, старая клиентская область сохраняется и выравнивается с верхним левым углом новой клиентской области», что похоже на то, что с вами происходит.

jeffm 11.10.2008 02:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
2
4 090
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

WParam всегда кажется TRUE (1), а lParam - это NCCALCSIZE_PARAMS ...

Намерение состоит в том, чтобы сделать именно то, что вы сказали: заставить все окно быть «клиентским», а затем использовать API Vista DWM для расширения фрейма в клиентскую область. Я просто не понимаю, почему он уходит так далеко влево ...

Если я отслеживаю или устанавливаю точку останова для метода HandleNCCalcSize, когда я изменяю размер окна (пока оно находится на краю, поэтому срабатывает привязка), NCCalcSize вызывается дважды: один раз там, где он должен быть, а затем слева, где он заканчивается вверх.

Ответ принят как подходящий

Причина, по которой это происходит, заключается в том, что обработка WM_NCCALCSIZE изменяет общий размер окна ... но если вы перемещаете окно, изменение вашего положения во время WM_MOVE или WM_WINDOWPOSCHANGED (что соответствует событию WPF WindowPositionChanged) вызывает другое сообщение WM_NCCALCSIZE .. .

Внесение изменений во время WM_NCCALCSIZE (даже просто подтверждение того, что вы обработали сообщение) вызывает еще один вызов WM_MOVE ... который помещает вас в цикл, в котором часть "FROM" сообщения с измененной позицией остается прежней (заставляя окно "прыгать" с того места, где он начал с того положения, в которое вы его настраивали во время WM_MOVE, снова и снова, когда он возвращается обратно после WM_NCCALCSIZE).

Правильный путь

Что вам нужно сделать, так это подчиниться Раймонду Чену и вместо этого используйте WM_WINDOWPOSCHANGING. Бывает до эти другие сообщения, и таким образом они не мешают друг другу!

Другие вопросы по теме