为什么处理WM_NCCALCSIZE导致我的窗口跳转?

时间:2008-10-10 21:45:25

标签: wpf windows winapi pinvoke

我有一个WPF应用程序可以捕捉到屏幕边缘(我只是设置窗口的.Top或.Left,如果你在屏幕边缘的20个像素内),但我最近添加了一些代码provided by the WPF SDK Team使用窗口镀铬“混乱”,虽然它工作得很好(screenshot),但它会导致“snapto”意外地移动窗口(例如:当它应该直接向下移动时,它会跳到左边)底部)

我已经把它缩小到他们对WM_NCCALCSIZE的处理......这真的很奇怪,因为他们基本上什么都不做,他们只是说他们处理它,然后返回0.

根据WM_NCCALCSIZE的文档,这应该只会导致整个窗口被视为客户端(没有非客户端边缘),但不知何故,这也意味着每当我的捕捉代码将窗口移动到底部时在屏幕上,它还向左移动大约134个像素......(移动到其他边缘有类似的副作用),只要我按住鼠标拖动它,它就会从它应该的位置来回闪烁。如果我对WM_NCCALCSIZE处理进行注释,则snap-to按照应有的方式工作(但表单看起来不正确)。

我已经尝试了WM_NCCALCSIZE处理程序中的所有功能,但是我无法阻止它向左跳...当然,只有在窗口大小发生变化时才会调用WM_NCCALCSIZE,所以我不明白它是如何导致这一点的!

P.S。如果您想实际查看代码,已经on CodePlex,则在两个文件中查找_HandleNCCalcSizeOnWindowLocationChanged

2 个答案:

答案 0 :(得分:6)

发生这种情况的原因是处理WM_NCCALCSIZE会改变窗口的整体大小......但如果您移动窗口,请在WM_MOVEWM_WINDOWPOSCHANGED期间更改您的位置(对应于WPF WindowPositionChanged事件)会导致另一条WM_NCCALCSIZE消息...

WM_NCCALCSIZE期间进行更改(即使只是断言你处理了这条消息)会导致另一次调用WM_MOVE ...这会让你进入一个循环,其中positionchanged消息的“FROM”部分保持不变相同(使窗口从开始的位置“跳转”到您在WM_MOVE期间一遍又一遍地调整它的位置,因为它在WM_NCCALCSIZE之后变回。

正确的方式

你要做的就是服从Raymond Chen和handle WM_WINDOWPOSCHANGING instead。它发生之前这些其他消息,这样他们就不会相互干扰!

答案 1 :(得分:0)

wParam似乎总是为TRUE(1)而lParam是NCCALCSIZE_PARAMS ......

目的是完全按照你所说的做法:强制整个窗口为“客户端”,然后使用Vista DWM apis将框架扩展到客户端区域。我只是不明白为什么它向左移动到左边......

如果我跟踪或断开HandleNCCalcSize方法,当我调整窗口大小时(当它在边缘上以便快照触发)时,NCCalcSize会被调用两次:一次应该在哪里,然后向左移动,结束的地方。