Why does handling WM_NCCALCSIZE make my window jump?

I have a WPF application that snaps to the edges of the screen (I just installed a .Top or .Left window if you are within 20 pixels from the edge of the screen), but recently I added the code provided by the WPF SDK command to "mess up" the window chrome, and although it works fine ( screenshot ), which causes snapto to unexpectedly move the window (for example: it jumps to the left when it needs to be attached to the bottom)

I narrowed it down to processing WM_NCCALCSIZE ... which is really strange because they basically do nothing, they just say that they are processing it, and return 0.

According to the WM_NCCALCSIZE documentation, this should simply cause the whole window to be treated as a client (without an edge without a client), but somehow it also means that whenever my anchor code moves the window down the screen, it also moves to the left about 134 pixels ... (moving to other edges has similar side effects), and while I hold the mouse to drag it, it flickers back and forth from where it should be. If I comment on the processing of WM_NCCALCSIZE, then the binding will work as it should (but the form does not look right).

I tried everything I could in the WM_NCCALCSIZE handler, but I can’t stop it from jumping to the left ... and, of course, WM_NCCALCSIZE is called only when the window is resized, so I don’t understand how it causes this in the first place!

PS If you really want to see the code, it is already on CodePlex , in two files, look for _ HandleNCCalcSize and OnWindowLocationChanged

+4
source share
2 answers

The reason for this is that processing WM_NCCALCSIZE changes the overall size of the window ... but if you move the window changing its position during WM_MOVE or WM_WINDOWPOSCHANGED (which corresponds to WPF WindowPositionChanged ), it causes another WM_NCCALCSIZE message ...

Making changes during WM_NCCALCSIZE (even just confirming that you have processed the message) causes another call to WM_MOVE ... which puts you in a loop where the FROM part of the message with the position remains unchanged (creating the jump window from where it is started with the position that you correct it during WM_MOVE again and again when it changes after WM_NCCALCSIZE ).

The right way

What you need to do is obey Raymond Chen and handle WM_WINDOWPOSCHANGING instead . This happens before these other messages, and thus they do not interfere with each other!

+4
source

wParam always seems TRUE (1), and lParam is NCCALCSIZE_PARAMS ...

The goal is to do what you said: get the whole window to be a "client", and then use Vista DWM to expand the scope into the client area. I just don’t understand why he was moving so far to the left ...

If I track or stop the HandleNCCalcSize method when I resize the window (while it is on the edge, so the binding is triggered), NCCalcSize is called twice: once where it should be, and then left where it ends.

0
source

Source: https://habr.com/ru/post/1277664/


All Articles