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





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. Бывает до эти другие сообщения, и таким образом они не мешают друг другу!
Я так и не понял этого, но я определил, что проблема исчезнет, если мы отрегулируем положение окна во время сообщения WM_WINDOWPOSCHANGING вместо события WPF WindowPositionChanged. Итак, обходной путь найден. двигаться дальше по жизни.